(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 += `
` }); 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 })()