思路总结
- 第一 因为我们用的是变换函数translate来移动ul ,为了方便我们获取和设置ul的位置,我们需要封装一个变换函数设值和获值的函数 来方便操作 不然我们就要用全局变量了
- 首先我们用参数的个数来判断是设值还是获值
- 因为我们知道变换函数的属性 一次可以设多个值 比如 transform: translateX(200px) rotate(60deg) scaleX(1.5)
- 所以为了封装一个比较完美的函数 我们在其中给要变换的元素加一个属性,这个属性是一个对象
- 把变换函数名作为属性名 变换函数值作为属性值 存入这个对象当中
- 然后遍历这个对象,分不同的情况给定不同的单位
- 在获值时我们也根据变换函数的情况设置默认值
(function (w) {
w.transformCss = function (node, prop, value) {
//用一个对象来 装所有的变换函数
if (node.transformData == undefined) {
node.transformData = {}
}
//先判断参数个数是设值还是获值
if (arguments.length === 2) {
//获值 返回变换函数的值
let param = node.transformData[prop]
if(param == undefined) {
if(prop = 'scale' || 'scaleX' || 'scaleY'){
param = 1
}else {
param = 0
}
}
return param
} else if (arguments.length === 3) {
//设置变换函数的值
//首先把所有的变换函数和值都放进对象中
node.transformData[prop] = value
//遍历对象
let transformStr = ''
for (const key in node.transformData) {
//判断变换函数的类型
switch (key) {
case 'translate':
case 'translateX':
case 'translateY':
transformStr += key + '(' + node.transformData[key] + 'px)'
break;
case 'scale':
case 'scaleX':
case 'scaleY':
transformStr += key + '(' + node.transformData[key] + ') '
break;
case 'rotate':
case 'skew':
case 'skewX':
case 'skewY':
transformStr += key + '(' + node.transformData[key] + 'deg) '
break;
default:
break;
}
}
node.style.transform = transformStr
}
}
})(window)
-
第二 因为后面要无缝滚动 要改变ul中的li 所以我们ul和li的宽度 都用js来设置
-
第三 让图片可以被滑动起来
- touchstart中 我们获取两个值 一个是触点的初始位置 一个是ul初始的translateX值
- touchmove中 我们需要获取触点当前的值
- translateX = 触点当前值 - 触点初始值 + ul的translateX初始值
- 注意这里的移动距离每时每刻都是在变换的 我们不能拿当前的translateX的值去算,那样就变成了累加 ,所以用原始值 ,也就是触点出现的位置
-
第四 现在我们在通过滑动来实现切换图片
-
这里有个很巧的算法 就是用 当前的translateX的值 / 轮播图的宽度 然后再四舍五入就是index了 也就是图片的索引值 为什么是这样呢? 是因为这个商可以表示 我们轮播图移动了几张 如果第二张划到一半 可以看到第三张的一半 这是这里的商就是-1.5 通过四舍五入 就是-2 把index转成正数 我们就得到要移动到哪一张的index啦
-
然后限定范围 这个很简单
-
最后根据得到的index来移动ul和切换小点
-
-
第五 现在切换时会很生硬 所以我们加上过渡 ,但是加在哪呢 很简单 我们手指离开时 就要过渡 让图片自己完成接下来的动作 注意 我们需要在触点开始时取消过渡,因为当我们用手指滑动时,我们希望是实时的,不需要过渡
-
第六 现在完成无缝轮播
-
把整个ul都复制一份 要在设置 ul和li的宽度之前 ,这个很容易理解
-
然后重新获取下ul里面的li
-
接下来我们思考怎么去刷的一下来移动这个ul ,让他不露馅儿 箭头就是刷的一下
第一组第一张 => 第二组的第一张 第二组最后一张 => 第一组最后一张
- 我们看到需要第一组的数据 为了方便我们事先在没克隆之前 获取下li的length
-
//Itemlength 是原来的li个数 listItems.length是现在的li个数
if (index <= 0) {
index = Itemlength
//然后马上刷的一下改变位置
bannerList.style.transform = transformCss(bannerList, 'translateX', -index * banner
.clientWidth)
} else if (index >= listItems.length - 1) {
index = Itemlength - 1
bannerList.style.transform = transformCss(bannerList, 'translateX', -index * banner
.clientWidth)
}
-
设置在startTouch中 ,刚好没有过渡 同时这样设置后 就不会超出限定的范围 范围限定可以不要了
-
小点的样式切换 我们可以取余来做 这样很方便 用index % 本来的li的个数 0 % 5 = 0 5 % 5 = 0
-
第七 实现快速滑动也能切换
- 思路 时间间隔 = 触点结束时间 - 触点出现时间 new Date().getTime()
- 接下来判断 时间间隔300ms的话,我们就直接用移动距离来判断 实现切换 index++ index--
- 没有的话 还是用原来的那个算法 到一半我们才切换
- 这里有个BUG 因为我们的移动距离一直被保存在整个轮播图元素的属性当中 这时我们先移动一次 再点一下 就会触发上一次的切换 所以我们再每次触点出现时 将存储移动距离的这个属性清0