轮播图源码
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>