摘要:你的網(wǎng)站真的需要一個(gè)輪播圖嗎輕輕問自己三聲,谷歌一下對(duì)輪播圖效果的相關(guān)調(diào)查和建議,再?zèng)Q定是否要著手制作你的輪播圖。在接近塊間距時(shí)關(guān)閉動(dòng)畫移至另一塊相應(yīng)位置。表示接近邊緣的圖片。可把一部分放到里或輪播圖前,阻塞渲染。
輪播圖千種萬種,怎樣才能做出符合要求的輪播圖?原理上天入地,如何優(yōu)化才能達(dá)到極限絲滑?本文作者將解答這一切,通過現(xiàn)場(chǎng)制作一個(gè)輪播圖,帶你詳細(xì)了解、理解,制作 All kinds of 高性能輪播圖 !
仿自 Google Play
不過,在事實(shí)上,輪播圖的點(diǎn)擊率通常都很低,很少能引起用戶的注意,而卻往往占用了頁面某個(gè)極重要的位置。你的網(wǎng)站真的需要一個(gè)輪播圖嗎?輕輕問自己三聲,谷歌一下對(duì)輪播圖效果的相關(guān)調(diào)查和建議,再?zèng)Q定是否要著手制作你的輪播圖。
2017.8.20 更新——————————
1. 代碼簡(jiǎn)潔化 & 語言精簡(jiǎn)
2. 刪去不被推薦的有限部分
3. API 重寫
! ES6 API 重寫
ES6 啊,,牛逼啊!我TM要火啊!!
然而并沒有。
1. 結(jié)構(gòu)
div.father包裹圖片。div.viewport為視口部分。
.viewport { width: 900px; height: 300px; overflow: hidden; position: relative; } .father { height: inherit; width: 3000%; /* 子元素 float 無法撐開 */ transform: translate3d(0, 0, 0); transition: transform 0.3s ease-in-out; } .father > div { width: 550px; height: inherit; float: left; } .mother { width: 30px; height: inherit; line-height: 300px; text-align: center; cursor: pointer; user-select:none; background: rgba(0,0,0,0.15); position: absolute;top: 0; } .mother.left { left: 0 } .mother.right { right: 0 }
transform: translate3d()使用 GPU 加速。
2. 代碼實(shí)現(xiàn)
class Lunbo { constructor(element) { this.viewport = element; this.father = element.children[0]; this.photos = this.father.children; // 自設(shè)的圖片寬, 包括 margin this.photoWidth = this.photos[0].offsetWidth + parseInt(getComputedStyle(this.photos[0]).marginLeft) + parseInt(getComputedStyle(this.photos[0]).marginRight); // 注冊(cè)移動(dòng)事件 element.children[1].addEventListener("click", this.left.bind(this)); element.children[2].addEventListener("click", this.right.bind(this)); } load() { } left() { this.load(this.showingId - 1); } right() { this.load(this.showingId + 1); } }
頁面加載時(shí):選取一張作為焦點(diǎn)
切換時(shí):fatherGo(to)負(fù)責(zé)跳轉(zhuǎn)到指定的焦點(diǎn)圖;
高效 & 無限輪播
(此處以下所有代碼僅顯示添加 / 修改部分)
思路也是難點(diǎn)。一題,這樣解決:
class Lunbo { constructor(element) { // (可視寬 -焦點(diǎn)圖片寬) / 2,焦點(diǎn)圖到視口左或右的距離 this.partnerWidth = (this.viewport.clientWidth - this.photoWidth) / 2; } // 計(jì)算移動(dòng)距離 countX(id) { return -id * this.photoWidth + this.partnerWidth; } // 切換 / 載入 / 移動(dòng)圖片。無參數(shù)則除法求整,僅用來切換到一個(gè)瞎選的初始焦點(diǎn) load(newId = parseInt(this.photos.length / 2) - 1) { this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`; this.showingId = newId; } } // 切換至初始焦點(diǎn) const Example = new Lunbo(document.getElementById("example")); Example.load();
countX(id) 解釋:
若將 Id = 2 對(duì)應(yīng)圖片(第 3 張)作焦點(diǎn),向左挪過去兩張(此時(shí)該圖靠最左),后加回partnerWidth
二題:
ABCDEABCDEABCDE
三倍于展示圖,JS 動(dòng)態(tài)生成亦可。稱之三個(gè)塊。
.moving { transition: none }
在接近塊間距時(shí)關(guān)閉動(dòng)畫移至另一塊相應(yīng)位置。
class Lunbo { constructor(element) { // 表示接近邊緣的圖片 Id。接近左邊緣的即第2 張圖,右邊緣的則為倒數(shù)第二張 this.closeLeftId = 1; this.closeRightId = this.photos.length - 2; this.photosQuantity = this.photos.length / 3; // 當(dāng)運(yùn)動(dòng)到上面兩個(gè) Id 時(shí)默默移動(dòng)到的對(duì)應(yīng) Id // 接近左邊時(shí)跳轉(zhuǎn)到右邊塊的第二張 // 接近右邊則跳轉(zhuǎn)到左邊塊的倒數(shù)第二張 this.backLeftId = this.photosQuantity - 2; this.backRightId = this.photosQuantity * 2 + 1; } load(newId = parseInt(this.photos.length / 2) - 1) { this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`; if (newId === this.closeLeftId){ newId = this.backRightId; } else if (newId === this.closeRightId){ newId = this.backLeftId; } else { this.showingId = newId; return; } this.father.addEventListener("transitionend", this.backMove.bind(this, newId), {once: true}); } backMove(newId) { this.father.classList.add("moving"); this.father.clientWidth(); this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`; this.father.clientWidth(); this.father.classList.remove("moving"); this.showingId = newId; } }
4. 整理代碼
17.8.20
代碼已通過測(cè)試。你需要碼更多的代碼,兼容各個(gè)瀏覽器,以及讓它可以被更好地維護(hù),然后做得更好(裝)看(B)一些。
高級(jí)選項(xiàng)一味把放到
前只會(huì)適得其反——你需要 “加載優(yōu)化” ;焦點(diǎn)圖沒有特別樣式不夠突出——你在想 “突出焦點(diǎn)” ;需要給予用戶更多自主選擇——去看看 “位置指示”
加載優(yōu)化(重要)我們會(huì)在頁面載入后看到輪播圖從第一張轉(zhuǎn)到焦點(diǎn) —— 非常有損體驗(yàn)。可把一部分放到里或輪播圖前,阻塞渲染。最好是提前計(jì)算 translateX 。
然后刪去多余初始移動(dòng)代碼。
突出焦點(diǎn)焦點(diǎn) { 放大到110% } 其他 { 半透明;正常大小 } .focusing { opacity: 1;transform: scale3d(1.1, 1.1, 1) } .father > div { opacity: 0.4;background: #bbb;transition: inherit; }
為Lunbo.load(newId)及backMove(newId)添加‘焦點(diǎn)樣式更改’行
class Lunbo { ...(前后文省略) load(newId) { ... this.photos[showingId].classList.remove("focusing"); this.photos[newId].classList.add("focusing"); ... } ... backMove(newId) { this.father.classList.add("moving"); this.photos[newId].classList.add("focusing"); this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`; this.father.clientWidth; this.father.classList.remove("moving"); this.photos[showingId].classList.remove("focusing"); this.showingId = newId; } ... }
位置指示 & 切換........
(在更新 ES6 之前,)這里的代碼經(jīng)過了測(cè)試。
1. 顯示
.seter { width: 400px;height: 20px; position: absolute;bottom: 0;left: calc(50% - 200px); cursor: pointer; } .seter > div { width: 80px;height: 28px; background: orange; float: left; } .seter > .on { margin-top: -8px;transition: margin 0.5s ease-in-out; }
函數(shù) toSeterId 通過給予的圖片 Id 計(jì)算對(duì)應(yīng)的 seterId;
class Lunbo { constructor(element) { ... this.seters = element.children[3].children; ... // 注冊(cè)移動(dòng)事件 ... element.children[3].addEventListener("click", function (event) { if (!event.target.hasAttribute("data-seter-id")) return; this.load(Number(event.target.getAttribute("data-seter-id"))); }.bind(this)) } ... load(newId) { ... this.seters[this.toSeterId(showingId)].className = ""; this.seters[this.toSeterId(newId)].className = "on"; ... } ... toSeterId(id) { let seterId; if(id >= this.photosQuantity * 2) { seterId = id - 2 * this.photosQuantity; } else if(id >= this.photosQuantity) { seterId = id - this.photosQuantity; } return seterId; } }
2. 可切換
每次通過指示切換時(shí)先backMove至中間塊,后再進(jìn)行移動(dòng);
避免從第一張晃過中間數(shù)張至最后一張(最短路徑)。
// 繼上文 “顯示” 進(jìn)一步更改 class Lunbo { constructor(element) { ... this.magicNumber = parseInt(this.photosQuantity / 2); ... // 注冊(cè)移動(dòng)事件 ... element.children[3].addEventListener("click", function (event) { if (!event.target.hasAttribute("data-seter-id")) return; const newId = Number(event.target.getAttribute("data-seter-id")) + this.photosQuantity; // 切換至中間塊 this.backMove(toSeterId(showingId) + this.photosQuantity); // 最短路徑選擇 if (newId > this.showingId + this.magicNumber) { // XXXX則移至左塊 this.load(newId - this.photosQuantity); } else if (newId < this.showingId - this.magicNumber) { // XXXX則移至右塊 this.load(newId + this.photosQuantity); } else { // 中間塊不變 this.load(newId); } }.bind(this)) } ... }(°_°ノ)
我突然知道為什么越牛的大牛會(huì)越越來越牛了 !!!∑(?Д?ノ)ノ
其實(shí)他們本來是想寫一個(gè)文檔來說明,寫一個(gè)動(dòng)態(tài)圖演示給新手的!("▽"〃)
但是……
做完后他們一定會(huì)腰酸背痛……(;`O′)o
// 本文不再更新,除非作者開心
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/116454.html
摘要:你的網(wǎng)站真的需要一個(gè)輪播圖嗎輕輕問自己三聲,谷歌一下對(duì)輪播圖效果的相關(guān)調(diào)查和建議,再?zèng)Q定是否要著手制作你的輪播圖。在接近塊間距時(shí)關(guān)閉動(dòng)畫移至另一塊相應(yīng)位置。表示接近邊緣的圖片。可把一部分放到里或輪播圖前,阻塞渲染。 showImg(https://segmentfault.com/img/bVIHHG?w=1800&h=770); 輪播圖千種萬種,怎樣才能做出符合要求的輪播圖?原理上天...
摘要:前言年月日,微信小程序發(fā)布。這也標(biāo)志著的,阿里的,的小程序這三架馬車在年并驅(qū)騎行。傳送門試駕小程序開發(fā)工具微信開發(fā)者工具方便我們?cè)诰幾g時(shí)能夠?qū)崟r(shí)的看到界面變化,我們并不用此來進(jìn)行小程序的開發(fā),只充當(dāng)一個(gè)模儀器來使用。 showImg(https://segmentfault.com/img/bVbaqpO?w=558&h=1002); 前言 2017年1月9日,微信小程序發(fā)布。這也標(biāo)志...
摘要:前言年月日,微信小程序發(fā)布。這也標(biāo)志著的,阿里的,的小程序這三架馬車在年并驅(qū)騎行。傳送門試駕小程序開發(fā)工具微信開發(fā)者工具方便我們?cè)诰幾g時(shí)能夠?qū)崟r(shí)的看到界面變化,我們并不用此來進(jìn)行小程序的開發(fā),只充當(dāng)一個(gè)模儀器來使用。 showImg(https://segmentfault.com/img/bVbaqpO?w=558&h=1002); 前言 2017年1月9日,微信小程序發(fā)布。這也標(biāo)志...
摘要:前言年月日,微信小程序發(fā)布。這也標(biāo)志著的,阿里的,的小程序這三架馬車在年并驅(qū)騎行。傳送門試駕小程序開發(fā)工具微信開發(fā)者工具方便我們?cè)诰幾g時(shí)能夠?qū)崟r(shí)的看到界面變化,我們并不用此來進(jìn)行小程序的開發(fā),只充當(dāng)一個(gè)模儀器來使用。 showImg(https://segmentfault.com/img/bVbaqpO?w=558&h=1002); 前言 2017年1月9日,微信小程序發(fā)布。這也標(biāo)志...
摘要:綁定輪播事件然后是鼠標(biāo)移入移出事件的綁定鼠標(biāo)移入移出事件移入時(shí)停止輪播播放的定時(shí)器,移出后自動(dòng)開始下一張的播放。 通過上一篇文章的學(xué)習(xí),我們基本掌握了一個(gè)輪子的封裝和開發(fā)流程。那么這次將帶大家開發(fā)一個(gè)更有難度的項(xiàng)目——輪播圖,希望能進(jìn)一步加深大家對(duì)于面向?qū)ο蟛寮_發(fā)的理解和認(rèn)識(shí)。 So, Lets begin! 目前項(xiàng)目使用 ES5及UMD 規(guī)范封裝,所以在前端暫時(shí)只支持標(biāo)簽的引入方式...
閱讀 3898·2021-11-24 11:14
閱讀 3341·2021-11-22 13:53
閱讀 3905·2021-11-11 16:54
閱讀 1601·2021-10-13 09:49
閱讀 1238·2021-10-08 10:05
閱讀 3413·2021-09-22 15:57
閱讀 1768·2021-08-16 11:01
閱讀 985·2019-08-30 15:55