specialBanner.vue 4.5 KB

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