zoukankan      html  css  js  c++  java
  • vue轮播图(可随父元素高宽自适应)

    使用vue的transition动画,匹配移动端的左右触摸滑动和隐藏左右按钮等等。

    效果如下所示:

    整个组件的代码如下所示:

    <template>
        <div class="slider-container" >
            <div class="img-slider-touchwindow" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
                <transition name="img-slider" tag="div" :enter-class="enterClass" :leave-active-class="leaveActiveClass" :enter-active-class="enterActiveClass">
                    <div v-for="(item,i) in imgList" :key="i" v-if="i === (currentIndex-1)" class="img-slider-bar" >
                        <img :src="item.img" alt="">
                    </div>
                </transition>
            </div>
    
            <ul ref="imgSliderDirection" class="img-slider-direction">
                <li class="img-slider-direction-left" @click="pre()">
                <svg class="img-slider-direction-left-icon" width="30px" height="30.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M481.233 904c8.189 0 16.379-3.124 22.628-9.372 12.496-12.497 12.496-32.759 0-45.256L166.488 512l337.373-337.373c12.496-12.497 12.496-32.758 0-45.255-12.498-12.497-32.758-12.497-45.256 0l-360 360c-12.496 12.497-12.496 32.758 0 45.255l360 360c6.249 6.249 14.439 9.373 22.628 9.373z"  /></svg>
                </li>
                <li class="img-slider-direction-right" @click="next()">
                <svg class="img-slider-direction-right-icon" width="30px" height="30.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M557.179 904c-8.189 0-16.379-3.124-22.628-9.372-12.496-12.497-12.496-32.759 0-45.256L871.924 512 534.551 174.627c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0l360 360c12.496 12.497 12.496 32.758 0 45.255l-360 360c-6.249 6.249-14.439 9.373-22.628 9.373z"  /></svg>
                </li>
            </ul>
    
             <ul class="img-slider-dots">
                <li v-for="(dot, i) in imgList" :key="i"
                :class="{dotted: i === (currentIndex-1)}"
                @click = jump(i+1)
                >
            </li>
          </ul>
        </div>
    </template>
    
    <script>
        //参考 https://cn.vuejs.org/v2/guide/transitions.html   
        export default {
            props:{
                //initInterval:每张图片轮播的间隔时间,默认3秒,单位秒
                initInterval:{
                    type:Number,
                    default:3 
                },
                //imgList:需要轮播的图片集合
                imgList:{
                  type:Array,
                  default:function(){
                      return [
                            {
                                img:'/static/images/hdimg/20120814204658.jpg'
                            },
                            {
                                img:'/static/images/hdimg/20200827163501.jpg'
                            },
                            {
                                img:'/static/images/hdimg/20200827163502.jpg'
                            },
                            {
                                img:'/static/images/hdimg/20120814204733.jpg'
                            },
                            {
                                img:'/static/images/hdimg/20200827163503.jpg'
                            },
                        ]
                  }
                }
            },
            data(){
                return {                
                    currentIndex:1,//当前显示图片的位置
                    direction:-1,  //-1从左向右,1从右向左
                    timer:null,    //轮播的定时器
                    flag: true,    // 节流阀 防止快速滑动
                    startX: 0,     // 手指开始触摸位置
                    moveX: 0,      // 手指移动距离
                }
            },
            computed: {
                enterClass:function(){
                    return this.direction===-1?"img-slider-enter-left-to-right":"img-slider-enter-right-to-left";
                },
                leaveActiveClass:function(){
                    return this.direction===-1?"img-slider-leave-active-left-to-right":"img-slider-leave-active-right-to-left";
                },
                enterActiveClass:function(){
                    return "img-slider-enter-active-all";
                },
                interval:function(){
                    return this.initInterval*1000;
                },
                isMobile(){
                    return navigator.userAgent.toLowerCase().match(/(ipod|ipad|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i) != null;
                }
            },
            methods:{
                pre(){
                    var currentIndex=(this.currentIndex-1)<=0?this.imgList.length:(this.currentIndex-1)
                    this.animate(currentIndex,1);
                },
                next(){
                    var currentIndex=(this.currentIndex+1)>this.imgList.length?1:(this.currentIndex+1)
                    this.animate(currentIndex,-1);
                },
                jump(idx){
                    this.animate(idx,this.currentIndex<idx?-1:1);
                },
                animate(index, imgDirection) {
                    if (this.timer) {
                        window.clearInterval(this.timer);
                        this.timer = null ;
                    }
                   
                    this.direction=imgDirection;  
                    this.currentIndex=index;            
    
                    this.timer = window.setInterval(() => {  
                        this.currentIndex=this.currentIndex+1>this.imgList.length?1:(this.currentIndex+1);
                        this.direction=-1;
                    }, this.interval);
                },
                play() {
                     if (this.timer) {
                        window.clearInterval(this.timer)
                        this.timer = null
                    }
                    this.timer = window.setInterval(() => {  
                        this.currentIndex=this.currentIndex+1>this.imgList.length?1:(this.currentIndex+1);
                        this.animate(this.currentIndex,this.direction);
                    }, this.interval);
                },
                stop() {
                    window.clearInterval(this.timer)
                    this.timer = null
                },
                init() {
                    this.play()
                    window.onblur = function() { this.stop() }.bind(this)
                    window.onfocus = function() { this.play() }.bind(this)
                },
                touchstart(event){// 手指开始触摸事件
                    window.clearInterval(this.timer);  // 关闭自动轮播
                    this.startX = event.targetTouches[0].clientX; // 获取开始触摸位置                
                },
                touchmove(event){// 手指开始移动
                    this.moveX = event.targetTouches[0].clientX - this.startX;  // 手指移动位置    
                },
                touchend(event){// 结束触摸       
                    if(this.moveX>10)
                        this.pre();
                    else if(this.moveX<-10)
                        this.next();               
                }            
            },
            mounted(){
                this.init();
                this.$nextTick(function(){
                    //console.log(this.isMobile);
                    if(this.isMobile){
                        this.$refs.imgSliderDirection.style.display="none";
                    }
                });
            }
        }
    </script>
    
    <style lang="scss" scoped>
    
    .slider-container{
        100%;
        height:100%;
        overflow: hidden;
        margin:0 auto;
        position: relative;
    }
    .img-slider-touchwindow{
        100%;
        height:100%;
        position: relative;
    }
    .img-slider-bar{
        100%;
        height:100%;
        position:absolute;
        top:0;
        left:0;    
    }
    .img-slider-bar img{
        100%;
        height:100%;    
        object-fit: cover;
    }
    .img-slider-enter-active-all{
      transition: all 1s; 
    }
    .img-slider-leave-active-left-to-right {
      transition: all 1s;
      transform: translateX(-100%);
    }
    .img-slider-leave-active-right-to-left {
      transition: all 1s;
      transform: translateX(100%);
    }
    .img-slider-enter-left-to-right {
      transform: translateX(100%);
    }
    .img-slider-enter-right-to-left {
      transform: translateX(-100%);
    }
    ol,ul{
      list-style: none;
    }
    .img-slider-direction-left, .img-slider-direction-right{
      position:absolute;
      top:50%;
      transform:translateY(-50%);
      50px;
      height:50px;
      background-color:rgba(0,0,0,.3);
      border-radius:50%;
      cursor:pointer;
    }
    .img-slider-direction-left{
      left:3%;
      padding-left:12px;
      padding-top:10px;
    }
    .img-slider-direction-right{
      right:3%;
      padding-right:12px;
      padding-top:10px;
    }
    
    .img-slider-dots{
      position:absolute;
      bottom:10px;
      left:50%;
      transform:translateX(-50%);
    }
    .img-slider-dots li{
      display:inline-block;
      15px;
      height:15px;
      margin:0 3px;
      border:1px solid white;
      border-radius:50%;
      background-color:#333;
      cursor:pointer;
    }
    .img-slider-dots .dotted{
      background-color:orange;
    }
    
    </style>
  • 相关阅读:
    [Bzoj2120]数颜色
    [Bzoj2049][Sdoi2008]Cave 洞穴勘测
    [2019上海网络赛F题]Rhyme scheme
    [2019上海网络赛J题]Stone game
    Codeforces Round #688 (Div. 2) C
    Educational Codeforces Round 99 (Rated for Div. 2) D
    Educational Codeforces Round 99 (Rated for Div. 2) B
    Codeforces Round #685 (Div. 2) D
    Codeforces Round #685 (Div. 2) C
    Codeforces Round #685 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/williamwsj/p/13627818.html
Copyright © 2011-2022 走看看