摘要:同理,向左輪播至第一張圖片時,也會取消后輪播圖定位至第六張圖片而后再度開啟。續判斷是否開啟自動輪播,如是則自動輪播加入事件監聽監聽鼠標移入事件,當鼠標移入的時候,停止自動滾動。監聽左右按鈕的點擊,執行上一張,下一張圖的輪播效果。
1. 前言
早在幾個月前,就想自己動手寫個輪播圖組件,因此也看了許多文章,斷斷續續過了幾個月,今天終于有時間騰出手來給此插件做個總結,因此有了這篇文章。話不多說,先上 Demo, 效果如下:
2. HTML and CSS本文不討論html,css的實現方式,直接貼上代碼
Suporka Vue App
/*樣式代碼*/ * { margin: 0; padding: 0; } div { margin: 0; border: 0; padding: 0; } #carousal { width: 557px; overflow: hidden; position: relative; } #wrapper { display: box; /* OLD - Android 4.4- */ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; -webkit-flex-wrap: nowrap; -moz-flex-wrap: nowrap; -ms-flex-wrap: nowrap; -o-flex-wrap: nowrap; flex-wrap: nowrap; white-space: nowrap; position: relative; left: 0; } .suporka-carousel__arrow { /* display: none; */ border: none; outline: none; padding: 0; margin: 0; height: 36px; width: 36px; cursor: pointer; transition: 0.3s; border-radius: 50%; background-color: rgba(31, 45, 61, 0.5); color: #fff; position: absolute; top: 50%; z-index: 10; transform: translateY(-50%); text-align: center; font-size: 12px; font-weight: 600; } .suporka-carousel__arrow--right { right: -38px; } .suporka-carousel__arrow--left { left: -38px; } #carousal:hover > .suporkal-carousel__arrow { display: block; } #carousal:hover .suporka-carousel__arrow--right { right: 16px; } #carousal:hover .suporka-carousel__arrow--left { left: 16px; } #suporka-dot { position: absolute; bottom: 20px; left: 50%; transform: translate(-50%, 0); } #suporka-dot span { width: 10px; height: 10px; border-radius: 50%; margin: 0 10px; display: inline-block; background: #999; } #suporka-dot .suporka-dot--acitve { background: #fff; }3. javascript 實現輪播圖功能
本插件是用 es6 寫的,當然考慮兼容性,你可以選擇 babel 進行編譯,本文不做闡述。
1. 首先,創建一個 carousal 類它有一些默認參數,如time(圖片輪播間隔),transition (轉場動畫時間),autoScroll(是否自動輪播),showDot(是否顯示底部小圓點)。然后將頁面的一些元素掛載在類的屬性上。
class Carousal { constructor(userOption) { this.option = { time: 4000, transition: 0.8, autoScroll: true, showDot: false }; // 當前索引 this.number = 1; // 定時器 this.timer = null; this.interval = null; this.carousal = document.getElementById("carousal"); this.wrapper = document.querySelector("#wrapper"); this.childrenLength: document.getElementById("wrapper").children.length; this.init(userOption); } }2. 初始化dom
當然,默認參數是可以修改的,所以類傳入了一個 userOption 對象, 在構造函數中將用戶設置的參數覆蓋默認參數,在this.init(userOption) 方法中執行覆蓋。
輪播圖輪播的原理是:在輪播圖組首位添加一個末位圖片的副本,同時也在輪播圖末位添加一個首位圖片的副本,大概就是 5 1 2 3 4 5 1 , 此時共有7張圖片,當向右輪播至第七張圖片‘1’ 時, 取消transition后輪播圖定位至第二張圖片 ‘1’, 此時再度開啟transition 。同理,向左輪播至第一張圖片“5”時,也會取消transition后輪播圖定位至第六張圖片 ‘5’, 而后再度開啟 transition。
因此,我們需要手動在dom結構中插入這兩個首尾圖片。pushItem() 方法正是為此而生。
class Carousal { //... init(userOption) { // 合并用戶配置 if (Object.assign) { Object.assign(this.option, userOption); } else { // 不支持 Object.assign 就調用 extend 方法 this.extend(this.option, userOption, true); } // 設置動畫 transition this.wrapper.style.transition = `all ${this.option.transition}s`; this.wrapper.style["-moz-transition"] = `all ${this.option.transition}s`; this.wrapper.style["-webkit-transition"] = `all ${this.option.transition}s`; this.wrapper.style["-o-transition"] = `all ${this.option.transition}s`; // 首尾添加元素 this.pushItem(); } // 合并屬性方法 extend(o, n, override) { for (var p in n) { if (n.hasOwnProperty(p) && (!o.hasOwnProperty(p) || override)) o[p] = n[p]; } } // 初始化添加首尾子元素 pushItem() { let movePx = this.carousal.offsetWidth; // 獲取輪播圖寬度 let first = this.wrapper.children[0].cloneNode(true); let last = this.wrapper.children[this.childrenLength - 1].cloneNode(true); let parent = this.wrapper; parent.appendChild(first); parent.insertBefore(last, parent.children[0]); this.wrapper.style.left = this.wrapper.offsetLeft - movePx + "px"; } }
插入輪播圖片之后,判斷是否需要插入底部小圓點。requestAnimFrame()用于實現持續的動畫效果。
class Carousal { init() { //...續 this.pushItem(); if (this.option.showDot) { let node = document.createElement("div"); node.setAttribute("id", "suporka-dot"); node.innerHTML = `${"".repeat(this.childrenLength)}`; this.carousal.appendChild(node); this.dot = document.getElementById("suporka-dot"); this.dot.firstChild.setAttribute("class", "suporka-dot--acitve"); } // 判斷是否開啟自動輪播,如是則自動輪播 if (this.option.autoScroll) this.requestAnimFrame(this.autoMove()); } requestAnimFrame() { return ( window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60); } ); } }3. 加入事件監聽
監聽鼠標移入事件,當鼠標移入的時候,停止自動滾動。
監聽左右按鈕的點擊,執行上一張,下一張圖的輪播效果。
class Carousal { init() { //...續 if (this.option.autoScroll) this.requestAnimFrame(this.autoMove()); this.addEventListener(); } // 添加事件 addEvent(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } } // 事件監聽 addEventListener() { if (this.option.autoScroll) { this.addEvent(this.carousal, "mouseover", event => { clearInterval(this.interval); }); this.addEvent(this.carousal, "mouseout", event => { this.autoMove(); }); } let prev = document.getElementById("suporka-prev-btn"); let next = document.getElementById("suporka-next-btn"); if (prev && next) { this.addEvent(prev, "click", event => { this.prev(); }); this.addEvent(next, "click", event => { this.next(); }); } } }4. 自動輪播
定時動畫,并且如果存在底部小圓點,修改其類名,達到與輪播圖同步的效果。
// 自動輪播 class Carousal { // ... autoMove() { let movePx = this.carousal.offsetWidth; this.interval = setInterval(() => { this.number += 1; this.wrapper.style.left = 0 - movePx * this.number + "px"; if (this.number === this.childrenLength + 1) this.startMove(); if (this.dot) this.setDotClass( this.dot.children, this.number - 1, "suporka-dot--acitve" ); }, this.option.time); } // 開始移動 startMove() { this.number = 1; this.timer = setTimeout(() => { this.wrapper.style.transition = `none`; this.wrapper.style.left = -this.carousal.offsetWidth + "px"; setTimeout(() => { this.wrapper.style.transition = `all ${ this.option.transition }s`; }, 100); }, this.option.transition * 1000); } // 設置小圓點樣式 setDotClass(parent, index, cls) { // 沒有小圓點就返回 if (!this.dot) return false; for (let i = 0; i < parent.length; i++) { removeClass(parent[i], cls); } addClass(parent[index], cls); } } // 三個類名操作方法 function hasClass(ele, cls) { if (ele.className) return ele.className.match(new RegExp("(s|^)" + cls + "(s|$)")); else return false; } function addClass(ele, cls) { if (!hasClass(ele, cls)) ele.className += " " + cls; } function removeClass(ele, cls) { if (hasClass(ele, cls)) { let reg = new RegExp("(s|^)" + cls + "(s|$)"); ele.className = ele.className.replace(reg, " "); } }5. 實現上一張,下一張輪播功能
class Carousal { //... // prev上一張 prev() { let movePx = this.carousal.offsetWidth; this.number -= 1; this.wrapper.style.left = 0 - movePx * this.number + "px"; if (this.number === 0) this.goLastOne(); if (this.dot) this.setDotClass( this.dot.children, this.number - 1, "suporka-dot--acitve" ); } // 下一張 next() { let movePx = this.carousal.offsetWidth; this.number += 1; this.wrapper.style.left = 0 - movePx * this.number + "px"; if (this.number === this.childrenLength + 1) this.startMove(); if (this.dot) this.setDotClass( this.dot.children, this.number - 1, "suporka-dot--acitve" ); } // 去到最后一張 goLastOne() { this.number = this.childrenLength; this.timer = setTimeout(() => { this.wrapper.style.transition = `none`; this.wrapper.style.left = -this.carousal.offsetWidth * this.childrenLength + "px"; setTimeout(() => { this.wrapper.style.transition = `all ${ this.option.transition }s`; }, 100); }, this.option.transition * 1000); } }4.優化及其他
最后,代碼需經過babel轉譯,并且以 umd 的形式支持瀏覽器直接引入,requirejs 及 commonjs 導入,詳細做法可以參考我之前的一篇文章《ES6 手寫一個“辨色”小游戲》。也可以參考我在 github 上的代碼, 歡迎 fork and star .
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100485.html
摘要:是一款輪播圖插件,我是用在里面,方便省事兒。官網地址地址安裝安裝完成之后,我沒有在中注冊它,而是在使用頁面注冊的。因為通常來說輪播圖只會在一個應用的首頁展示,所以就沒必要在全局注冊它,只用在頁面注冊使用一下就可以了。 swipe是一款輪播圖插件,我是用在vue里面,方便省事兒。swipe里面有很多關于滑動的組建,我只用過輪播圖,如果以后有時間,可以再看看官網上別的組件介紹。官網地址 g...
摘要:老姚淺談怎么學鑒于時不時,有同學私信問我老姚,下同怎么學前端的問題。擼碼聽歌,全局控制。 淺析用 js 解析 xml 的方法 由于項目上需要解析 xml,于是各種百度,然后自己總結了下各個主流瀏覽器解析 xml 的方法,只能是很淺顯的知道他的用法,但是還沒有深層次的研究。 裝 X - 建立自己的斗圖網站庫 之前加過一個斗圖群,看到很多經典的表情,然后就收藏到了 QQ, 迫于本屌絲開不起...
摘要:頁面調試騰訊開發維護的代碼調試發布,錯誤監控上報,用戶問題定位。同樣是由騰訊開發維護的代碼調試工具,是針對移動端的調試工具。前端業務代碼工具庫。動畫庫動畫庫,也是目前通用的動畫庫。 本人微信公眾號:前端修煉之路,歡迎關注 本篇文章整理自己使用過的和看到過的一些插件和工具,方便日后自己查找和使用。 另外,感謝白小明,文中很多的工具來源于此。 彈出框 layer:http://layer....
閱讀 4160·2021-11-22 13:52
閱讀 2074·2021-09-22 15:12
閱讀 1121·2019-08-30 15:53
閱讀 3455·2019-08-29 17:12
閱讀 2190·2019-08-29 16:23
閱讀 1647·2019-08-26 13:56
閱讀 1772·2019-08-26 13:44
閱讀 1880·2019-08-26 11:56