🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、幻灯片的 HTML 和 CSS ``` <div id="slider" class="slider"> <div class="slider-item-container"> <div class="slider-item"> <a href="###" class="slider-link"> <img src="img/1.jpg" alt="slider" class="slider-img"> </a> </div> <div class="slider-item"> <a href="###" class="slider-link"> <img src="img/2.jpg" alt="slider" class="slider-img"> </a> </div> <div class="slider-item"> <a href="###" class="slider-link"> <img src="img/3.jpg" alt="slider" class="slider-img"> </a> </div> <div class="slider-item"> <a href="###" class="slider-link"> <img src="img/4.jpg" alt="slider" class="slider-img"> </a> </div> <div class="slider-item"> <a href="###" class="slider-link"> <img src="img/5.jpg" alt="slider" class="slider-img"> </a> </div> </div> <div class="slider-indicator-container"> <span class="slider-indicator"></span> <span class="slider-indicator"></span> <span class="slider-indicator"></span> <span class="slider-indicator"></span> <span class="slider-indicator"></span> </div> </div> ``` ``` /*css reset*/ * { box-sizing: border-box; padding: 0; margin: 0; } img { border: none; vertical-align: top; } a { -webkit-tap-highlight-color: transparent; } /*slider*/ .slider { overflow: hidden; position: relative; width: 100%; height: 183px; } .slider-item-container, .slider-item, .slider-link, .slider-img { width: 100%; height: 100%; } .slider-item-container { display: flex; transition: transform 0; } .slider-item { flex-shrink: 0; } .slider-link { display: block; } .slider-indicator-container { position: absolute; bottom: 10px; width: 100%; text-align: center; } .slider-indicator { display: inline-block; width: 8px; height: 8px; background-color: #000; opacity: 0.2; border-radius: 50%; margin-right: 8px; } .slider-indicator-active { background-color: #007aff; opacity: 1; } ``` ## 二、封装 Slider.js ``` function Slider(el, options) { var defaults = { initIndex: 0, speed: 300, hasIndicator: false }; this.options = {}; this.options.initIndex = typeof options.initIndex !== 'undefined' ? options.initIndex : defaults.initIndex; this.options.speed = typeof options.speed !== 'undefined' ? options.speed : defaults.speed; this.options.hasIndicator = typeof options.hasIndicator !== 'undefined' ? options.hasIndicator : defaults.hasIndicator; this.el = el; this.itemContainer = el.querySelector('.slider-item-container'); this.items = this.itemContainer.children; this.distancePerSlide = this.items[0].offsetWidth; this.minIndex = 0; this.maxIndex = this.items.length - 1; // this.index = this.options.initIndex; this.index = this._adjustIndex(this.options.initIndex); this.move(this.getDistanceByIndex(this.index)); if (this.options.hasIndicator) { this._createIndicators(); this._setIndicatorActive(this.index); } } Slider.prototype.to = function (index, cb) { this.index = index; this._setTransitionSpeed(this.options.speed); this.move(this.getDistanceByIndex(this.index)); var self = this; this.itemContainer.addEventListener('transitionend', function () { self._setTransitionSpeed(0); if (typeof cb === 'function') { cb(); } }, false); if (this.options.hasIndicator) { this._setIndicatorActive(this.index); } }; Slider.prototype._setTransitionSpeed = function (speed) { this.itemContainer.style.transitionDuration = speed + 'ms'; }; Slider.prototype.prev = function (cb) { this.to(this.index - 1, cb); }; Slider.prototype.next = function (cb) { this.to(this.index + 1, cb); }; Slider.prototype._adjustIndex = function (index) { if (index < this.minIndex) { index = this.minIndex; } else if (index > this.maxIndex) { index = this.maxIndex; } return index; }; Slider.prototype.move = function (distance) { this.itemContainer.style.transform = 'translate3d(' + distance + 'px, 0, 0)'; }; Slider.prototype.getDistanceByIndex = function (index) { return -index * this.distancePerSlide; }; Slider.prototype._createIndicators = function () { var indicatorContainer = document.createElement('div'); var html = ''; indicatorContainer.className = 'slider-indicator-container'; for (var i = 0; i <= this.maxIndex; i++) { html += '<span class="slider-indicator"></span>'; } indicatorContainer.innerHTML = html; this.el.appendChild(indicatorContainer); }; Slider.prototype._setIndicatorActive = function (index) { this.indicators = this.indicators || this.el.querySelectorAll('.slider-indicator'); for (var i = 0; i < this.indicators.length; i++) { this.indicators[i].classList.remove('slider-indicator-active'); } this.indicators[index].classList.add('slider-indicator-active'); }; Slider.prototype.getItemContainer = function () { return this.itemContainer; }; Slider.prototype.getIndex = function () { return this.index; }; Slider.prototype.getDistancePerSlide = function () { return this.distancePerSlide; }; ``` ## 三、测试 Slider ``` <button id="prev">prev</button> <button id="next">next</button> var slider = new Slider(document.getElementById('slider'), { initIndex: 0, // 初始显示第几张幻灯片,从0开始 speed: 300, // 幻灯片的切换速度 hasIndicator: true // 是否需要指示器indicator }); document.getElementById('prev').addEventListener('click', function () { // 切换上一张幻灯片 slider.prev(); }, false); document.getElementById('next').addEventListener('click', function () { // 切换下一张幻灯片 slider.next(); }, false); ``` ## 四、hammer.js ``` var slider = new Slider(document.getElementById('slider'), { initIndex: 0, // 初始显示第几张幻灯片,从0开始 speed: 300, // 幻灯片的切换速度 hasIndicator: true // 是否需要指示器indicator }); var hammer = new Hammer(slider.getItemContainer()); var isSwiping = false; hammer.on('panmove', function (ev) { var distance = ev.deltaX + slider.getDistanceByIndex(slider.getIndex()); slider.move(distance); }); hammer.on('panend', function (ev) { if (isSwiping) return; var distance = ev.deltaX + slider.getDistanceByIndex(slider.getIndex()); var index = getIndexByDistance(distance); slider.to(index); }); // 根据容器移动的距离获取索引 function getIndexByDistance(distance) { if (distance > 0) { return 0; } else { return Math.round(-distance / slider.getDistancePerSlide()); } } hammer.on('swipeleft', function (ev) { // next isSwiping = true; slider.next(function () { isSwiping = false; }); }); hammer.on('swiperight', function (ev) { // prev isSwiping = true; slider.prev(function () { isSwiping = false; }); }); ```