实现移动端滑动轮播和定时轮播
- slideBanner.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>移动端-轮播图</title>
<link rel="stylesheet" href="slideshow.css">
</head>
<body>
<div class="layout">
<div class="banner">
<ul class="clearfix">
<li><a href="#"><img src="images/5.jpg"></a></li>
<li><a href="#"><img src="images/1.jpg"></a></li>
<li><a href="#"><img src="images/2.jpg"></a></li>
<li><a href="#"><img src="images/3.jpg"></a></li>
<li><a href="#"><img src="images/4.jpg"></a></li>
<li><a href="#"><img src="images/5.jpg"></a></li>
<li><a href="#"><img src="images/1.jpg"></a></li>
</ul>
<ul>·
<li class="now"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
<script src="base.js"></script>
<script src="slideshow.js"></script>
</body>
</html>
- slideBanner.css
*,
::before,
::after{
padding: 0;
margin: 0;
/*兼容移动端主流浏览器*/
-webkit-box-sizing: border-box;
box-sizing: border-box;
/*清除移动端点击高亮效果*/
-webkit-tap-highlight-color: transparent;
}
body{
/*移动端默认的字体*/
font-family:Microsoft YaHei,sans-serif;
font-size: 14px;
color: #333;
}
ol,ul{
list-style: none;
}
/*清除浮动*/
.clearfix::before,
.clearfix::after{
content: "";
display: block;
height: 0;
line-height: 0;
visibility: hidden;
clear: both;
}
.layout{
width: 100%;
max-width: 750px;
min-width: 320px;
margin: 0 auto;
position: relative;
}
.banner{
width: 100%;
height: 300px;
overflow: hidden;
position: relative;
}
.banner ul:first-child{
width: 1000%;
height: 300px;
-webkit-transform: translateX(-10%);
transform: translateX(-10%);
}
.banner ul:first-child li{
width: 10%;
height: 100%;
float: left;
}
.banner ul:first-child li a{
display: block;
width: 100%;
height: 100%;
}
.banner ul:first-child li a img{
width: 100%;
height: 100%;
display: block;
}
.banner ul:last-child{
position: absolute;
bottom: 6px;
width: 100%;
text-align: center;
}
.banner ul:last-child li{
width: 6px;
height: 6px;
border: 1px solid #fff;
border-radius: 50%;
display: inline-block;
margin-left: 10px;
}
.banner ul:last-child li:first-child{
margin-left: 0;
}
.banner ul:last-child li.now{
background: #fff;
}
- slideBanner.js
/*封装一些公用的事件或者公用的方法*/
/*定义的一个命名空间*/
window.S = {};
/*封装一个事件 过渡结束事件*/
S.transitionEnd = function(dom,callback){
//1.给谁加事件
//2.事件触发后处理什么业务
if(!dom || typeof dom != 'object'){
//没dom的时候或者不是一个对象的时候 程序停止
return false;
}
dom.addEventListener('transitionEnd', function(){
callback && callback();
});
dom.addEventListener('webkitTransitionEnd', function(){
callback && callback();
});
}
window.onload = function(){
/*
* 1.自动轮播 定时器 无缝衔接 动画结束瞬间定位
* 2.点需要随着轮播的滚动改变对应的点 改变当前样式 当前图片的索引
* 3.手指滑动的时候让轮播图滑动 touch事件 记录坐标轴的改变 改变轮播图的定位(位移css3)
* 4.当滑动的距离不超过一定的距离的时候 需要吸附回去 过渡的形式去做
* 5.当滑动超过了一定的距离 需要 跳到 下一张或者上一张 (滑动的方向) 一定的距离(屏幕的三分之一)
* */
let imageCount = 5; //页面中用来轮播的图片有5张不同的
//轮播图大盒子
let banner = document.querySelector('.banner');
//图片的宽度
let width = banner.offsetWidth;
//图片盒子
let imageBox = banner.querySelector('ul:first-child');
//点盒子
let pointBox = banner.querySelector('ul:last-child');
//所有的点
let points = pointBox.querySelectorAll('li');
//公用方法
//加过渡
let addTransition = function(){
imageBox.style.transition = "all 0.3s";
imageBox.style.webkitTransition = "all 0.3s";/*做兼容*/
};
//清除过渡
let removeTransition = function(){
imageBox.style.transition = "none";
imageBox.style.webkitTransition = "none";
}
//定位
let setTranslateX = function(translateX){
imageBox.style.transform = "translateX("+translateX+"px)";
imageBox.style.webkitTransform = "translateX("+translateX+"px)";
}
//功能实现
//自动轮播 定时器 无缝衔接 动画结束瞬间定位
let index = 1;
let timer = setInterval(function(){
index++ ; //自动轮播到下一张
//改变定位 动画的形式去改变 transition transform translate
addTransition(); //加过渡动画
setTranslateX(-index * width); //定位
},3000);
//等过渡结束之后来做无缝衔接
S.transitionEnd(imageBox, function(){
//处理事件结束后的业务逻辑
if(index > imageCount ){
index = 1;
}else if(index <= 0){
index = imageCount;
}
removeTransition(); //清除过渡
setTranslateX(-index * width); //定位
setPoint(); //设置底部显示当前图片对应的圆角
});
//改变当前样式 当前图片的索引
let setPoint = function(){
//清除上一次的now
for(let i = 0 ; i < points.length ; i++){
points[i].className = " ";
}
//给图片对应的点加上样式
points[index-1].className = "now";
}
/*
手指滑动的时候让轮播图滑动 touch事件 记录坐标轴的改变 改变轮播图的定位(位移css3)
当滑动的距离不超过一定的距离的时候 需要吸附回去 过渡的形式去做
当滑动超过了一定的距离 需要 跳到 下一张或者上一张 (滑动的方向) 一定的距离(屏幕的三分之一)
*/
//touch事件
let startX = 0; //记录起始 刚刚触摸的点的位置 x的坐标
let moveX = 0; //滑动的时候x的位置
let distanceX = 0; //滑动的距离
let isMove = false; //是否滑动过
imageBox.addEventListener('touchstart', function(e){
clearInterval(timer); //清除定时器
startX = e.touches[0].clientX; //记录起始X
});
imageBox.addEventListener('touchmove',function(e){
moveX = e.touches[0].clientX; //滑动时候的X
distanceX = moveX - startX; //计算移动的距离
//计算当前定位 -index*width+distanceX
removeTransition(); //清除过渡
setTranslateX(-index * width + distanceX); //实时的定位
isMove = true; //证明滑动过
});
//在模拟器上模拟的滑动会有问题 丢失的情况 最后在模拟器的时候用window
imageBox.addEventListener('touchend', function(e){
// 滑动超过 1/3 即为滑动有效,否则即为无效,则吸附回去
if(isMove && Math.abs(distanceX) > width/3){
//5.当滑动超过了一定的距离 需要 跳到 下一张或者上一张 (滑动的方向)*/
if(distanceX > 0){ //上一张
index --;
}
else{ //下一张
index ++;
}
}
addTransition(); //加过渡动画
setTranslateX(-index * width); //定位
if(index > imageCount ){
index = 1;
}else if(index <= 0){
index = imageCount;
}
setPoint();
//重置参数
startX = 0;
moveX = 0;
distanceX = 0;
isMove = false;
//加定时器
clearInterval(timer); //严谨 再清除一次定时器
timer= setInterval(function(){
index++ ; //自动轮播到下一张
addTransition(); //加过渡动画
setTranslateX(-index * width); //定位
},3000);
});
};
4.核心代码解释
// 第一步
// 首尾两张图片是为了滑动时的过渡,当JS监听到此时滑动到是最后一张或者第一张的时候,
// 会分别自动地切换到倒数第二张(肉眼看到的最后一张)或者第二张图片(肉眼看到的第一张)
<li><a href="#"><img src="images/5.jpg"></a></li>
<li><a href="#"><img src="images/1.jpg"></a></li>
<li><a href="#"><img src="images/2.jpg"></a></li>
<li><a href="#"><img src="images/3.jpg"></a></li>
<li><a href="#"><img src="images/4.jpg"></a></li>
<li><a href="#"><img src="images/5.jpg"></a></li>
<li><a href="#"><img src="images/1.jpg"></a></li>
// 第二步
// 上面说到的监听会在transition结束后进行,
// 例如,要展示的图片共5张,此时滑到了第七张(也就是最后一张图片,同时也是我们肉眼看到的第一张图片),
// 监听到这种情况发生后,就会将位置移动到第二张(还是我们肉眼看到的第一张),但是这次移动是没有过渡效果,速度很快,
// 所以肉眼看不出来图片被我们替换了(因为是同一张图片,并且速度快,肉眼看不出位置已经被替换了)
// 同理,左滑滑到了第一张图片也是这样的处理逻辑。
S.transitionEnd(imageBox, function(){
//处理事件结束后的业务逻辑
if(index > imageCount ){
index = 1;
}else if(index <= 0){
index = imageCount;
}
removeTransition(); //清除过渡
setTranslateX(-index * width); //定位
setPoint(); //设置底部显示当前图片对应的圆角
});
// 第三步
//监听的核心的给dom添加监听事件'transitionEnd'。
S.transitionEnd = function(dom,callback){
//1.给谁加事件
//2.事件触发后处理什么业务
if(!dom || typeof dom != 'object'){
//没dom的时候或者不是一个对象的时候 程序停止
return false;
}
dom.addEventListener('transitionEnd', function(){
callback && callback();
});
dom.addEventListener('webkitTransitionEnd', function(){
callback && callback();
});
}
// 第四步
// 用JS添加CSS样式,添加过渡效果
let addTransition = function(){
imageBox.style.transition = "all 0.3s";
imageBox.style.webkitTransition = "all 0.3s";/*做兼容*/
};
// 第五步
// 动态去改变轮播的位置
let setTranslateX = function(translateX){
imageBox.style.transform = "translateX("+translateX+"px)";
imageBox.style.webkitTransform = "translateX("+translateX+"px)";
}
// 第六步
// 手指触摸屏幕的时候('touchstart'),记得清楚定时器
// 手指离开屏幕的时候('touchend'),记得添加回定时器
let removeTransition = function(){
imageBox.style.transition = "none";
imageBox.style.webkitTransition = "none";
}
5.效果图如下