接上一篇,第一个问题:我们要考虑图片数量,当图片数量<=1时,不显示指示器:
//第二步:添加指示器
var indicator_li = null;
if (banner_li.length > 1) {
var ul_indicator = document.getElementById("ul_indicator");
var indicatorHtml = "";
for (let i = 0; i < banner_li.length - 2; i++) {//要按原来的图片数量
indicatorHtml += "<li></li>"
}
ul_indicator.innerHTML = indicatorHtml;
indicator_li = ul_indicator.getElementsByTagName("li");
}
第二个问题:实现移动端手势滑动操作:监听触摸操作,我们需要用到addEventListener方法,并且需要监听至少三个手势:
按下:关闭定时器并记录手指落点坐标
ul_banner.addEventListener("touchstart", function () {
})
滑动:根据滑动动态坐标与手指落点坐标计算动态滑动距离
ul_banner.addEventListener("touchmove", function () {
})
抬起:做一些还原操作如再次开启定时器
ul_banner.addEventListener("touchend", function () {
})
另外要计算好,手指在屏幕滑动的距离,即
moveX=手指抬起点-手指落点
手指往右滑动,轮播图往左移动,moveX就为负数,反之为正数,因为我们上面的属性left用的是百分比(也可以用px具体值),所以我们要根据滑动距离/屏幕宽度计算滑动的百分比,再加上原来的ul偏移的百分比得到最终的left偏移量!
另外一个优化点是,手指滑动图片抬起后,图片的位置该如何显示?我这里是做了一个判断处理,如果滑动图片距离超过50%,则在抬起时自动滑动到上一个或下一个图片,如果未到50%,则还原。
了解滑动原理及计算方法后,其实下面就很好写了:
function bannerCarousel() {
// 第一步:获取banner li img列表,将列表第一张图片复制添加到最后一位,最后一张图片复制添加到第一位;
//以本例4张图片为例,将第4张图片复制一份放到第一位,将第1张图片放置到最后一位,最后得到6张图片,
// 这样每次轮播到position=0或者5时,将其位置重置为4或1,以实现无限滚动轮播
var ul_banner = document.getElementById("ul_banner");
var banner_li = ul_banner.getElementsByTagName("li");
var banner_li_first = banner_li[0];
var banner_li_last = banner_li[banner_li.length - 1];
ul_banner.appendChild(banner_li_first.cloneNode(true));//将第一张图片复制一份添加到最后一位
ul_banner.insertBefore(banner_li_last.cloneNode(true), ul_banner.firstChild);//将最后一张图片复制一份添加到第一位
ul_banner.style.width = banner_li.length * 100 + "%";//宽度为6张图片宽度
for (let i = 0; i < banner_li.length; i++) {
banner_li[i].style.width = 100 / banner_li.length + "%";
}
ul_banner.style.left = "-100%";//因首位添加图片后,需要将整体定位到第2张图片(实际为banner第一张)
//第二步:添加指示器
var indicator_li = null;
if (banner_li.length > 1) {
var ul_indicator = document.getElementById("ul_indicator");
var indicatorHtml = "";
for (let i = 0; i < banner_li.length - 2; i++) {//要按原来的图片数量
indicatorHtml += "<li></li>"
}
ul_indicator.innerHTML = indicatorHtml;
indicator_li = ul_indicator.getElementsByTagName("li");
}
//第三步:开启定时器
var page_index = 1;//初始位置为1
var timer = function () {
page_index++;
ul_banner.style.transition = "left 0.5s";
ul_banner.style.left = -page_index * 100 + "%";
changeIndicator();
reLoadPosition();
};
var interval = setInterval(timer, 2000);
//指示器改变
var changeIndicator = function () {
if (indicator_li != null) {
for (var i = 0; i < indicator_li.length; i++) {
indicator_li[i].style.backgroundColor = "#ccc";
}
if (page_index === 0 || page_index === banner_li.length - 2) {//最后一张
indicator_li[banner_li.length - 3].style.backgroundColor = "#fff";
} else if (page_index === banner_li.length - 1) {
indicator_li[0].style.backgroundColor = "#fff";
} else {
indicator_li[page_index - 1].style.backgroundColor = "#fff";
}
}
}
//重置banner位置
var reLoadPosition = function () {
setTimeout(function () {//延时操作,等待0.5s动画执行完毕后再执行以下操作
if (page_index === 0) {
page_index = banner_li.length - 2;
ul_banner.style.transition = "none";
ul_banner.style.left = (-page_index * 100) + "%";
} else if (page_index === banner_li.length - 1) {
page_index = 1;
ul_banner.style.transition = "none";
ul_banner.style.left = (-page_index * 100) + "%";
}
}, 500);
}
//滑动监听
var screenW = window.screen.width;
var startX, w_current_percent, w_move_percent;
ul_banner.addEventListener("touchstart", function () {
clearInterval(interval);
var touch = event.targetTouches[0];
startX = touch.clientX;
w_current_percent = -page_index * 100;//当前left的百分比
});
ul_banner.addEventListener("touchmove", function () {
var touch = event.targetTouches[0];
var moveX = touch.clientX - startX;
w_move_percent = moveX / screenW * 100;//跟随手指移动的百分比
ul_banner.style.transition = "none";//重要:一定不要忘记清除过渡效果
ul_banner.style.left = (w_current_percent + w_move_percent) + "%";
});
ul_banner.addEventListener("touchend", function () {
//如果左右滑动<宽度一般,则还原为原来的位置,否则,滑动到上一位或下一位
if ((w_move_percent < 50 && w_move_percent > 0) || (w_move_percent < 0 && w_move_percent > -50)) {
ul_banner.style.left = w_current_percent + "%";
} else if (w_move_percent > 50) {//往右滑动一位
page_index--;
ul_banner.style.transition = "left 0.5s";
ul_banner.style.left = (w_current_percent + 100) + "%";
changeIndicator();
reLoadPosition();
} else if (w_move_percent < -50) {//往左滑动一位
page_index++;
ul_banner.style.transition = "left 0.5s";
ul_banner.style.left = (w_current_percent - 100) + "%";
changeIndicator();
reLoadPosition();
}
interval = setInterval(timer, 2000);
});
}
其中重要的一点,在move过程中,一定不要忘了清除过渡效果:
ul_banner.style.transition = "none";
难点或者复杂点其实就是,滑动距离的计算,手指抬起时图片位置显示计算,以及指示器显示计算,这几点弄明白后,实现起来就不在话下了!