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>
  • 相关阅读:
    Educational Codeforces Round 10 C. Foe Pairs 水题
    Educational Codeforces Round 10 B. z-sort 构造
    CDOJ 1048 Bob's vector 三分
    Educational Codeforces Round 10 A. Gabriel and Caterpillar 模拟
    第14届电子科大初赛民间盗版部分题目题解
    HDU 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数
    HDU 5653 Bomber Man wants to bomb an Array. dp
    HDU 5652 India and China Origins 二分+并查集
    HDU 5651 xiaoxin juju needs help 数学
    HDU 5650 so easy 数学
  • 原文地址:https://www.cnblogs.com/williamwsj/p/13627818.html
Copyright © 2011-2022 走看看