338 lines
9.1 KiB
JavaScript
338 lines
9.1 KiB
JavaScript
(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
|
||
|
||
})()
|
||
|
||
// 自执行函数
|