当前位置:   article > 正文

Vue 自定义轮播

Vue 自定义轮播

先看效果图:

 开发可视化大屏的时候想在网上随便找一个,翻了翻都不太满意就手撸了一个,

配置信息如下:

有些属于“预留”功能,目前没有达到理想效果,后续我会在这篇博客里继续完善,

源码如下:

  1. <template>
  2. <div>
  3. <div class="swiper-title">自定义轮播图</div>
  4. <div class="swiper-box">
  5. <!-- 轮播区域 -->
  6. <div :class="[config.column ? 'column-row' : '']" class="swiper">
  7. <div v-for="(item, index) in list" :key="index" :class="[nowInd === index ? 'focus' : '']" class="swiper-item"
  8. :style="{
  9. backgroundImage: `url(${item.url})`,
  10. transition: `all ${nowFlag ? (config.changeTime < config.waitTime ? config.changeTime + 's' : '0.5s') : '0s'}`,
  11. transform: config.column ? `translateX(-${100 * nowInd}%)` : `translateY(-${100 * nowInd}%)`,
  12. }">
  13. <p class="title">文字和图片没有什么关联</p>
  14. <p class="info">图片是河南开封的美景</p>
  15. <p class="name">{{ item.name }}</p>
  16. </div>
  17. </div>
  18. <!-- 指示点 -->
  19. <div v-if="config.spot" class="spot-flex">
  20. <div @click="spotActive(ind)" v-for="ind in list.length - 1" :key="ind"
  21. :class="[nowInd === ind ? 'focus' : '', config.spotStyle ? `spot${config.spotStyle}` : 'spot1']" class="spot">
  22. </div>
  23. </div>
  24. <!-- 左右切换 -->
  25. <img v-if="config.arrow" @click="spotActive('-')"
  26. src="https://img-blog.csdnimg.cn/ae2239969edd48cc803da677dd791865.png" alt="" class="icon left">
  27. <img v-if="config.arrow" @click="spotActive('+')"
  28. src="https://img-blog.csdnimg.cn/46d9862a4c3e42819a79ebd2b84d0d73.png" alt="" class="icon right">
  29. <!-- 控制台 -->
  30. <!-- <div class="operate">
  31. <div class="row">
  32. <span>排列方式:</span>
  33. <input type="radio">
  34. <input type="radio">
  35. <input v-model="config.column" type="text">
  36. </div>
  37. </div> -->
  38. </div>
  39. </div>
  40. </template>
  41. <script>
  42. export default {
  43. name: "Swiper",
  44. data() {
  45. return {
  46. config: {
  47. column: true, // true: 横向排列 false: 纵向排列
  48. changeStyle: 2, // 切换风格 (可选1、2)
  49. changeTime: 1, // 转换时长(秒) 转换时长必须小于等待时长,默认为500毫秒
  50. waitTime: 2, // 等待时长(秒) 等待时长最短为1s
  51. spot: true, // 指示点 true: 显示 false: 隐藏
  52. spotStyle: 1, // 指示点风格 (可选1、2、3)
  53. arrow: false, // 左右切换按钮 true: 显示 false: 隐藏
  54. },
  55. nowInd: 0, // 轮播图当前下标
  56. nowFlag: true, // 过渡控制器
  57. myInt: '', // 轮播图计时器
  58. list: [
  59. { name: '巍峨壮丽连绵不绝的山脉', url: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimagepphcloud.thepaper.cn%2Fpph%2Fimage%2F206%2F104%2F959.jpg&refer=http%3A%2F%2Fimagepphcloud.thepaper.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1663147037&t=19521f70b52350b3d1ad05c57d71dd0e' },
  60. { name: '傍晚的天空和海面的霞光', url: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.dazijia.com%2FUploads%2Fjingdian%2F20210323%2Fy605991b3e31d3.jpg&refer=http%3A%2F%2Fwww.dazijia.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1663147229&t=f32746ac1f21b8e1d243747e9353fa16https://img0.baidu.com/it/u=2725915437,1236608227&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500' },
  61. { name: '峻峭的雪山景色', url: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fphoto.tuchong.com%2F1658968%2Ff%2F149475915.jpg&refer=http%3A%2F%2Fphoto.tuchong.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1663147301&t=1be195b9d22a1307a66fb8e19697fb54' }
  62. ]
  63. }
  64. },
  65. mounted() {
  66. this.list.length > 0 ? this.list.push(this.list[0]) : '';
  67. this.autoInt()
  68. },
  69. methods: {
  70. // 轮播图计时器
  71. autoInt() {
  72. clearInterval(this.myInt)
  73. this.myInt = setInterval(() => {
  74. this.nowInd++
  75. if (this.nowInd > this.list.length - 1) {
  76. this.nowFlag = false;
  77. this.nowInd = 0
  78. setTimeout(() => {
  79. this.nowFlag = true;
  80. this.nowInd++
  81. }, 10)
  82. }
  83. }, this.config.waitTime * 1000 < 1000 ? 1000 : this.config.waitTime * 1000)
  84. },
  85. // 指示点/左右按钮点击
  86. spotActive(ind) {
  87. if (ind === '+') {
  88. this.nowInd < this.list.length - 2 ? this.nowInd++ : this.nowInd = 0
  89. } else if (ind === '-') {
  90. this.nowInd > 0 ? this.nowInd-- : this.nowInd = this.list.length - 2
  91. } else {
  92. this.nowInd = ind;
  93. }
  94. this.autoInt()
  95. },
  96. }
  97. }
  98. </script>
  99. <style lang="scss" scoped>
  100. .swiper-title {
  101. width: 600px;
  102. text-align: center;
  103. line-height: 40px;
  104. font-size: 22px;
  105. font-family: 仿宋;
  106. font-weight: 500;
  107. color: #f7c40b;
  108. }
  109. .column-row {
  110. white-space: nowrap;
  111. .swiper-item {
  112. display: inline-block;
  113. }
  114. }
  115. .swiper-box {
  116. position: relative;
  117. width: 600px;
  118. height: 360px;
  119. .swiper {
  120. width: 100%;
  121. height: 100%;
  122. overflow: hidden;
  123. .swiper-item {
  124. width: 100%;
  125. height: 100%;
  126. background: no-repeat center;
  127. background-size: cover;
  128. overflow: hidden;
  129. .title,
  130. .info,
  131. .name {
  132. transform: translateX(-100%)
  133. }
  134. }
  135. .focus {
  136. .title,
  137. .info,
  138. .name {
  139. transform: translateX(20px);
  140. }
  141. .title {
  142. transition: all .6s .3s;
  143. }
  144. .info {
  145. transition: all .6s .5s;
  146. }
  147. .name {
  148. transition: all .6s .7s;
  149. }
  150. }
  151. }
  152. .icon {
  153. position: absolute;
  154. top: 0;
  155. bottom: 0;
  156. margin: auto;
  157. width: 30px;
  158. height: 30px;
  159. border-radius: 50%;
  160. cursor: pointer;
  161. }
  162. .left {
  163. left: 0;
  164. }
  165. .right {
  166. right: 0;
  167. }
  168. .spot-flex {
  169. position: absolute;
  170. left: 0;
  171. right: 0;
  172. bottom: -20px;
  173. margin: auto;
  174. display: flex;
  175. justify-content: center;
  176. align-items: center;
  177. .spot1 {
  178. width: 30px;
  179. height: 8px;
  180. margin: 0 10px;
  181. border-radius: 4px;
  182. background-color: pink;
  183. transition: all .6s;
  184. cursor: pointer;
  185. }
  186. .spot2 {
  187. width: 6px;
  188. height: 6px;
  189. margin: 0 10px;
  190. border: 2px solid #acd6f3;
  191. transform: rotate(45deg);
  192. transition: all .6s;
  193. cursor: pointer;
  194. }
  195. .spot3 {
  196. width: 6px;
  197. height: 6px;
  198. margin: 0 10px;
  199. border-radius: 3px;
  200. box-shadow: 0px 0px 6px 3px #acd6f3;
  201. transition: all .6s;
  202. cursor: pointer;
  203. }
  204. .focus {
  205. background-color: skyblue;
  206. }
  207. }
  208. }
  209. .operate {
  210. margin-left: 40px;
  211. .row {
  212. display: flex;
  213. align-items: center;
  214. font-size: 14px;
  215. }
  216. }
  217. </style>

组件开发的比较潦草,后续会进行迭代和完善,继续在这篇文章里进行更新。

设计思路如下:

划分标题、轮播区、指示点三块,在轮播区使用 display: inline-block; ​使子元素横向排列,

此时​限制父元素的宽度,子元素会自动换行,使用 white-space: nowrap; 则强制不换行。

使用动态样式的写法,判断column 的属性值,以此来实现横向或纵向排列。

使用计时器控制变量 nowInd 变化,当nowInd 发生改变会影响轮播图上的判断条件,进而控制轮播运动

根据config.column 的值,判断是进行左右移动 还是上下移动,用transition 来动态控制过渡效果的有无。

文字的滑动效果来自于 css 动画,代码如下:

  1. .focus {
  2. .title,.info,.name {
  3. transform: translateX(20px);
  4. }
  5. .title {
  6. transition: all .6s .3s;
  7. }
  8. .info {
  9. transition: all .6s .5s;
  10. }
  11. .name {
  12. transition: all .6s .7s;
  13. }
  14. }

通过nowInd 是否等于当前子元素的下标,以此来断定是否聚焦了当前的子元素,当子元素满足条件拥有.focus 时,子元素向右移动,给不同的延迟时间,以此实现波浪化。

三种指示点共用同一套动画,样式也进行和封装和复用,需要别的款式可以仿照我现在的代码进行更改。

这里为了高度复用性,使用的并不是img 轮播,而是div 区域轮播,以背景图的形式体现

可以根据不同的需求更改或隐藏背景图,在div 里进行自定义排版。

暂时就讲到这里了,后续会在这篇文章的底部继续更新该组件,感兴趣的话可以收藏一下,see you

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/251117
推荐阅读
相关标签
  

闽ICP备14008679号