移动web轮播图
参考实例,可以从中保存轮播图的图片,这里我们放入uploads的文件夹下,将八张图片一次改为l1.jpg,l2.jpg…
HTML
- 这里要放入十张图片,因为手指滑动的时候要从第一张滑动到最后一张,是无缝滑动,当然可以用原生的JS进行添加
- 最终我们可以通过移动ul来达到轮播的效果,所以ul的宽度要刚好放得下十张图片
- ol下的li是分页器,也就是我们看到的圆圈,类.current为选中状态
- clearfix类是清除浮动
<div class="jd_banner">
<ul class="jd_wrap clearfix">
<li><a href="javascript:;"><img src="uploads/l8.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l1.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l2.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l3.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l4.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l5.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l6.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l7.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l8.jpg" alt=""></a></li>
<li><a href="javascript:;"><img src="uploads/l1.jpg" alt=""></a></li>
</ul>
<ol>
<li class="current"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ol>
</div>
css样式
.clearfix::before,
.clearfix::after{
content: "";
display: block;
height: 0;
line-height: 0px;
clear: both;
visibility: hidden;
}
.jd_banner {
max-width: 640px;
min-width: 320px;
margin: 100px auto;
width: 100%;
position: relative;
overflow: hidden;
}
.jd_banner .jd_wrap {
width: 1000%;
transform: translateX(-10%);
}
.jd_banner .jd_wrap li {
width: 10%;
float: left;
}
.jd_banner .jd_wrap li img {
width: 100%;
}
.jd_banner ol {
height: 10px;
position: absolute;
left: 50%;
bottom: 3px;
transform: translateX(-50%);
}
.jd_banner ol li {
width: 6px;
height: 6px;
float: left;
border: 1px solid #fff;
margin-left: 10px;
border-radius: 50%;
}
.jd_banner ol li.current {
background: #fff;
}
JS
- 我们主要通过控制index,translateX,监听过渡动画的结束(webkitTransitionEnd)来实现轮播
- 对index进行限制
- 相同的代码进行封装
- 优化代码
var jdCon = document.querySelector('.jd_banner')
var ul = document.querySelector('.jd_banner>.jd_wrap')
var index = 1
var li = ul.querySelectorAll('li')
var olLi = document.querySelectorAll('ol>li')
var imgWidth = li[0].offsetWidth
// 过渡移动的效果
var transit = function(move){
var move = move || 0
ul.style.transition = 'all 0.5s linear'
ul.style.transform = `translateX(${-imgWidth*index+move}px)`
}
// 瞬间定位效果
var moment = function(distanceMove){
var distanceMove = distanceMove || 0
ul.style.transform = `translateX(${-imgWidth*index+distanceMove}px)`
ul.style.transition = 'none'
}
window.onresize = function(){
imgWidth = li[0].offsetWidth
}
var timer1 = setInterval(function(){
index++;
transit()
}, 1000)
ul.addEventListener('webkitTransitionEnd', function(){
if(index>li.length-2){
index = 1
moment()
}
if(index<1){
index = li.length-2
moment()
}
document.querySelector('.current').classList.remove('current')
olLi[index-1].classList.add('current')
})
var distanceStart = 0;
var move = 0;
var distanceEnd = 0;
jdCon.addEventListener('touchstart',function(e){
clearInterval(timer1)
distanceStart = e.touches[0].clientX
})
jdCon.addEventListener('touchmove',function(e){
var distance = e.touches[0].clientX
move = distance - distanceStart
moment(move)
})
jdCon.addEventListener('touchend',function(){
if(move>imgWidth/2){
index--
transit()
}else if(move<-imgWidth/2){
index++
transit()
}else{
transit()
}
distanceStart = 0;
move = 0;
distanceEnd = 0;
timer1 = setInterval(function(){
index++;
transit()
}, 1000)
})
整体思路
- 首先做好布局,ul的子元素li要在一行上,无缝链接
- 利用css,ul的宽度为1000%, 设置transform: translateX(-10%);,使得不会显示展示给用户的最后一张图片,显示第一张图片
- 自动播放轮播图
- 利用定时器,让index每次加1,然后过渡滚动一张图片
var timer1 = setInterval(function(){
index++;
ul.style.transition = 'all 0.5s linear'
ul.style.transform = `translateX(${-imgWidth*index}px)`
}, 1000)
- 监听webkitTransitionEnd,过渡动画结束时,清除当前的类.current,给ol下的li[index]添加一个类
- 过渡动画结束后,如果index过大,我们要对其进行限制,当index为9,此时界面显示的是第十张图片,也就是用户看到的第一张图片,所以我们瞬间(在0s)让其移动到第一张,在令index=1
ul.addEventListener('webkitTransitionEnd', function(){
// 当时间过渡结束
// 添加.current
if(index>8){
// 当第一张移动完成后
// 瞬间让index变为1
ul.style.transform = `translateX(${-imgWidth}px)`
ul.style.transition = 'none'
index = 1
} document.querySelector('.current').classList.remove('current')
olLi[index-1].classList.add('current')
})
- ul跟随着手指的滑动而滑动,当手指滑动多少,ul跟着滑动多少
var distanceStart = 0;
var move = 0;
var distanceEnd = 0;
jdCon.addEventListener('touchstart',function(e){
clearInterval(timer1)
distanceStart = e.touches[0].clientX
})
jdCon.addEventListener('touchmove',function(e){
var distance = e.touches[0].clientX
move = distance - distanceStart
ul.style.transform = `translateX(${-imgWidth*index+move}px)`
ul.style.transition = 'none'
})
- 滑动结束时做吸附效果
- 向右滑动时,如果滑动大于图片二分之一的宽度,当手指放开则加上过渡动画效果移动到上一张图片,此时我们移动始终是控制index
if(move>imgWidth/2){
index--
ul.style.transition = 'all 0.5s linear'
ul.style.transform = `translateX(${-imgWidth*index}px)`
}
- 向左滑动时,如果滑动大于图片二分之一的宽度,当手指放开则加上过渡动画效果移动到下一张图片,此时我们移动始终是控制index
else if(move<-imgWidth/2){
index++
ul.style.transition = 'all 0.5s linear'
ul.style.transform = `translateX(${-imgWidth*index}px)`
}
- 其它情况保持显示现状的图片
else{
ul.style.transition = 'all 0.5s linear'
ul.style.transform = `translateX(${-imgWidth*index}px)`
}
- 最后所有的清0,开启定时器
- 相同代码封装,测试是否有bug,发现右滑有问题--------始终通过控制index来实现移动和切换ol分页器,要对index进行限制。对数字通过ul下的li.length来控制,将代码封装成可调用,可读性,逻辑性的代码
if(index<1){
ul.style.transform = `translateX(${-imgWidth*8}px)`
ul.style.transition = 'none'
index = 8
}
步骤
/*
获取 必须知道的 变量
步骤1: 不考虑过渡效果 直接 刷刷刷的 切换
定时器中 index++
判断是否越界
修改 轮播图ul的 位置
考虑到 索引从1开始
css 默认 让ul 往左边窜一个屏幕宽度
步骤2: 下方的 索引li标签 修改 外观
由于我们是使用.current 标示当前的索引值
清空所有li的 class
为当前的那个 li 添加current
步骤3:然切换有动画效果
使用css3中的transition
.style.transition ='all .3s';
在获取的时候 进行添加即可
步骤4:当我切换到 最后一张时 瞬间 切到 第一张
关闭过度
瞬间切换到第一张
步骤5:对代码 进行重构 添加进来了 过渡结束知识点
由于 我们在修改 ul的位置时 会使用过度
当注册了 过渡结束事件之后,每次 过渡完毕 都会 调用该事件
将 判断 index 是否 越界 以及 修改 索引的 代码 全部 迁移到 过渡结束事件中
定时器逻辑
index++;
修改 ul的 位置 ->开始过渡
过渡结束事件逻辑
判断 index是否有效
进行修正
修改索引li标签的 显示
步骤6: 使用touch事件,实现 手指 拨动 ul滑动 效果
touchstart
记录开始值
关闭定时器
关闭过渡效果
touchmove
计算移动值
修改ul的位置(在原始值的基础上进行修改,没有过渡效果的)
touchend
记录移动的距离(?)
开启定时器(*)
*/
疑问
- 宽高必须考虑到移动web的适配方案
- 可能大家会把ul进行定位,ul定位(absolute),我们就无法把父盒子撑开,也就是父盒子jd_banner就没有高度,到时ol也很难定位,影响页面布局等问题
- 直接给父盒子设置高度,但是我们这个高度不好设置,因为不同的屏幕图片高度是不一致的
- 使用translateX来移动逻辑会更简单些
- 注意要样式重置,比如img要去掉基线
- clearfix可以不加,因为父盒子jd_banner已经设置overflow: hidden;会触发bfc