现在轮播图在很多项目或者App中处处可见,像我经常用的腾讯视频、QQ音乐等等都有轮播图,因此接下来就让我们看看轮播图组件的开发过程。
在此之前,我要用到我前面所讲的预加载(LoadImage)和Utils,如果有不了解的同学可以去loadImage、Utils预习一下,方便理解。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type = "module">
//模块化开发
import Utils from ./js/Utils.js;
import LoadImage from ./js/LoadImage.js;
var imageCon,left,right,dot;
var arr = ["a","b","c","e","left","right"];
var basePath = "./img/";
var expandedName = "png";
var bnlist;
var list;
var pos = 0;
var direction = "";
var carousel;
var dotlist = [];
var x = 0;
var bool = false;
var autobool = false;
var time = 200;
var speed = 40;
var pre;
init();
function init(){
carousel = Utils.ce("div",{
width:WIDTH + "px",
height:HEIGHT + "px",
position:"relative",
margin:"auto",
left:0,
right:0,
overflow:"hidden"
},body);
carousel.addEventListener("mouseenter",mouseHandler);
carousel.addEventListener("mouseleave",mouseHandler);
new LoadImage(arr,bashPath,expandedName,finishHandler);
}
function mouseHandler(e){
if(e.type === "mouseenter"){
autobool = false;
time = 200;
}else{
autobool = true;
}
}
function finishHandler(_list){
bnlist = _list.splice(-2);
list = _list.map(item=>{
item.style.width = WIDTH + "px";
item.style.height = HEIGHT + "px";
return item;
});
createImage();
createBn();
createDot();
animation();
}
function createImage(){
imgCon = Utils.ce("div",{
width:WIDTH*2 + "px",
height:HEIGHT+"px",
position:"absolute",
left:0
})
carousel.appendChild(imgCon);
imgCon.appendChild(list[0]);
}
function createBn(){
bnlist.forEach(function(item,index){
Object.assign(item.style,{
position:"absolute",
left:index === 0 ? "20px":"none",
right:index === 1 ? "20px":"none",
top:(HEIGHT-item.height)/2 + "px"
})
item.addEventListener("click",clickHandler);
carousel.appendChild(item);
})
}
function createDot(){
dot = Utils.ce("ul",{
listStyle:"none",
margin:"0px",
padding:"0px",
position:"absolute",
bottom:"20px"
});
list.forEach(function(item,index){
var li = Utils.ce("li",{
width:"15px",
height:"15px",
backgroundColor:"rgba(255,0,0,0)",
borderRadius:"15px",
marginLeft:index === 0 ? 0 : "10px",
float:"left",
},dot);
dotlist.push(li);
})
carousel.appendChild(dot);
dot.style.left = (WIDTH - dot.offsetWidth)/2 + "px";
dot.addEventListener("click",clickDotHandler);
}
function clickHandler(e){
if(bnlist.indexOf(this) === 0){
pos--;
if(pos < 0) pos = list.length-1;
direction = "right";
}else{
pos++;
if(pos > list.length-1) pos = 0;
direction = "left";
}
createNextImage();
}
function clickDotHandler(e){
if(e.target.constructor !== HTMLLIElement) return;
var index = dotlist.indexOf(e.target);
if(index === pos) return;
direction = index > pos ? "left" : "right";
pos = index;
createNextImage();
}
function createNextImage(){
if(direction === "left"){
imgCon.appendChild(list[pos]);
imgCon.style.left = "0px";
x = 0;
}else{
imgCon.insertBefore(list[pos],imgCon.firstChild);
imgCon.style.left = -WIDTH + "px";
x = -WIDTH;
}
bool = true;
changepre();
}
function animation(){
requestAnimationFrame(animation);
//无限循环 固定频率 每秒60帧
imgMove();
autoPlay();
}
function imgMove(){
if(!bool) return;
if(direction == "left"){
x-=speed;
if(x < -WIDTH){
x = 0;
bool = false;
imgCon.firstElementChild.remove();
}
imgCon.style.left = x + "px";
}else{
x+=speed;
if(x >= list.length-1){
x = 0;
bool = false;
imgCon.lastElementChild.remove();
}
imgCon.style.left = x + "px";
}
}
function autoplay(){
if(!autoBool) return;
time--;
if(time > 0) return;
time = 200;
//防抖:当持续触发事件时,一段时间内没有再触发事件,事件处理函数才会执行一次;如果在设置的时间到来之前,又一次触发了事件,就会造成延迟,也就是说当前时间的帧没执行完就又执行下一秒的帧,在下一秒的帧没执行之前,会先执行上一秒没执行完的帧,这就会造成卡顿,解决方法就是让上一秒的帧完完全全执行完,没16毫秒执行一次time--,直到time减为零,才会执行再次触发的事件。当然time的值只要大于(1000/16)就行 ,但是尽量大一点。
var evt = new MouseEvent("click");
bnlist[1].dispatchEvent(evt);
}
function changepre(){
if(pre){
pre.style.backgroundColor = "rgba(255,0,0,0)";
}
pre = dotlist[pos];
pre.style.backgroundColor = "rgba(255,0,0,0.6)";
}
</script>
</body>
</html>