轮播图(面向对象)
import LoadImage from "./";
import Utils from "./";
export default class Carousel {
imgList; //轮播图图片放入ingList数组中
w;
h;
bnlist; //存放左右点击按钮的图片
list; //存放只含有轮播图图片的数组
imageCon; //存放两张图片隐藏在轮播图后边,通过调整定位改变位置,进而实现轮播图
parent; //父元素
dot; //轮播图下部点击小圆点整体ul图
dotList = []; //轮播图下部点击小圆点li存入数组
pos = 0; //通过pos 记录当前为第几张图片
direction = ""; //记录轮播图转换时图片移动方向
bool = false; //控制图片是否转换,转换开关
x = 0; //控制imageCon left的值
speed = 0.5; // 控制imageCon移动速度
autoBool = false; //图片自动轮播开关
time = 200; //设置防抖 200次执行一次
pre; //设置下部小圆点 背景颜色透明度
static carouselList = []; //存放轮播图,可以设置多个轮播图,然后添加到数组内
constructor(_imgList) {
this.imgList = _imgList;
//创建播放轮播图的div
this.carousel = this.createCarousel();
//预缓存图片,并且全部缓存完成后执行finishHandler函数,此时图片已经是一个图片元素了
new LoadImage(_imgList, (list) => this.finishHandler(list));
//将创建的轮播图放入静态数组内
Carousel.carouselList.push(this);
}
//将元素放入给定的父元素内
appendTo(parent) {
if (parent.constructor === String) parent = document.querySelector(parent);
parent.appendChild(this.carousel);
this.parent = parent;
}
//图片全部预缓存结束后执行的函数
finishHandler(_list) {
//将预缓存后存放浅复制图片的数组删除后两位,即删除左右按钮两张图片,将删除的两张图片存入新数组内
this.bnlist = _list.splice(-2);
//如果w不存在,给w赋予轮播图第一张图片的宽和高
if (!this.w) {
this.w = _list[0].width / 100;
this.h = _list[0].height / 100;
}
// 到此为止w和h正式全部确认完毕
this.list = _list.map((item) => {
item.style.width = this.w + "rem";
item.style.height = this.h + "rem";
return item;
});
//给carousel设置宽高
Object.assign(this.carousel.style, {
width: this.w + "rem",
height: this.h + "rem",
});
//图片全部加载完成后执行以下函数
this.createImageCon();
this.createBn();
this.createDot();
this.changePre();
}
//setWH函数 :设置图片宽高
setWH(_w, _h) {
//如果图片加载完成,直接返回
if (!this.parent) return;
//如果传入的参数为布尔值
if (_w.constructor === Boolean) {
//如果第一个为true
if (_w) {
//则以父元素的宽作为图片的宽,高为宽的一半
var rect = this.parent.getBoundingClientRect();
this.w = rect.width / 100;
this.h = this.w / 3;
}
//如果第一个参数为数值型,宽高为 传入的参数
} else if (_w.constructor === Number) {
this.w = _w / 100;
this.h = _h / 100;
}
}
//创建轮播图容器
createCarousel() {
var carousel = Utils.ce("div", {
position: "relative",
margin: "auto",
overflow: "hidden",
left: 0,
right: 0,
backgroundColor: "rgba(255,0,0,0.1)",
});
//为轮播图容器设置鼠标滑入和鼠标滑出事件,用来实现 轮播图自动播放
carousel.addEventListener("mouseenter", (e) => this.mouseHandler(e));
carousel.addEventListener("mouseleave", (e) => this.mouseHandler(e));
return carousel;
}
//创建图片存放的div,存放两张图片,以实现图片实现
createImageCon() {
this.imageCon = Utils.ce("div", {
width: this.w * 2 + "rem",
height: this.h + "rem",
position: "absolute",
left: 0,
});
//将第一张图片放入图片存放容器中
this.imageCon.appendChild(this.list[0]);
//将图片存放容器放入轮播图div中
this.carousel.appendChild(this.imageCon);
}
//创建左右按钮
createBn() {
//遍历存放左右按钮的数组,并且给图片元素添加CSS样式
this.bnlist.forEach((item, index) => {
Object.assign(item.style, {
position: "absolute",
left: index === 0 ? "20px" : "none",
right: index === 1 ? "20px" : "none",
top: (this.h - item.height / 100) / 2 + "rem",
});
//给左右按钮添加点击事件
item.addEventListener("click",e => this.clickHandler(e));
//将左右按钮添加到轮播图容器里
this.carousel.appendChild(item);
});
}
createDot() {
//创建存放轮播图下方小按钮的ul
this.dot = Utils.ce("ul", {
listStyle: "none",
margin: "0px",
padding: "0px",
position: "absolute",
bottom: "0.2rem",
});
//根据存放图片数组的长度创建小按钮li
this.list.forEach((item, index) => {
var li = Utils.ce(
"li",
{
width: "0.15rem",
height: "0.15rem",
backgroundColor: "rgba(255,0,0,0)",
border: "1px solid #FF0000",
borderRadius: "0.15rem",
float: "left",
marginLeft: index === 0 ? 0 : "0.1rem",
},
this.dot
);
//将创建的li放入dotList数组内
this.dotList.push(li);
});
//将小按钮添加到轮播图容器内
this.carousel.appendChild(this.dot);
//给小按钮设置位置
this.dot.style.left = (this.w - this.dot.offsetWidth / 100) / 2 + "rem";
//给小按钮添加点击事件
this.dot.addEventListener("click", (e) => this.clickDotHandler(e));
}
//左右按钮触发后执行的函数
clickHandler(e) {
if(this.bool) return;
//如果侦听的元素为左右按钮数组内的第0为 即左按钮时
if (this.bnlist.indexOf(e.currentTarget) === 0) {
//pos-1,pos为轮播图图片的“编号”,图片依靠pos改变。
this.pos--;
//如果pos小于零说明左侧没有图片了,pos等于最右侧图片“编号”
if (this.pos < 0) this.pos = this.list.length - 1;
//图片此时向右滑动
this.direction = "right";
}
//else即为右按钮
else {
//pos的值+1
this.pos++;
//如果pos大于了图片的个数,则右侧没有图片了,pos等于最左侧图片的“编号”,即0
if (this.pos > this.list.length - 1) this.pos = 0;
//此时pos向左移动
this.direction = "left";
}
//然后执行图片切换函数
this.createNextImage();
}
//点击下方小按钮执行的函数
clickDotHandler(e) {
if(this.bool) return;
//委托事件,如果点击的元素不是li,直接返回
if (e.target.constructor !== HTMLLIElement) return;
//声明index为点击的li在数组内的下标
var index = this.dotList.indexOf(e.target);
//如果点击li的下标等于当前pos,即小按钮对应的图片一致时,直接返回
if (index === this.pos) return;
//根据下标和pos的大小判断点击li后图片应该左移还是右移
this.direction = index > this.pos ? "left" : "right";
//然后将pos改为点击li的下标
this.pos = index;
//执行更换图片的函数
this.createNextImage();
}
//更换图片函数
createNextImage() {
//如果移动方向为左
if (this.direction === "left") {
//将在图片列表里下标为pos的图片元素插入到存放图片用来转换的容器内
this.imageCon.appendChild(this.list[this.pos]);
this.imageCon.style.left = "0rem";
this.x = 0;
}
//如果移动方向为右
else {
//在转换容器的最左侧插入下标为pos的图片元素
this.imageCon.insertBefore(this.list[this.pos], this.imageCon.firstChild);
//然后将给转换容器定位为-w ,即把准备切换的图片切换到最左侧,以实现切换动画效果
this.imageCon.style.left = -this.w + "rem";
//x赋值为-w
this.x = -this.w;
}
//将切换开关设置为true
this.bool = true;
//执行下方按钮背景图改变函数
this.changePre();
}
changePre() {
//如果pre存在,先把所有小圆点背景色设为透明
if (this.pre) {
this.pre.style.backgroundColor = "rgba(255,0,0,0)";
}
//然后给pre赋值为下标为pos的小圆点,并且将其背景色设置为0.6透明
this.pre = this.dotList[this.pos];
this.pre.style.backgroundColor = "rgba(255,0,0,0.6)";
}
//鼠标滑入滑出事件执行的函数
mouseHandler(e) {
//如果鼠标滑入,自动播放关闭,且防抖time设为200
if (e.type === "mouseenter") {
this.autoBool = false;
this.time = 200;
} else {
//如果鼠标滑出,开始自动播放
this.autoBool = true;
}
}
//改变函数
update() {
this.imgMove();
this.autoPlay();
}
//图片转换函数
imgMove() {
//判断容器是否移动,否的话直接返回
if (!this.bool) return;
//如果移动方向为左
if (this.direction === "left") {
//x值逐渐减少,即容器定位左移,显示图片左移效果
this.x -= this.speed;
//当x<=-w时,x=0,关闭转换开关,,并且删除第一张在转换容器的图片
if (this.x <= -this.w) {
this.x = 0;
this.bool = false;
this.imageCon.firstElementChild.remove();
}
//转换容器定位到x
this.imageCon.style.left = this.x + "rem";
} else {
//右移时,x值从-w逐渐增大,即容器右移,图片右移效果
this.x += this.speed;
//当x>=0时,x=0,关闭转换开关,删除之前图片
if (this.x >= 0) {
this.x = 0;
this.bool = false;
this.imageCon.lastElementChild.remove();
}
//转换容器定位到x=0
this.imageCon.style.left = this.x + "rem";
}
}
//自动播放函数
autoPlay() {
//如果开关为关,即鼠标滑入,直接返回
if (!this.autoBool) return;
this.time--;
//如果开关为开,即鼠标滑出,抛发给右按钮点击事件
if (this.time > 0) return;
this.time = 200;
var evt = new MouseEvent("click");
this.bnlist[1].dispatchEvent(evt);
}
//静态改变方法,可以给全部的轮播图实现改变
static UPDATE() {
for (var i = 0; i < Carousel.carouselList.length; i++) {
Carousel.carouselList[i].update();
}
}
}