基本结构
代码语言:javascript复制<div class="focus">
<ul>
<!-- 最前面为最后一张 -->
<li><img src="./images/three.jpg" alt=""></li>
<li><img src="./images/one.jpg" alt=""></li>
<li><img src="./images/two.jpg" alt=""></li>
<li><img src="./images/three.jpg" alt=""></li>
<!-- 最后一张==第一张 -->
<li><img src="./images/one.jpg" alt=""></li>
</ul>
<ol>
<li class="current"></li>
<li></li>
<li></li>
</ol>
</div>
基本css
代码语言:javascript复制/* 轮播图 */
.focus{
position: relative;
padding-top: 44px;
overflow:hidden;//溢出的图片隐藏
}
.focus ul{
width: 500%;
overflow:hidden;/*清除浮动*/
margin-left:-100%;/*默认展示第一张图片而不是克隆的最后一张图片*/
}
.focus ul li{
width: 20% ;/*防止图片变大5倍*/
float:left;
}
.focus img{
width: 100%;
height:1.333333rem
}
/*园点*/
.focus ol {
position: absolute;
bottom: 5px;
right: 5px;
}
.focus ol li{
width: 5px;
height: 5px;
background-color: #fff;
display:inline-block;
border-radius: 5px;
}
/*当前高亮*/
.focus ol li.current{
width: 15px;
}
为了使ul装下5张图片我们将其宽度设置为500%,但这样会造成图片放大5倍,因此我们为img的父元素li设置20%的宽度占ul的五分之一,这时候图片就显示正常了
自动播放
利用索引号与宽度实现每次要滚动的距离 每次移动的距离等于当前索引*宽度 js代码
代码语言:javascript复制window.addEventListener('load',function(){
//1. 获取元素
var focus = document.querySelector('.focus');
var ul = focus.children[0];
//2.获取focus的宽度
var w = focus.offsetWidth;
//3.定时器开启
var index = 0;
var timer = setInterval(function(){
index
//移动距离
var translateX = -index*w
ul.style.transition = 'all .3s'
ul.style.transform = 'translate(' translateX 'px)'
},2000);
})
到此实现自动轮播效果,接下来需要实现无缝滚动
无缝滚动
原理很简单,当滚动到最后一张图片(克隆的第一张图片)的时候,我们快速跳到第一张图片的位置继续滚动即可
不过需要注意的是我们使用了过渡效果,如果我们直接跳转会有过渡效果这样用户会很明显的感觉到,我们要做的是用户察觉不出来图片已经跳到了第一张
解决办法是等过渡完成后在进行判断当前索引是不是最后一个,如果是则跳转到第一张图片 通过 过渡完成事件transitionend
代码实现
...
//过渡完成后判断是否到最后一张图片
ul.addEventListener('transitionend',function(){
// 无缝滚动实现
if(index>=3){
index=0
ul.style.transition = 'none'/*跳转去掉过渡效果 */
/*按照最新的索引移动位置 也就是快速定位到真正的第一张图片*/
/*在从第一张图片的位置继续轮播 */
var translateX = -index*w
ul.style.transform = 'translateX(' translateX 'px)'
}
})
})
此时无缝滚动完成一半了
我们还有一种情况,当用户在第一张图片向右边拖到图片时,此时应该看到最后一张,并且由最后一张继续轮播,我们可以先写一部分逻辑和上面类似
代码语言:javascript复制...
ul.addEventListener('transitionend',function(){
// 无缝滚动实现
if(index>=3){
index=0
ul.style.transition = 'none'/*跳转去掉过渡效果 */
/*按照最新的索引移动位置 也就是快速定位到真正的第一张图片*/
/*在从第一张图片的位置继续轮播 */
var translateX = -index*w
ul.style.transform = 'translateX(' translateX 'px)'
}else if(index < 0){
index=2/*即将跳转到克隆的第一张图片 */
ul.style.transition = 'none'/*跳转去掉过渡效果 */
var translateX = -index*w
ul.style.transform = 'translateX(' translateX 'px)'
}
})
})
当用户在第一张进行向右拖动时,用户看到的是克隆版的最后一张,为了实现无缝滚动效果,此时我们瞬间跳转到真正的最后一张也就是索引为2的,当执行定时器时,索引变成了3,此时又会跳到第一张,由此实现了无缝滚动。
小圆点高亮实现
这里我们要用到一个新的属性---classList classList属性是HTML5新添加的一个属性,可以返回元素的类名,不过ie10以上才支持 但是我们是做移动端所以不用考虑ie的问题。 该属性还可用于在元素添加,移除,切换 CSS类,有如下方法
- element.classList.add('类名') 追加类名(不用加点)
- element.classList.remove(’类名‘) 移除类名
- element.classList.toggle('类名') 切换类名(原来有这个类名则取消否则添加)
代码如下
代码语言:javascript复制...
// 小圆点跟随变化
//将ol里面的li带有current的类名元素选择出来去掉类名
ol.querySelector('li.current').classList.remove('current')
//当前索引li高亮
ol.children[index].classList.add('current')
})
})
手动拖放元素
接下来我们实现手指拖放元素,通过手指控制图片位置,要用到两个移动端的事件
touchstart:获取手指初始坐标 touchmove:移动手指 计算手指滑动距离,并且移动盒子 代码如下
代码语言:javascript复制 ...
//当前索引li高亮
ol.children[index].classList.add('current')
})
//手指滑动轮播
//触摸元素获取手指初始坐标
var startX = 0;
var moveX = 0;
ul.addEventListener('touchstart',function(e){
/*第一个手指的坐标*/
startX = e.targetTouches[0].pageX;
/*手指按下清除定时器*/
clearInterval(timer)
})
ul.addEventListener('touchmove',function(e){
/*移动的时候计算移动距离*/
/* 移动之后的手指坐标减去 初始坐标就是手指移动的距离 */
moveX = e.targetTouches[0].pageX-startX
//移动盒子 :盒子原来的位置加上手指移动的距离
var translateX = -index*w moveX;
ul.style.transform = 'translateX(' translateX 'px)'
})
})
实现轮播图上一张、下一张、回弹
上面代码只实现了拖放元素,并没有实现轮播图上一张、下一张、回弹的功能,我们要根据用户滑动的距离来实现上一张下一张或者回弹的功能
touchend 手指离开时 根据滑动距离分不同的情况
代码如下
代码语言:javascript复制 //触摸元素获取手指初始坐标
var startX = 0;
var moveX = 0;
var flag = false;//用户是否产生滑动标识
ul.addEventListener('touchstart',function(e){
/*第一个手指的坐标*/
startX = e.targetTouches[0].pageX;
/*手指按下清除定时器*/
clearInterval(timer)
})
ul.addEventListener('touchmove',function(e){
/*移动的时候计算移动距离*/
/* 移动之后的手指坐标减去 初始坐标就是手指移动的距离 */
moveX = e.targetTouches[0].pageX-startX
//移动盒子 :盒子原来的位置加上手指移动的距离
var translateX = -index*w moveX;
ul.style.transition='none';
ul.style.transform = 'translateX(' translateX 'px)';
flag=true;//移动时状态为正
e.preventDefault();//阻止滚动屏幕的行为
});
//手指离开时 回弹,上一张。下一张
ul.addEventListener('touchend',function(e){
// 如果用户确实发生了移动操作
console.log(moveX)
if(flag){
if(Math.abs(moveX)>50){
//上一张 (右滑 moveX为正)
if(moveX>0){
index--;
}else if(moveX<0){
//下一张 (左滑 moveX为负)
index ;
}
var translateX = -index*w;
ul.style.transition='all .3s';
ul.style.transform = 'translateX(' translateX 'px)';
}else{
//小于50像素回弹 回到当前位置不变
var translateX = -index*w;
ul.style.transition='all .1s';
ul.style.transform = 'translateX(' translateX 'px)';
}
moveX=0;//手指离开时清除移动距离防止用户移动离开后在次点击触发
}
//手指离开重新开启定时器
clearInterval(timer);
timer = setInterval(function(){
index
//移动距离
var translateX = -index*w
ul.style.transition = 'all .2s'
ul.style.transform = 'translateX(' translateX 'px)'
console.log(index)
},2000);
})
})
1.我们添加了用户滑动标识,当滑动时才时这个标识生效,避免用户点击的时候触发轮播 2.在用户手指离开时我们先进行判断用户是否产生了滑动操作,如果产生了滑动操作则根据用户行为实现上一张、下一张、回弹效果 分为下面几种情况 2.1用户滑动距离取绝对值>50 此时进行上一张下一张操作 2.1.1:当滑动距离>0时 代表右滑,此时实现上一张 2.1.2:当滑动距离<0时 代表左滑,此时实现下一张
2.2用户滑动距离取绝对值<50 此时实现回弹操作
并且在手指离开时我们清除了原来的滑动距离;重新开启了定时器
到此轮播图制作完成。