specialBanner.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <template>
  2. <div class="banner-container">
  3. <swiper :style="{width: '100vw', height: '410rpx'}"
  4. :indicator-dots="swiperConfig.indicatorDots"
  5. :indicator-color="swiperConfig.indicatorColor"
  6. :indicator-active-color="swiperConfig.indicatorActiveColor"
  7. :autoplay="swiperConfig.autoplay"
  8. :interval="swiperConfig.interval"
  9. :duration="swiperConfig.duration"
  10. :circular="swiperConfig.circular"
  11. :previous-margin="swiperConfig.previousMargin"
  12. :next-margin="swiperConfig.nextMargin"
  13. @change="swiperChange"
  14. @animationfinish="animationfinish">
  15. <swiper-item v-for="(item, i) in bannerList" :key="i">
  16. <!-- 1.当前展示为第1项时,bannerList最后一项和第二项的justifyContent值分别为flex-end和flex-start,其余项值为center -->
  17. <!-- 2.当前展示为最后一项时,bannerList倒数第2项和第1项的justifyContent值分别为flex-end和flex-start,其余项值为center -->
  18. <!-- 3.当前展示为其他项(非第1和最后1项)时,bannerList当前项的前1项和后1项的justifyContent值分别为flex-end和flex-start,其余项值为center -->
  19. <!-- 4.padding值也需要根据不同项设定不同值,但理同justifyContent -->
  20. <div class="image-container"
  21. :class="[curIndex===0?((i===listLen-1)?'item-left':(i===1?'item-right':'item-center')):(curIndex===listLen-1?(i===0?'item-right':(i===listLen-2?'item-left':'item-center')):(i===curIndex-1?'item-left':(i===curIndex+1?'item-right':'item-center')))]">
  22. <image :src="item.picture"
  23. class="slide-image"
  24. :style="{
  25. transform: curIndex===i?'scale(' + scaleX + ',' + scaleY + ')':'scale(1,1)',
  26. transitionDuration: '.3s',
  27. transitionTimingFunction: 'ease'
  28. }"
  29. @click="getBannerDetail(i)"/>
  30. </div>
  31. </swiper-item>
  32. </swiper>
  33. <div class="desc-wrap" :class="[isDescAnimating?'hideAndShowDesc':'']">
  34. <div class="title">{{bannerList[descIndex].title}}</div>
  35. <div class="desc">{{bannerList[descIndex].description}}</div>
  36. </div>
  37. </div>
  38. </template>
  39. <script>
  40. export default {
  41. props: {
  42. bannerList: {
  43. type: Array,
  44. default () {
  45. return []
  46. }
  47. },
  48. swiperConfig: {
  49. type: Object,
  50. default () {
  51. return {
  52. indicatorDots: true,
  53. indicatorColor: 'rgba(255, 255, 255, .4)',
  54. indicatorActiveColor: 'rgba(255, 255, 255, 1)',
  55. autoplay: false,
  56. interval: 3000,
  57. duration: 300,
  58. circular: true,
  59. previousMargin: '58rpx',
  60. nextMargin: '58rpx'
  61. }
  62. }
  63. },
  64. scaleX: {
  65. type: String,
  66. default: (634 / 550).toFixed(4)
  67. },
  68. scaleY: {
  69. type: String,
  70. default: (378 / 328).toFixed(4)
  71. }
  72. },
  73. computed:{
  74. listLen () {
  75. return this.bannerList.length
  76. }
  77. },
  78. data () {
  79. return {
  80. curIndex: 0,
  81. descIndex: 0,
  82. isDescAnimating: false
  83. }
  84. },
  85. methods: {
  86. swiperChange (e) {
  87. const that = this
  88. this.curIndex = e.mp.detail.current
  89. this.isDescAnimating = true
  90. let timer = setTimeout(function () {
  91. that.descIndex = e.mp.detail.current
  92. clearTimeout(timer)
  93. }, 150)
  94. },
  95. animationfinish (e) {
  96. this.isDescAnimating = false
  97. },
  98. getBannerDetail (index) {
  99. uni.showLoading({
  100. title: '将前往详情页面',
  101. duration: 2000,
  102. mask: true
  103. })
  104. }
  105. }
  106. }
  107. </script>
  108. <style lang="scss" scoped>
  109. .banner-container {
  110. width: 100vw;
  111. height: 524rpx;
  112. .image-container {
  113. box-sizing: border-box;
  114. width: 100%;
  115. height: 100%;
  116. display: flex;
  117. .slide-image {
  118. width: 550rpx;
  119. height: 328rpx;
  120. z-index: 200;
  121. }
  122. }
  123. .item-left {
  124. justify-content: flex-end;
  125. padding: 56rpx 26rpx 0 0;
  126. }
  127. .item-right {
  128. justify-content: flex-start;
  129. padding: 56rpx 0 0 26rpx;
  130. }
  131. .item-center {
  132. justify-content: center;
  133. padding: 56rpx 0 0 0;
  134. }
  135. .desc-wrap {
  136. box-sizing: border-box;
  137. width: 100%;
  138. height: 98rpx;
  139. padding: 24rpx 66rpx 0;
  140. .title {
  141. width: 100%;
  142. height: 42rpx;
  143. line-height: 42rpx;
  144. color: #222222;
  145. font-size: 30rpx;
  146. font-family: 'PingFangTC-Regular';
  147. font-weight: 600;
  148. text-align: left;
  149. }
  150. .desc {
  151. margin-top: 4rpx;
  152. width: 100%;
  153. height: 34rpx;
  154. line-height: 34rpx;
  155. color: #999999;
  156. font-size: 24rpx;
  157. font-family: 'PingFangTC-Regular';
  158. text-align: left;
  159. }
  160. }
  161. @keyframes descAnimation {
  162. 0% {
  163. opacity: 1;
  164. }
  165. 25% {
  166. opacity: .5;
  167. }
  168. 50% {
  169. opacity: 0;
  170. }
  171. 75% {
  172. opacity: .5;
  173. }
  174. 100% {
  175. opacity: 1;
  176. }
  177. }
  178. @-webkit-keyframes descAnimation {
  179. 0% {
  180. opacity: 1;
  181. }
  182. 25% {
  183. opacity: .5;
  184. }
  185. 50% {
  186. opacity: 0;
  187. }
  188. 75% {
  189. opacity: .5;
  190. }
  191. 100% {
  192. opacity: 1;
  193. }
  194. }
  195. .hideAndShowDesc {
  196. animation: descAnimation .3s ease 1;
  197. -webkit-animation: descAnimation .3s ease 1;
  198. }
  199. }
  200. </style>