e-swiper.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <template>
  2. <!-- 轮播图 -->
  3. <view class="Swiper-mfw-index-box">
  4. <view class="Swiper-mfw-index Swiper-box" :class="[dotPosition]">
  5. <swiper
  6. class="Swiper-mfw"
  7. :style="{ height: height }"
  8. :circular="true"
  9. :indicator-dots="false"
  10. :autoplay="autoplay"
  11. :interval="3000"
  12. :duration="1000"
  13. :current="currentIndex"
  14. :disable-touch="disable_touch"
  15. @change="change"
  16. >
  17. <!-- 只需要前5条数据 -->
  18. <swiper-item class="swiper-mfw-item" v-if="index <= (dotPosition == 'right' ? 3 : 4)" v-for="(item, index) in list" :key="index">
  19. <!-- /*
  20. 1. 这里不需要用api控制暂停视频
  21. 2. 因为video标签上加了v-if="current==index"
  22. 3. 当current == index时才会创建视频组件
  23. 4. 否current != index则就销毁视频
  24. */ -->
  25. <!-- 如果有视频,则显示视频-->
  26. <template v-if="item.mp4 && current == index">
  27. <video
  28. class="ImageVideo"
  29. :id="'ImageVideo' + index"
  30. :ref="'ImageVideo' + index"
  31. :src="item.mp4"
  32. :loop="true"
  33. :muted="false"
  34. :autoplay="current == index ? true : false"
  35. :controls="false"
  36. :show-fullscreen-btn="false"
  37. :show-play-btn="false"
  38. :enable-progress-gesture="false"
  39. :play-strategy="0"
  40. :poster="item.image || item.src"
  41. ></video>
  42. </template>
  43. <!-- 否则显示图片 -->
  44. <image v-else :src="item.image || item.src" class="Image" mode="aspectFill" @click.stop="$emit('on-click', item)"></image>
  45. </swiper-item>
  46. </swiper>
  47. <!-- 指示器 [Top] -->
  48. <view v-if="useTop" class="Swiper-indicator-box indicator-Top-box">
  49. <!-- Top顶部 [今日首推-盒子] -->
  50. <view class="Top-date-hot">
  51. <view class="left-date-ri">
  52. <text class="date-ri-text text">{{ date.month }}</text>
  53. </view>
  54. <view class="conter-date-nianyue">
  55. <view class="left-width-bgcolor"></view>
  56. <view class="right-date-nianyue">
  57. <text class="Top-yue-usa text">{{ date.monthEn }}</text>
  58. <text class="Bottom-nian text">{{ date.year }}</text>
  59. </view>
  60. </view>
  61. <view class="right-hot-ttf">
  62. <text class="text hot-text">{{ title }}</text>
  63. </view>
  64. </view>
  65. </view>
  66. <!-- 指示器 标题区域 -->
  67. <view v-if="useTitle" class="Swiper-indicator-Top" :class="{ 'no-dot': !useDot }">
  68. <block v-for="(item, index) in list" :key="index">
  69. <view v-if="currentIndex == index" class="Top-item" :class="current == index ? 'current' : 'no'">
  70. <!-- 如果存在视频,则显示“视频预览”提示 -->
  71. <view v-if="item.mp4" class="Top-ImageVideo">
  72. <!-- icon图标 -->
  73. <view class="Icons">
  74. <!-- 播放按钮图标 -->
  75. <text class="iconfont icon-caret-right"></text>
  76. </view>
  77. <text class="text ImageVideo-text app-ttf">视频预览</text>
  78. </view>
  79. <!-- 标题 -->
  80. <view class="Top-Title">
  81. <text class="text title-text">{{ item.title }}</text>
  82. </view>
  83. <!-- 用户信息 -->
  84. <view class="Bottom-UserInfo">
  85. <!-- 头像 -->
  86. <view class="UserImage-box"><image :src="item.avatar" class="Image" mode="aspectFill"></image></view>
  87. <!-- 用户名 -->
  88. <view class="textbox UserName-box">
  89. <text class="text UserInfo">{{ item.nickname }}</text>
  90. </view>
  91. <view v-if="item.createTime" class="jiange-box"><text class="text jiange-text"></text></view>
  92. <view v-if="item.createTime" class="textbox UserGPS-box">
  93. <text class="text UserInfo">发布于 {{ item.createTime }}</text>
  94. </view>
  95. <view v-if="item.address" class="jiange-box"><text class="text jiange-text">·</text></view>
  96. <view v-if="item.address" class="textbox UserGPS-box">
  97. <text class="text UserInfo">{{ item.address }}</text>
  98. </view>
  99. </view>
  100. </view>
  101. </block>
  102. </view>
  103. <!-- 指示器 [左边图片列表+右边按钮] -->
  104. <view v-if="useDot" class="Swiper-indicator-Bottom">
  105. <!-- 左边 -->
  106. <view class="Bottom-left-Imagelist">
  107. <block v-for="(item, index) in list" :key="index">
  108. <view
  109. class="Bottom-item"
  110. v-if="Number(index) <= (dotPosition == 'right' ? 3 : 4)"
  111. :class="currentIndex == index ? 'current' : 'no'"
  112. @click="SwiperIndTap(index)"
  113. >
  114. <image :src="item.image || item.src" class="Image" mode="aspectFill"></image>
  115. </view>
  116. </block>
  117. </view>
  118. <!-- 右边 -->
  119. <view class="Bottom-right-lili-btn">
  120. <view class="Bottom-item is-more">
  121. <view class="more" @click.stop="$emit('on-more')">
  122. MORE
  123. <text class="iconfont icon-caret-right"></text>
  124. </view>
  125. <text class="left text indicator-text">更多推荐</text>
  126. </view>
  127. </view>
  128. </view>
  129. </view>
  130. </view>
  131. </template>
  132. <script>
  133. export default {
  134. name: 'e-swiper',
  135. props: {
  136. title: {
  137. type: String,
  138. default: ''
  139. },
  140. height: {
  141. type: String,
  142. default: '450rpx'
  143. },
  144. dotPosition: {
  145. type: String,
  146. default: 'bottom'
  147. },
  148. useTop: {
  149. type: Boolean,
  150. default: true
  151. },
  152. useDot: {
  153. type: Boolean,
  154. default: true
  155. },
  156. useTitle: {
  157. type: Boolean,
  158. default: true
  159. },
  160. useUser: {
  161. type: Boolean,
  162. default: true
  163. },
  164. // 轮播图 数据列表
  165. list: {
  166. type: Array,
  167. default: () => []
  168. },
  169. // 当前选中的项(指示器坐标位置)
  170. current: {
  171. type: Number,
  172. default: 0
  173. },
  174. // 是否自动轮播
  175. autoplay: {
  176. type: Boolean,
  177. default: false
  178. }
  179. },
  180. data() {
  181. return {
  182. // 是否禁止用户 touch 操作
  183. currentIndex: 0,
  184. disable_touch: false, //touch 用户划动引起swiper变化。
  185. date: {
  186. year: '-',
  187. monthEn: '-',
  188. month: '-'
  189. }
  190. };
  191. },
  192. created() {
  193. this.currentIndex = this.current;
  194. const date = new Date();
  195. //将月份名称存储在数组中
  196. const monthArray = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
  197. this.date.year = date.getFullYear();
  198. let month = date.getMonth() + 1;
  199. this.date.month = month < 10 ? '0' + month : month;
  200. this.date.monthEn = monthArray[date.getMonth()].toUpperCase();
  201. },
  202. methods: {
  203. // current 改变时会触发 change 事件,event.detail = {current: current, source: source}
  204. change(e) {
  205. let { current, source } = e.detail;
  206. //只有页面自动切换,手动切换时才轮播,其他不允许
  207. if (source === 'autoplay' || source === 'touch') {
  208. let event = {
  209. current: current
  210. };
  211. this.currentIndex = current;
  212. this.$emit('change', event);
  213. }
  214. },
  215. // 手动点击了指示器[小图模式]
  216. SwiperIndTap(e) {
  217. let index = e;
  218. let event = {
  219. current: index
  220. };
  221. this.currentIndex = index;
  222. this.$emit('change', event);
  223. }
  224. }
  225. };
  226. </script>
  227. <style lang="scss" scoped>
  228. @import './e-swiper.scss';
  229. </style>