轮播图源码

2020-08-11  本文已影响0人  爱吃西瓜的勺子
    <div id="swiper-container" >
        <ul class="swiper-wrapper" ref='swiperWrapper' @touchstart="touchStart" @touchmove="touchMove"  @touchend="touchEnd">
            <li class="swiper-item"><a href=""><img src="~assets/images/swiper/banner1.jpg"></a></li>
            <li class="swiper-item"><a href=""><img src="~assets/images/swiper/banner2.jpg"></a></li>
            <li class="swiper-item"><a href=""><img src="~assets/images/swiper/banner3.jpg"></a></li>
            <li class="swiper-item"><a href=""><img src="~assets/images/swiper/banner4.jpg"></a></li>
            <li class="swiper-item"><a href=""><img src="~assets/images/swiper/banner5.jpg"></a></li>
        </ul>
        <div class="indicator">
            <div class="indicator-item" v-for='(item,index) in swiperItemCount' :key='index' :class="{indicatorActive:(index+1)===currentIndex}"></div>
        </div>
    </div>
</template>


<script>
    
    export default{
        name:"Swiper",
        components:{
            
        },
        props:{
            moveRatio:{
                type:Number,
                default:0.25
            },
            duration:{
                type:Number,
                default:300
            },
            interval:{
                type:Number,
                default:3000
            }
        },
        data(){
            return {
                swiperItemCount:0,
                swiperWidth:0,
                swiperStyle:null,
                playTimer:null,
                currentIndex:1,
                scrolling:false
            }
        },
        mounted(){
            setTimeout(()=>{
                //等待图片加载
                this.handleDom();

                this.startTimer();

            },1000)
        },
        methods:{
            // 操作Dom,加上第一张和最后一张图片。
            handleDom(){
                // 获取要操作的元素
                let swiperWrapper=this.$refs.swiperWrapper;//ul
                let swiperItems=swiperWrapper.querySelectorAll('.swiper-item');//li
                // 保存图片数量
                this.swiperItemCount=swiperItems.length;

                //复制首尾图片并插入ul中。
                //判断图片数量:只有大于一张图片时才设置滑动效果
                if(this.swiperItemCount>1){
                    //复制第一张和最后一张图片
                    let cloneFirst=swiperItems[0].cloneNode(true);
                    let cloneLast=swiperItems[this.swiperItemCount-1].cloneNode(true);

                    //插入图片节点
                    swiperWrapper.appendChild(cloneFirst);
                    swiperWrapper.insertBefore(cloneLast,swiperItems[0]);

                    //获取wrapper宽度(包括border)和设置样式
                    this.swiperWidth=swiperWrapper.offsetWidth;
                    this.swiperStyle=swiperWrapper.style;
                    //初始化 设置当前显示为第一张图片
                    this.swiperStyle.transform=`translate(-${this.swiperWidth}px,0px)`;

                }

            },
            //移动函数
            setTransform(positionX){
                    this.swiperStyle.transform=`translate(${positionX}px,0)`;
                    this.swiperStyle['-webkit-transform']=`translate(${positionX}px,0)`;
                    this.swiperStyle['-ms-transform']=`translate(${positionX}px,0)`;
            },
            // 自动轮播函数
            startTimer(){
                this.playTimer=window.setInterval(()=>{
                    this.currentIndex++;
                    this.scrollPosition(-this.swiperWidth*this.currentIndex);
                },this.interval)
            },
            //清除定时器函数
            stopTimer(){
                window.clearInterval(this.playTimer);
            },
            //touch事件
            touchStart(e){
                // 如果正在滚动,不可以拖动
                if(this.scrolling) return;
                //停止计时器
                this.stopTimer();
                //保存开始滚动的位置(手指的位置)this是指当前组件
                this.startX=e.touches[0].pageX;
            },
            //图片跟随手指移动,但切换图片还是回到原处,需要在松手以后判断
            touchMove(e){
                //拖动过程中手指的位置(每一刻都在变化)
                this.currentX=e.touches[0].pageX;
                //手指拖动的距离
                this.distance=this.currentX-this.startX;
                //获取当前位置
                let currentPosition=-this.currentIndex*this.swiperWidth;
                //计算移动距离
                let moveDistance=currentPosition+this.distance;
                //实时移动
                this.setTransform(moveDistance);
            },
            //手指最大的移动范围就是屏幕的大小,也可以说是一张图片的宽度。
            touchEnd(e){
                //获取拖动的距离绝对值
                let currentMove=Math.abs(this.distance);
                // 获取移动参照距离
                let referDistance=this.moveRatio*this.swiperWidth;
                if(this.distance===0){
                    this.startTimer();
                    return;
                }
                else if(this.distance>0 && currentMove>referDistance){
                    // 如果向右移动距离大于总宽度*0.25,设置应该显示图片的index
                    this.currentIndex--;
                }
                else if(this.distance<0 && currentMove>referDistance){
                    //如果向左移动距离大于总宽度*0.25,向左移动一张图片
                    this.currentIndex++;
                }
                //以上判断主要是确定当前index,然后设置过渡效果
                this.scrollPosition(-this.currentIndex*this.swiperWidth);
                //重新开启定时器
                this.startTimer();
            },
            //确定滚动到什么位置,并设置过渡效果
            scrollPosition(position){
                 //正在滚动时,touch无效。
                 this.scrolling=true;
                 // 设置滚动过渡时间
                 this.swiperStyle.transition='transform '+this.duration+'ms';
                 //调用滚动函数
                 this.setTransform(position);
                 // 此时是有过渡效果了,但是当到达了正确的位置,还需要取消过渡效果
                 //这样手指才能实时拖动。另外还需要判断是否在障眼图片位置。
                 this.setCurrentIndex();//异步函数
                 //滚动完成
                this.scrolling=false;
            },
            setCurrentIndex(){
                // 因为设置了过渡时间,这里要等移动结束再来判断index的值。
                //使用箭头函数,这里的this指向组件
                setTimeout(()=>{
                    // 先取消过渡效果,瞬间切换照片
                    this.swiperStyle.transition='0ms';
                    console.log(this.currentIndex);
                    // 判断index
                    if(this.currentIndex===this.swiperItemCount+1){
                        this.currentIndex=1;
                        this.setTransform(-this.swiperWidth*1)
                    }
                    else if(this.currentIndex===0){
                        this.currentIndex=this.swiperItemCount;
                        this.setTransform(-this.swiperWidth*this.currentIndex);
                    }   

                },this.duration)


            }

        }
    }
</script>

<style scoped>
    #swiper-container{
        width: 100%;
        overflow: hidden;
        position: relative;
    }
    .swiper-wrapper{
        width: 100%;
        display: flex;
    }
    .swiper-item{
        width: 100%;
        flex-shrink:0;
        
    }
    .swiper-item img{
        width: 100%;
        height: 100%;
    }
    .indicator{
        position: absolute;
        bottom: 10px;
        width: 100%;
        display: flex;
        justify-content: center;
    }
    .indicator-item{
        width: 8px;
        height: 8px;
    
        background-color: #fff;
        border-radius: 50%;
        margin:0px 3px;
    }
    .indicatorActive{
        background-color: #ff5777;
    }
</style>
上一篇 下一篇

猜你喜欢

热点阅读