摘要:前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。作為演示,用標(biāo)簽代替了圖片。關(guān)鍵使用不同背景色的替代圖片。
前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。
先看看在線DEMO:原生JS循環(huán)播放圖片輪播組件?(支持IE8+,本文中的在線demo均未經(jīng)過(guò)壓縮,可以直接在瀏覽器中調(diào)試)
以及GitHub倉(cāng)庫(kù)地址及完整代碼:JuniorTour/simple-standard-js-carousel
一、思路講解: 1.先說(shuō)基本的非循環(huán)無(wú)過(guò)渡圖片輪播:這個(gè)思路還是很簡(jiǎn)單的,通過(guò)觀察一些圖片輪播就可以發(fā)現(xiàn),圖片輪播一般是以一個(gè)尺寸較小的父元素作為窗口,包裹住一組較長(zhǎng)的長(zhǎng)條狀的項(xiàng)目(item)子元素,再利用?overflow: hidden; ,將父元素作為“窗口”,只顯示出的項(xiàng)目子元素的一部分,并通過(guò)改變項(xiàng)目子元素的定位或translate3d屬性,實(shí)現(xiàn)多張圖片項(xiàng)目動(dòng)態(tài)播放。
基本原理可以參考這個(gè)demo:圖片輪播基本原理演示
2.比較有意思的其實(shí)是循環(huán)的功能:但是這樣簡(jiǎn)單的輪播是不會(huì)循環(huán)播放的,也就是說(shuō)當(dāng)一輪圖片項(xiàng)目(item)播放到結(jié)尾;或者當(dāng)在第一張圖(第一個(gè)項(xiàng)目)繼續(xù)向前時(shí),就會(huì)超出內(nèi)容子元素,出現(xiàn)空白部分,這一般不是我們想要的結(jié)果。
有多種思路可以實(shí)現(xiàn)循環(huán)播放,我觀察到淘寶網(wǎng)首頁(yè)的圖片輪播是這樣的思路:
復(fù)制開(kāi)頭和結(jié)尾的項(xiàng)目,并分別放在開(kāi)頭和結(jié)尾,當(dāng)播放到開(kāi)頭或結(jié)尾的項(xiàng)目,繼續(xù)播放,需要循環(huán)時(shí),臨時(shí)取消transition屬性,并立即用定位跳轉(zhuǎn)至相應(yīng)的真正的開(kāi)頭或結(jié)尾之后,再恢復(fù)原來(lái)的transition,繼續(xù)正常滾動(dòng)播放,從而利用視覺(jué)上的“欺騙”,實(shí)現(xiàn)帶有過(guò)渡效果的循環(huán)播放。
相應(yīng)的原理可以參考這個(gè)demo:圖片輪播循環(huán)原理演示
二、HTML標(biāo)記部分核心理念是簡(jiǎn)潔、語(yǔ)義化。這部分因?yàn)槲覍W(xué)過(guò)bootstrap框架所以借鑒了bootstrap的HTML標(biāo)記結(jié)構(gòu)。
整體結(jié)構(gòu)為:
外層的.carousel-wrapper包裹著輪播的三個(gè)主要部分,分別是:
.carousel-item-wrapper:項(xiàng)目?jī)?nèi)容部分(作為演示,本文中的demo使用a標(biāo)簽代替了圖片,大家可以自行嘗試替換為圖片;同時(shí)添加了文字序號(hào)標(biāo)記,以便于觀察理解,尤其要注意兩個(gè)復(fù)制的開(kāi)頭和結(jié)尾項(xiàng)目copy-1和copy-5)。
.carousel-control-wrapper:控制按鈕部分,即兩個(gè)用于控制左右移動(dòng)的按鈕。
.carousel-index-wrapper:索引按鈕部分,即圖片輪播中的那一排“小圓點(diǎn)”。為了便于用JS操控,我添加了id作為“鉤子”。而bootstrap在這里用的是自定義的data屬性。
三、CSS樣式部分
總的來(lái)說(shuō)比較簡(jiǎn)單,重要的地方我加上了注釋,有存疑的地方,歡迎和我交流。
/*reset*/ * { border: none; padding: 0; margin: 0; } button { outline: none; } li { list-style: none; } .carousel-wrapper { width:520px; height:280px; overflow: hidden; /*關(guān)鍵*/ position: relative; margin: 100px auto; } .carousel-item-wrapper { width:3640px; height:280px; position: absolute; top: 0; left: -520px; transition: left .2s ease-in; } .carousel-item a { display: block; background-color: red; width:520px; height: 280px; } /*使用不同背景色的a替代圖片。*/ .carousel-item:nth-child(1) a { background-color: rgb(129,194,214); /*第五張圖片的復(fù)制*/ } .carousel-item:nth-child(2) a { background-color: rgb(129,146,214); } .carousel-item:nth-child(3) a { background-color: rgb(217,179,230); } .carousel-item:nth-child(4) a { background-color: rgb(220,247,161); } .carousel-item:nth-child(5) a { background-color: rgb(131,252,216); } .carousel-item:nth-child(6) a { background-color: rgb(129,194,214); } .carousel-item:nth-child(7) a { background-color: rgb(129,146,214); /*第一張圖片的復(fù)制*/ } .carousel-item { float: left; } .carousel-index-mark { font-size:60px; color: black; position: absolute; top: 0; } .carousel-control-wrapper { transition: all .2s; } .carousel-wrapper:hover button { display: block; } .carousel-control-wrapper button { transition: all .2s linear; display: none; width:24px; height:36px; line-height:36px; background-color: rgba(0,0,0,.3); color: #fff; position: absolute; top: 50%; cursor: pointer; } button#prev { left:0; } button#next { right:0; } button i { font-size: 18px; } .carousel-index-wrapper { width:65px; height:13px; overflow: hidden; position: absolute; bottom:15px; left:50%; margin-left: -33px; } .carousel-index-btn { width:9px; height:9px; float: left; margin:2px; background-color: #b7b7b7; border-radius: 50%; text-indent: -999em; /*這個(gè)-999em的文字對(duì)齊聲明有助于增強(qiáng)可訪問(wèn)性。*/ cursor: pointer; } .active-carousel-index-btn { background-color: #f44103; }四、JS部分
這一塊是主要部分,內(nèi)容較多,因此我們逐步來(lái)實(shí)現(xiàn)各部分功能以便于理解。
0.功能和結(jié)構(gòu)分析:根據(jù)最開(kāi)始的思路講解,我們把這個(gè)輪播的JavaScript功能大致分為以下4個(gè)部分:
1.左右滑動(dòng)按鈕功能
2.索引按鈕跳轉(zhuǎn)功能
3.自動(dòng)播放功能
4.循環(huán)播放功能。
我們來(lái)分別逐步實(shí)現(xiàn)。
1.實(shí)現(xiàn)左右滑動(dòng)按鈕功能:function addLoadEvent(func) { var oldLoad = window.onload; if (typeof oldLoad != "function") { window.onload = func; } else { window.onload = function () { oldLoad(); func(); } } } //給文檔加載完成后的load事件綁定相應(yīng)的處理函數(shù): addLoadEvent(preventDefaultAnchors); addLoadEvent(carouselControl); /*用一個(gè)對(duì)象把輪播組件的相關(guān)參數(shù)封裝起來(lái),優(yōu)點(diǎn)是靈活便于擴(kuò)展升級(jí);缺點(diǎn)是同時(shí)也增加了文件的體積。*/ var carouselInfo = { itemWidth: 520, trueItemNum: 5, itemNum: 7, totalWidth: 7 * 520 }; //阻止a標(biāo)簽?zāi)J(rèn)的點(diǎn)擊跳轉(zhuǎn)行為 function preventDefaultAnchors() { var allAnchors = document.querySelectorAll("a"); for (var i = 0; i < allAnchors.length; i++) { allAnchors[i].addEventListener("click", function (e) { e.preventDefault(); }, false); } } function carouselControl () { var prev = document.querySelector("#prev"); var next = document.querySelector("#next"); var carouselWrapper = document.querySelector(".carousel-wrapper"); prev.onclick = function () { slide(-1); }; next.onclick = function () { slide(1); }; } function slide(slideItemNum) { var itemWrapper=document.querySelector(".carousel-item-wrapper"); var currentLeftOffset=(itemWrapper.style.left)?parseInt(itemWrapper.style.left): 0, targetLeftOffset=currentLeftOffset-(slideItemNum*carouselInfo.itemWidth); itemWrapper.style.left=targetLeftOffset+"px"; }
第1步的demo:carousel-step-1
2.實(shí)現(xiàn)索引按鈕跳轉(zhuǎn)功能:function carouselControl() { var prev = document.querySelector("#prev"); var next = document.querySelector("#next"); var carouselWrapper = document.querySelector(".carousel-wrapper"); //添加索引按鈕的引用 var indexBtns = document.querySelectorAll(".carousel-index-btn"); //標(biāo)記當(dāng)前所在的圖片編號(hào),用于配合控制.index-btn。 var currentItemNum = 1; prev.onclick = function () { //把滑動(dòng)功能和切換索引按鈕功能裝入一個(gè)函數(shù)之中,以便于獲取當(dāng)前索引: currentItemNum=prevItem(currentItemNum); }; next.onclick = function () { //把滑動(dòng)功能和切換索引按鈕功能裝入一個(gè)函數(shù)之中,以便于獲取當(dāng)前索引: currentItemNum=nextItem(currentItemNum); }; for (var i = 0; i < indexBtns.length; i++) { //利用立即調(diào)用函數(shù),解決閉包的副作用,傳入相應(yīng)的index值 (function (i) { indexBtns[i].onclick = function () { slideTo(i+1); currentItemNum=i+1; } })(i); } } function nextItem(currentItemNum) { slide(1); currentItemNum += 1; if (currentItemNum == 6) currentItemNum = 1; switchIndexBtn(currentItemNum); return currentItemNum; } function prevItem(currentItemNum) { slide(-1); currentItemNum -= 1; if (currentItemNum == 0) currentItemNum = 5; switchIndexBtn(currentItemNum); return currentItemNum; } //添加直接跳轉(zhuǎn)函數(shù): function slideTo(targetNum) { var itemWrapper=document.querySelector(".carousel-item-wrapper"); itemWrapper.style.left=-(targetNum*carouselInfo.itemWidth)+"px"; switchIndexBtn(targetNum); } function slide(slideItemNum) { var itemWrapper = document.querySelector(".carousel-item-wrapper"); var currentLeftOffset = (itemWrapper.style.left) ? parseInt(itemWrapper.style.left) : 0, targetLeftOffset = currentLeftOffset - (slideItemNum * carouselInfo.itemWidth); itemWrapper.style.left = targetLeftOffset + "px"; } function switchIndexBtn(targetNum) { //切換當(dāng)前的索引按鈕 //刪除過(guò)去激活的.active-carousel-index-btn var activeBtn=document.querySelector(".active-carousel-index-btn"); activeBtn.className=activeBtn.className.replace(" active-carousel-index-btn",""); //添加新的激活索引按鈕 var targetBtn=document.querySelectorAll(".carousel-index-btn")[targetNum-1]; targetBtn.className+=" active-carousel-index-btn"; }
第2步的demo:carousel-step-2
3.實(shí)現(xiàn)自動(dòng)播放功能:function carouselControl() { //省略前面重復(fù)的代碼...... for (var i = 0; i < indexBtns.length; i++) { //利用立即調(diào)用函數(shù),解決閉包的副作用,傳入相應(yīng)的index值 (function (i) { indexBtns[i].onclick = function () { slideTo(i+1); currentItemNum=i+1; } })(i); } //添加定時(shí)器 var scrollTimer; function play() { scrollTimer=setInterval(function () { currentItemNum=nextItem(currentItemNum); },2000); } play(); function stop() { clearInterval(scrollTimer); } //綁定事件 carouselWrapper.addEventListener("mouseover",stop); carouselWrapper.addEventListener("mouseout",play,false); /*DOM二級(jí)的addEventListener相對(duì)于on+sth的優(yōu)點(diǎn)是: * 1.addEventListener可以先后添加多個(gè)事件,同時(shí)這些事件還不會(huì)相互覆蓋。 * 2.addEventListener可以控制事件觸發(fā)階段,通過(guò)第三個(gè)可選的useCapture參數(shù)選擇冒泡還是捕獲。 * 3.addEventListener對(duì)任何DOM元素都有效,而不僅僅是HTML元素。*/ }
第3步的demo:carousel-step-3
4.關(guān)鍵點(diǎn):實(shí)現(xiàn)循環(huán)播放功能:function slide(slideItemNum) { var itemWrapper = document.querySelector(".carousel-item-wrapper"); var currentLeftOffset = (itemWrapper.style.left) ? parseInt(itemWrapper.style.left) : 0, targetLeftOffset = currentLeftOffset - (slideItemNum * carouselInfo.itemWidth); /*不在這里跳轉(zhuǎn)了。先處理偏移值,實(shí)現(xiàn)循環(huán),再跳轉(zhuǎn)。*/ //itemWrapper.style.left = targetLeftOffset + "px"; switch (true) { /*switch 的語(yǔ)法是:當(dāng)case之中的表達(dá)式等于switch (val)的val時(shí),執(zhí)行后面的statement(語(yǔ)句)。*/ case (targetLeftOffset>0): itemWrapper.style.transition="none"; itemWrapper.style.left=-carouselInfo.trueItemNum*carouselInfo.itemWidth+"px"; /*此處即相當(dāng)于:itemWrapper.style.left="-2600px";*/ targetLeftOffset=-(carouselInfo.trueItemNum-1)*carouselInfo.itemWidth; //相當(dāng)于:targetLeftOffset=-2080; break; case (targetLeftOffset<-(carouselInfo.totalWidth-carouselInfo.itemWidth)): //此處即相當(dāng)于:targetLeftOffset<-3120 itemWrapper.style.transition="none"; itemWrapper.style.left=-carouselInfo.itemWidth+"px"; //相當(dāng)于:itemWrapper.style.left="-520px"; targetLeftOffset=-carouselInfo.itemWidth*2; //相當(dāng)于:targetLeftOffset=-1040; break; } /*這里我使用了setTimeout(fn,0)的hack * 參考bootstrap的carousel.js源碼,似乎也利用了setTimeout(fn,0)這一hack。 * * stackoverflow上有對(duì)這一hack的討論和解釋: * http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful * 根據(jù)第二個(gè)回答,我個(gè)人的理解是:setTimeout(fn,0)相當(dāng)于異步執(zhí)行內(nèi)部的代碼fn, * 具體到這個(gè)輪播,就是在上一輪非過(guò)渡定位的頁(yè)面渲染工作(switch語(yǔ)句內(nèi)部的case)結(jié)束之后,再執(zhí)行setTimeout內(nèi)部的過(guò)渡位移工作。 * 從而避免了,非過(guò)渡的定位還未結(jié)束,就恢復(fù)了過(guò)渡屬性,使得這一次非過(guò)渡的定位也帶有過(guò)渡效果。 **/ //各位可以試一試,把setTimeout內(nèi)部的代碼放在外部,“循環(huán)”時(shí)會(huì)有什么樣的錯(cuò)誤效果。 //itemWrapper.style.transition="left .2s ease-in"; //itemWrapper.style.left=targetLeftOffset+"px"; setTimeout(function () { itemWrapper.style.transition="left .2s ease-in"; itemWrapper.style.left=targetLeftOffset+"px"; },20); }
第4步的demo:carousel-step-4
至此,就完成了一個(gè)完整的循環(huán)播放圖片輪播,欣賞一下自己的杰作吧~~~ヾ(??▽?)ノ
五、源碼及示例: 1.GitHub倉(cāng)庫(kù)地址及完整代碼:JuniorTour/simple-standard-js-carousel 2.在線demo:原生JS循環(huán)播放圖片輪播組件?很慚愧,只做了一點(diǎn)簡(jiǎn)單的工作。如果覺(jué)得本文不錯(cuò)的話,歡迎給我的GitHub點(diǎn)贊!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83417.html
摘要:前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。作為演示,用標(biāo)簽代替了圖片。關(guān)鍵使用不同背景色的替代圖片。 前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。 先看看在線DEMO:原生JS循環(huán)播放圖片輪播組件?(支持IE8+,本文中的在線demo均未經(jīng)過(guò)壓縮...
摘要:前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。作為演示,用標(biāo)簽代替了圖片。關(guān)鍵使用不同背景色的替代圖片。 前段時(shí)間學(xué)習(xí)了淘寶首頁(yè)的靜態(tài)頁(yè)面,其中收獲較大的的就是這個(gè)循環(huán)播放的圖片輪播組件,本文就將相關(guān)制作經(jīng)驗(yàn)分享給大家。 先看看在線DEMO:原生JS循環(huán)播放圖片輪播組件?(支持IE8+,本文中的在線demo均未經(jīng)過(guò)壓縮...
摘要:綁定輪播事件然后是鼠標(biāo)移入移出事件的綁定鼠標(biāo)移入移出事件移入時(shí)停止輪播播放的定時(shí)器,移出后自動(dòng)開(kāi)始下一張的播放。 通過(guò)上一篇文章的學(xué)習(xí),我們基本掌握了一個(gè)輪子的封裝和開(kāi)發(fā)流程。那么這次將帶大家開(kāi)發(fā)一個(gè)更有難度的項(xiàng)目——輪播圖,希望能進(jìn)一步加深大家對(duì)于面向?qū)ο蟛寮_(kāi)發(fā)的理解和認(rèn)識(shí)。 So, Lets begin! 目前項(xiàng)目使用 ES5及UMD 規(guī)范封裝,所以在前端暫時(shí)只支持標(biāo)簽的引入方式...
摘要:昨天學(xué)習(xí)了輪播的原理,今天再來(lái)看看無(wú)縫輪播的技術(shù)。無(wú)縫輪播無(wú)縫輪播的原來(lái)大致類似小時(shí)候跳大繩,小朋友一個(gè)個(gè)進(jìn)入,一個(gè)個(gè)出來(lái),出來(lái)后排到隊(duì)伍末尾,等在著進(jìn)入,無(wú)縫輪播也類似這種機(jī)制。 昨天學(xué)習(xí)了輪播的原理,今天再來(lái)看看無(wú)縫輪播的技術(shù)。 昨天學(xué)習(xí)的輪播機(jī)制類似于走馬燈,所有圖片排成一排,輪流在你眼前走過(guò),你就會(huì)感覺(jué)他們動(dòng)起來(lái)了,今天學(xué)的無(wú)縫輪播就不能用昨天的思路了,它和昨天最大的區(qū)別是,從...
摘要:鼠標(biāo)放到輪播圖的圖片上時(shí)不再自動(dòng)輪播并且左右箭頭顯示出來(lái),鼠標(biāo)移開(kāi)時(shí)左右箭頭隱藏掉并且自動(dòng)輪播。核心原理清除定時(shí)器,綁定事件,重構(gòu)下代碼封裝出往右往左輪播函數(shù)和自動(dòng)輪播函數(shù)。 需求與分析 需求:循環(huán)無(wú)縫自動(dòng)輪播五張圖,按左右箭頭可以手動(dòng)切換圖片,鼠標(biāo)點(diǎn)擊輪播圖下面按鈕 1 2 3 4 5會(huì)跳轉(zhuǎn)到對(duì)應(yīng)的第1 2 3 4 5張圖片。鼠標(biāo)放到輪播圖的圖片上時(shí)不再自動(dòng)輪播并且左右箭頭顯示出來(lái),...
閱讀 1872·2023-04-26 02:32
閱讀 601·2021-11-18 13:12
閱讀 2480·2021-10-20 13:48
閱讀 2559·2021-10-14 09:43
閱讀 3870·2021-10-11 10:58
閱讀 3595·2021-09-30 10:00
閱讀 2970·2019-08-30 15:53
閱讀 3517·2019-08-30 15:53