Vue实现带两个方向过渡效果的轮播图

Posted hans774882968

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue实现带两个方向过渡效果的轮播图相关的知识,希望对你有一定的参考价值。

网上有许多轮播图案例,但只有极少数做了两个方向的滑动过渡效果。而我就是其中一个!所以来关注hans774882968,看技术干货!

先看效果图

html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>轮播图图片切换</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <link rel="stylesheet" type="text/css" href = "./index.css" />
  <style type="text/css"></style>
  <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
  <script src="https://cdn.staticfile.org/vue/2.5.2/vue.min.js"></script>
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
  <main id="app" class="container">
    <div class="img-wrap">
      <div class="wrap" v-for="(item,idx) in imgs" :key="idx">
        <transition :name="imgAnime">
          <img v-show="curIdx === idx" :key="item.idx" :src="item.src" />
        </transition>
      </div>
      <div class="left-btn" @click="imgChange(-1)"><</div>
      <div class="right-btn" @click="imgChange(1)">></div>
    </div>
  </main>
  <script src="./index.js"></script>
</body>
</html>

.img-wrap是整个轮播图组件的根元素。.wrap则是被绝对定位控制在我们期望的位置。

若干个图片,只有一个能显示,其他的应该display: none;所以用v-show和curIdx来控制。

CSS

body{
  margin: 0;
  background-color: wheat;
}

div{
  box-sizing: border-box;
}

.container{
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.img-wrap{
  width: 600px;
  height: 225px;
  position: relative;
  overflow: hidden;/* 隐藏突出部分 */
}

.wrap{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

img{
  width: 100%;
  height: 100%;
}
/* right=左to右 */
.img-play-right-enter-active,.img-play-right-leave-active,
.img-play-left-enter-active,.img-play-left-leave-active{
  transition: all .6s;
}
/* 左to右和右to左的类名呈现一个reverse的关系 */
.img-play-right-enter,.img-play-left-leave-to {
  transform: translateX(100%);
}

.img-play-right-enter-to,.img-play-left-leave{
  transform: translateX(0);
}
.img-play-right-leave,.img-play-left-enter-to{
  transform: translateX(0);
}
.img-play-right-leave-to,.img-play-left-enter{
  transform: translateX(-100%);
}

.left-btn,.right-btn{
  position: absolute;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background-color: rgba(0,0,0,.2);
  top: 50%;
  margin-top: -12px;
  font-size: 20px;
  font-weight: bold;
  color: white;
  line-height: 29px;
  text-align: center;
  user-select: none;
  cursor: pointer;
}

.left-btn{
  left: 16px;
}

.right-btn{
  right: 16px;
}

.wrap被绝对定位控制在-100%、0%和100%(相对.img-wrap的宽度)的位置,然后用translateX()和vue提供的<transition>来控制进入阶段(enter阶段)的起点、终点和离开阶段(leave阶段)的起点、终点。详细写法可以看代码的注释。

.img-wrapoverflow: hidden;来隐藏.wrap的突出部分。

但还有一个问题没解决:怎么实现两个方向都有动画?参考https://www.cnblogs.com/gsgs/p/6698494.html,我们发现,直接动态修改<transition>的name属性即可(注意,vue官方文档没有提到这个)。

.left-btn.right-btn用绝对定位跑到期望的位置,然后进行一些样式上的处理,都是基本操作了。

JS

"use strict";

function main() {
  let vm = new Vue({
    el: '#app',
    data() {
      return {
        imgs: [
          {
            idx: 0,
            src: './imgs/1.jfif'
          },
          {
            idx: 1,
            src: './imgs/2.jfif'
          },
          {
            idx: 2,
            src: './imgs/3.jfif'
          }
        ],
        curIdx: 0,
        timer: null,
        imgAnime: 'img-play-right'
        /* transition的name属性也可以动态变化~这一事实来自:
         * https://www.cnblogs.com/gsgs/p/6698494.html */
      }
    },
    mounted(){
      this.newTimer()
    },
    methods: {
      newTimer(){
        this.timer = setInterval(() => {
          this.imgChange(1)
        },3000)
      },
      stopTimer(){
        clearInterval(this.timer)
      },
      imgChange(v) {
        this.imgAnime = v === -1 ? 'img-play-left' : 'img-play-right'
        let l = this.imgs.length
        this.curIdx = ((this.curIdx + v) % l + l) % l
        this.stopTimer()
        this.newTimer()
      }
    }
  });
}

$(document).ready(main);

这里为了方便,对于没点击按钮时,自动放下一张图片的逻辑,也用this.imgChange(1)实现了。这就导致每次setInterval调用1次就被清空。反正不影响效果,不想改代码了。

it is not bug, it is feature!

以上是关于Vue实现带两个方向过渡效果的轮播图的主要内容,如果未能解决你的问题,请参考以下文章

用vue写一个仿简书的轮播图

用html+css怎么写出带按钮的轮播图?

用jquery实现带左右按键的轮播图

用vue写一个轮播图效果

js实现效果:循环轮播图

实现比较简单的轮播图效果