Files
2024-09-27 02:06:13 +08:00

338 lines
9.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function () {
// 插件的默认参数
var defaultOption = {
el: '.swiper-container',
reverse: true,
eventBus: {},
timer: null,
statusCallChangeX: true,
containerWidth: function () {
return $(this.el).clientWidth
},
loop: false, // false 不开启, true 开启
autoPlay: false,
autoTime: 300,
speed: 300,
direction: 'horizontal',
initialSlide: 0,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
pagination: {
el: '.swiper-pagination',
}
};
// 模拟类
function Swiper(option) {
if (option.hasOwnProperty("el") && option.el.length != 0) {
defaultOption.el = option.el;
defaultOption.loop = option.loop || defaultOption.loop;
defaultOption.autoPlay = option.autoPlay || defaultOption.autoPlay;
defaultOption.autoTime = option.autoTime || defaultOption.autoTime;
defaultOption.speed = option.speed || defaultOption.speed;
defaultOption.direction = option.direction || defaultOption.direction;
defaultOption.initialSlide = option.initialSlide || defaultOption.initialSlide;
if (option.hasOwnProperty("navigation")) {
if (option.navigation.hasOwnProperty("nextEl")) {
defaultOption.navigation.nextEl = option.navigation.nextEl
}
if (option.navigation.hasOwnProperty("prevEl")) {
defaultOption.navigation.prevEl = option.navigation.prevEl
}
}
if (option.hasOwnProperty("on")) {
for (const key in option.on) {
if (!defaultOption.eventBus.hasOwnProperty(key)) {
defaultOption.eventBus[key] = option.on[key];
} else {
throw new Error(`方法:${key}已经存在`)
}
}
}
this.init()
} else {
throw new Error("缺少必填参数el或el为空");
}
}
Swiper.prototype = {
init() {
this.createdDot();
this.initialSlide();
this.bindNextEl();
this.bindPrevEl();
defaultOption.autoPlay ? this.AutoPlay() : '';
},
/**
* 默认显示第几张轮播图
*/
initialSlide() {
var offset = -defaultOption.initialSlide * defaultOption.containerWidth();
this.changeX(offset);
this.DotChange(defaultOption.initialSlide)
},
/**
* 下一页
*/
bindNextEl() {
if ($(defaultOption.navigation.nextEl) != null) {
$(defaultOption.navigation.nextEl).onclick = () => {
this.loopChange("next")
}
}
},
/**
* 上一页
*/
bindPrevEl() {
if ($(defaultOption.navigation.prevEl) != null) {
$(defaultOption.navigation.prevEl).onclick = () => {
this.loopChange("prev")
}
}
},
/**
* 计算移动距离,和越界处理
* @param offset
*/
animation(offset) {
var oldOffset = parseInt($(".swiper-wrapper").style.transform.substring(11));
var newOffset = oldOffset + offset;
if (newOffset < -1040) {
newOffset = 0
};
if (newOffset > 0) {
newOffset = -1040
};
this.DotChange(
Math.abs(newOffset / defaultOption.containerWidth())
);
this.changeX(newOffset)
},
/**
* 创建小圆点
*/
createdDot() {
// 如果没有小圆点的父级dom元素那么不创建小圆点
if ($(defaultOption.pagination.el) != null) {
var Slide = $(".swiper-wrapper .swiper-slide");
Slide.forEach((v, i) => {
$(defaultOption.pagination.el).innerHTML +=
`<div class="swiper-pagination-dot ${i == 0 ? 'dot-active': ''}"></div>`
});
// 绑定事件
var children = $(`${defaultOption.pagination.el} swiper-pagination-dot`)
children.forEach((v, i) => {
v.onclick = () => {
this.DotChange(i)
}
});
// var children = $(defaultOption.pagination.el).children
// for (var i = 0; i < children.length; i++) {
//
// ((index)=>{
//
// children[index].onclick = () => {
// this.DotChange(index)
// }
//
// })(i);
//
// }
}
},
/**
* 小圆点切换
* @param index 下标
*/
DotChange(index) {
// 保存最新的下标
defaultOption.initialSlide = index;
// 调用事件,回传最新下标给用户的方法
defaultOption.eventBus.slideChange &&
defaultOption.eventBus.slideChange(defaultOption.initialSlide)
// 改变小圆点的激活样式
var children = $(defaultOption.pagination.el).children;
for (var i = 0; i < children.length; i++) {
children[i].classList.remove("dot-active")
}
children[index].classList.add("dot-active")
// 移动轮播图
this.changeX(index * -defaultOption.containerWidth())
},
/**
* 让图片动起来
* @param x
*/
changeX(x) {
var style = null;
// 通过变量 statusCallChangeX 判断方法是否是第一次执行,如果是第一次执行
// 那么不需要 transition-duration 动画时间
// 主要是解决initialSlide 的bug
if (defaultOption.statusCallChangeX) {
style = `transform: translateX(${x}px);`;
} else {
style =
`
transition-duration: ${defaultOption.speed/1000}s;
transform: translateX(${x}px);
`
}
defaultOption.statusCallChangeX = false;
$(".swiper-wrapper").style = style
},
/**
* 自动播放
* @constructor
*/
AutoPlay() {
timer = setInterval(
() => {
// 如果开启了循环播放
if (defaultOption.loop) {
// 向下一页播放
this.loopChange("next")
} else {
// 如果不是最后一张
if (defaultOption.initialSlide != $(".swiper-wrapper").children.length - 1) {
// 因为这行代码会被重复执行,所以需要做一个变量来决定轮播图移动的方向
// 进而判断向什么方向保持继续移动
if (defaultOption.reverse) {
this.loopChange("next")
} else {
this.loopChange("prev")
}
} else {
this.loopChange("prev")
defaultOption.reverse = false
}
// 判断是否是第一张,如果是第一张,那么改变方向(下一页)
if (defaultOption.initialSlide == 0) {
defaultOption.reverse = true
}
}
},
defaultOption.autoTime);
$(defaultOption.el).onmousemove = () => clearInterval(timer);
$(defaultOption.el).onmouseout = () => this.AutoPlay();
},
/**
* 循环切换的公共代码封装
*/
loopChange(type) {
if (defaultOption.loop) {
this.animation(
type == 'next' ? -defaultOption.containerWidth() : defaultOption.containerWidth()
)
} else {
if (
defaultOption.initialSlide !=
(type == "next" ?
$(".swiper-wrapper").children.length - 1 :
0)
) {
this.animation(type == 'next' ? -defaultOption.containerWidth() : defaultOption.containerWidth())
}
}
},
// ----------- 对外暴露的方法 ----------
/**
* 事件控制中心
* @param methodsName
* @param callBack
*/
on(methodsName, callBack) {
if (!defaultOption.eventBus.hasOwnProperty(methodsName)) {
defaultOption.eventBus[methodsName] = callBack;
switch (methodsName) {
case 'slideChange':
defaultOption.eventBus[methodsName](defaultOption.initialSlide)
break;
}
} else {
throw new Error(`方法:${methodsName}已经存在`)
}
},
/**
* 切换轮播图
* @param index
*/
slideTo(index = 0) {
this.changeX(-index * defaultOption.containerWidth());
this.DotChange(index)
}
}
function $(className) {
var classNameArr = className.split(" ");
if (classNameArr.length == 1) {
return document.querySelector(className)
} else {
// 多类名的时候,获取最后一个类名的上一个类名
var fatherClassName = classNameArr[classNameArr.length - 2];
// 获取最后一个类名
var lastClassName = classNameArr[classNameArr.length - 1];
var NewArr = []
// 获取父级有多少个子元素
var childrenList = document.querySelector(fatherClassName).children;
// 返回你要的子元素
for (let i = 0; i < childrenList.length; i++) {
if (childrenList[i].className.indexOf(lastClassName.replace(".", "")) != -1) {
NewArr.push(childrenList[i])
}
}
//return NewArr.length == 1 ? NewArr[0] : NewArr
// 如果只有一个返回html
if (NewArr.length == 1) {
return NewArr[0]
// 多个直接返回数组
} else {
return NewArr
}
}
}
window.Swiper = Swiper
})()
// 自执行函数