331 lines
13 KiB
JavaScript
331 lines
13 KiB
JavaScript
(function () {
|
||
/**
|
||
* 构造函数
|
||
* @param {*} ParentElement 父节点的选择器名称
|
||
* @param {*} Configuration 插件的自定义设置项
|
||
*/
|
||
function Swiper(ParentElement, Configuration) {
|
||
// 默认参数
|
||
// slideChangeTransitionStart【完成】
|
||
// slideTo【完成】
|
||
this.defaultConf = {
|
||
reverse: false,
|
||
timer: '', // 保存自动播放的定时器
|
||
ParentElement: '.swiper-container',
|
||
wrapper: '.swiper-wrapper',
|
||
slide: '.swiper-slide',
|
||
config: {
|
||
loop: false, // 是否开启循环播放【完成】
|
||
time: 1, // 自动播放的间隔事件【完成】
|
||
speed: 300, // 切换轮播图时候用的时间【完成】
|
||
grabCursor: false, // 鼠标放到轮播图上是否显示为 小手【完成】
|
||
initialSlide: 0, // 默认显示第一个【完成】
|
||
auto: false, // 是否开启自动播放【完成】
|
||
},
|
||
// 小圆点的父标签选择器名称
|
||
pagination: {
|
||
el: '.swiper-pagination',
|
||
},
|
||
navigation: {
|
||
nextEl: '.swiper-button-next', // 下一页
|
||
prevEl: '.swiper-button-prev', // 上一页
|
||
},
|
||
}
|
||
|
||
this.defaultConf.ParentElement = ParentElement || this.defaultConf.ParentElement;
|
||
this.defaultConf.config.loop = Configuration.loop || this.defaultConf.config.loop;
|
||
this.defaultConf.config.time = Configuration.time || this.defaultConf.config.time;
|
||
this.defaultConf.config.speed = Configuration.speed || this.defaultConf.config.speed;
|
||
this.defaultConf.config.grabCursor = Configuration.grabCursor || this.defaultConf.config.grabCursor;
|
||
this.defaultConf.config.initialSlide = Configuration.initialSlide || this.defaultConf.config.initialSlide;
|
||
this.defaultConf.config.auto = Configuration.auto || this.defaultConf.config.auto;
|
||
this.defaultConf.wrapper = Configuration.wrapper || this.defaultConf.wrapper;
|
||
this.defaultConf.slide = Configuration.slide || this.defaultConf.slide;
|
||
|
||
this.slideArr = this._(`${this.defaultConf.wrapper} ${this.defaultConf.slide}`);
|
||
|
||
// 最外层 swiper-container 宽度
|
||
this.f = this.$(this.defaultConf.ParentElement).offsetWidth;
|
||
|
||
// 判断小圆点
|
||
if (Configuration.hasOwnProperty("pagination")) {
|
||
this.defaultConf.pagination.el = Configuration.pagination.el;
|
||
this.RenderDot()
|
||
}
|
||
|
||
// 判断使用自定义前进后退按钮
|
||
if (Configuration.hasOwnProperty("navigation")) {
|
||
this.RenderNavigation()
|
||
//判断下一页按钮的名称是否自定义
|
||
if (Configuration.navigation.hasOwnProperty("nextEl")) {
|
||
this.defaultConf.navigation.nextEl = Configuration.navigation.nextEl;
|
||
}
|
||
//判断上一页按钮的名称是否自定义
|
||
if (Configuration.navigation.hasOwnProperty("prevEl")) {
|
||
this.defaultConf.navigation.prevEl = Configuration.navigation.prevEl;
|
||
}
|
||
}
|
||
|
||
this.UserConfig = Configuration
|
||
this.init()
|
||
}
|
||
|
||
|
||
// 类的方法
|
||
Swiper.prototype = {
|
||
init: function () {
|
||
this.SetWrapperWidth();
|
||
this.defaultConf.config.auto ? this.AutoPlay() : '';
|
||
this.initSwiperSlide()
|
||
},
|
||
// 设置swiper-slide父类的宽度
|
||
SetWrapperWidth: function () {
|
||
|
||
// 计算swiper-slide的宽度
|
||
this.slideArr.forEach(v => v.style.width = `${this.f}px`)
|
||
this.$(this.defaultConf.wrapper).style = `
|
||
width: ${this.f * this.slideArr.length}px;
|
||
left: -${this.f * this.defaultConf.config.initialSlide}px;
|
||
transition: all ease ${this.defaultConf.config.speed / 1000}s;
|
||
cursor: ${this.defaultConf.config.grabCursor ? 'pointer' : ''} ;
|
||
`
|
||
},
|
||
|
||
/**
|
||
* 注册移动端滑动
|
||
*/
|
||
initSwiperSlide: function () {
|
||
var fa = this.$(this.defaultConf.ParentElement),
|
||
startX = 0,
|
||
startY = 0;
|
||
|
||
fa.addEventListener('touchstart', function (e) {
|
||
e.stopPropagation()
|
||
startX = e.targetTouches[0].pageX
|
||
startY = e.targetTouches[0].pageY
|
||
})
|
||
|
||
var getDirection = function (startx, starty, endx, endy) {
|
||
// 获得角度
|
||
var getAngle = function(angx, angy) {
|
||
return Math.atan2(angy, angx) * 180 / Math.PI;
|
||
};
|
||
|
||
var angx = endx - startx;
|
||
var angy = endy - starty;
|
||
var result = 0;
|
||
|
||
// 如果滑动距离太短
|
||
if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
|
||
return result;
|
||
}
|
||
|
||
var angle = getAngle(angx, angy);
|
||
if (angle >= -135 && angle <= -45) {
|
||
result = 1;
|
||
} else if (angle > 45 && angle < 135) {
|
||
result = 2;
|
||
} else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
|
||
result = 3;
|
||
} else if (angle >= -45 && angle <= 45) {
|
||
result = 4;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
fa.addEventListener('touchmove', (e) => {
|
||
e.stopPropagation()
|
||
var endX = e.changedTouches[0].pageX;
|
||
var endY = e.changedTouches[0].pageY;
|
||
|
||
var direction = getDirection(startX, startY, endX, endY);
|
||
if (direction == 3 || direction == 4) {
|
||
var x = parseInt(endX - startX) - 40
|
||
this.$(this.defaultConf.wrapper).style.webkitTransform = `translate3d(${x}px,0px,0px)`;
|
||
}
|
||
});
|
||
|
||
fa.addEventListener('touchend', (e) => {
|
||
e.stopPropagation()
|
||
var endX = e.changedTouches[0].pageX;
|
||
var endY = e.changedTouches[0].pageY;
|
||
|
||
var direction = getDirection(startX, startY, endX, endY);
|
||
|
||
switch (direction) {
|
||
case 0:
|
||
console.log("未滑动!");
|
||
break;
|
||
case 1:
|
||
console.log("向上!")
|
||
break;
|
||
case 2:
|
||
console.log("向下!")
|
||
break;
|
||
case 3:
|
||
this.$(this.defaultConf.wrapper).style.webkitTransform = `translate3d(0px,0px,0px)`;
|
||
this.animation(-this.f)
|
||
this.CallMethods()
|
||
this.UserConfig.pagination && this.ChangeDotActive()
|
||
console.log("向左!")
|
||
break;
|
||
case 4:
|
||
this.$(this.defaultConf.wrapper).style.webkitTransform = `translate3d(0px,0px,0px)`;
|
||
this.animation(this.f)
|
||
this.CallMethods()
|
||
this.UserConfig.pagination && this.ChangeDotActive()
|
||
console.log("向右滑动");
|
||
break;
|
||
default:
|
||
}
|
||
})
|
||
},
|
||
|
||
CallMethods() {
|
||
if (this.UserConfig.hasOwnProperty("on")) {
|
||
var TotalLeft = Math.abs(parseInt(this.$(this.defaultConf.wrapper).style.left));
|
||
index = TotalLeft / this.f;
|
||
// 实现调用用户传入的方法,返回下标给用户
|
||
this.UserConfig.on && this.UserConfig.on.slideChangeTransitionStart(index)
|
||
}
|
||
},
|
||
|
||
// 生成小圆点
|
||
RenderDot: function () {
|
||
this.slideArr.forEach((v, i) => {
|
||
this.$(this.defaultConf.pagination.el).innerHTML +=
|
||
`
|
||
<div class="swiper-dot ${i == 0 ? 'swiper-active' : ''}"></div>
|
||
`
|
||
});
|
||
|
||
var Dot = this._(`${this.defaultConf.pagination.el} .swiper-dot`);
|
||
Dot.forEach((v, i) => {
|
||
v.onclick = () => {
|
||
this.UserConfig.pagination && this.ChangeDotActive(i)
|
||
this.$(this.defaultConf.wrapper).style.left = `-${i * this.f}px`;
|
||
}
|
||
})
|
||
},
|
||
|
||
// 渲染左右前进后退按钮
|
||
RenderNavigation: function () {
|
||
var prev = this.$(this.defaultConf.navigation.prevEl);
|
||
var next = this.$(this.defaultConf.navigation.nextEl);
|
||
prev.innerText = "<";
|
||
next.innerText = ">";
|
||
this.BindNavigationClick(prev, next)
|
||
},
|
||
|
||
// 为上一页下一页按钮绑定切换事件
|
||
BindNavigationClick() {
|
||
// var a = this
|
||
// 下一页
|
||
this.$(this.defaultConf.navigation.nextEl).onclick = () => {
|
||
this.animation(-this.f)
|
||
this.UserConfig.pagination && this.ChangeDotActive()
|
||
}
|
||
// 上一页
|
||
this.$(this.defaultConf.navigation.prevEl).onclick = () => {
|
||
this.animation(this.f)
|
||
this.UserConfig.pagination && this.ChangeDotActive()
|
||
}
|
||
},
|
||
|
||
// 切换动画
|
||
animation(offset) {
|
||
var swiperWrapper = this.$(this.defaultConf.wrapper);
|
||
var y = parseInt(swiperWrapper.style.left) + offset,
|
||
max = -(this.f * (this.slideArr.length - 1));
|
||
|
||
// 如果时最后一张图
|
||
if (y < max) {
|
||
if (this.defaultConf.config.loop) {
|
||
swiperWrapper.style.left = "0px";
|
||
} else if (this.defaultConf.config.auto) {
|
||
this.defaultConf.reverse = true
|
||
this.animation(this.f)
|
||
}
|
||
return;
|
||
|
||
// 判断是不是第一张图
|
||
} else if (y > 0) {
|
||
if (this.defaultConf.config.loop == false && this.defaultConf.config.auto) {
|
||
this.defaultConf.reverse = false
|
||
swiperWrapper.style.left = `${y - this.f * 2}px`
|
||
}
|
||
if (this.defaultConf.config.loop) {
|
||
swiperWrapper.style.left = `${max}px`
|
||
}
|
||
return
|
||
} else {
|
||
if (this.defaultConf.config.loop == false
|
||
&& this.defaultConf.config.auto
|
||
&& this.defaultConf.reverse) {
|
||
swiperWrapper.style.left = `${y}px`
|
||
} else {
|
||
swiperWrapper.style.left = `${y}px`
|
||
}
|
||
|
||
}
|
||
},
|
||
|
||
ChangeDotActive(type = null) {
|
||
var Dot = this._(`${this.defaultConf.pagination.el} .swiper-dot`);
|
||
var index = "";
|
||
if (type == null) {
|
||
var TotalLeft = Math.abs(parseInt(this.$(this.defaultConf.wrapper).style.left));
|
||
index = TotalLeft / this.f;
|
||
} else {
|
||
index = type;
|
||
}
|
||
|
||
// 实现调用用户传入的方法,返回下标给用户
|
||
this.CallMethods()
|
||
|
||
// 清除所有的激活样式
|
||
Dot.forEach(val => val.className = "swiper-dot");
|
||
// 为你点击的li加激活样式
|
||
Dot[index].className = "swiper-dot swiper-active";
|
||
},
|
||
|
||
AutoPlay() {
|
||
this.defaultConf.timer = setInterval(() => {
|
||
if (this.defaultConf.config.loop == false
|
||
&& this.defaultConf.config.auto
|
||
&& this.defaultConf.reverse) {
|
||
this.animation(this.f)
|
||
} else {
|
||
this.animation(-this.f)
|
||
}
|
||
this.UserConfig.pagination && this.ChangeDotActive()
|
||
}, this.defaultConf.config.time * 1000)
|
||
|
||
this.$(this.defaultConf.ParentElement).onmouseover = function () {
|
||
clearInterval(this.defaultConf.timer)
|
||
}
|
||
|
||
this.$(this.defaultConf.ParentElement).onmouseout = () => {
|
||
this.AutoPlay()
|
||
}
|
||
},
|
||
|
||
// 通过js调用此方法,实现轮播图的切换
|
||
slideTo(index) {
|
||
this.$(this.defaultConf.wrapper).style.left = `-${index * this.f}px`;
|
||
this.UserConfig.pagination && this.ChangeDotActive()
|
||
},
|
||
$: function (className) {
|
||
return document.querySelector(className)
|
||
},
|
||
_: function (className) {
|
||
return document.querySelectorAll(className)
|
||
}
|
||
}
|
||
|
||
|
||
window.swiper = Swiper
|
||
|
||
|
||
})() |