原生JS實(shí)現(xiàn)圖片無縫滾動(dòng)方法(附帶封裝的運(yùn)動(dòng)框架)
話說輪播圖效果是前端er學(xué)習(xí)JS的必經(jīng)之路啊,很多同學(xué)寫的第一個(gè)JS效果應(yīng)該就是它了,在各大網(wǎng)站我們都會(huì)經(jīng)常見到,但是無縫滾動(dòng)運(yùn)動(dòng)效果的輪播圖,對(duì)于小白們來說還是有一定難度的。
我們來看看思路吧~
首先我們要實(shí)現(xiàn)的效果有以下幾點(diǎn):
小圓點(diǎn):點(diǎn)擊小圓點(diǎn)顯示與之對(duì)應(yīng)的圖片
向左和向右按鈕:點(diǎn)擊向左按鈕圖片向后運(yùn)動(dòng),點(diǎn)擊向右按鈕圖片向前運(yùn)動(dòng)
定時(shí)器:每隔 2s 自動(dòng)播放
主要難點(diǎn)在于:
當(dāng)圖片運(yùn)動(dòng)到最后一張,點(diǎn)擊向右的按鈕時(shí),應(yīng)該顯示第一張;
當(dāng)前顯示的是第一張,點(diǎn)擊向左的按鈕時(shí),應(yīng)該顯示最后一張;
思路:
1、先將第一張圖片復(fù)制 添加到 ul 最后面,將最后一張圖片復(fù)制 添加到 ul 最前面(此時(shí) ul 的第一張圖片是pic3,最后一張圖片是pic0);
2、當(dāng)圖片(ul)運(yùn)動(dòng)到pic3,繼續(xù)向前運(yùn)動(dòng),運(yùn)動(dòng)到最后一張pic0時(shí),瞬間把 ul 拉回到第二張圖片pic0的位置,然后在繼續(xù)向前運(yùn)動(dòng);
3、當(dāng)圖片(ul)向后運(yùn)動(dòng)到第一張圖片pic3時(shí),瞬間把 ul 拉回到倒數(shù)第二張圖片pic3的位置。
4、還有非常關(guān)鍵的一點(diǎn):定義iNow變量,用于對(duì)應(yīng)當(dāng)前顯示的圖片與ol中的小圓點(diǎn),并且可以用來關(guān)聯(lián) ul 的位置。
html代碼:
<div id="tab"> <ul> <li><img src="image/pic0.jpg" alt="" /></li> <li><img src="image/pic1.jpg" alt="" /></li> <li><img src="image/pic2.jpg" alt="" /></li> <li><img src="image/pic3.jpg" alt="" /></li> </ul> <ol> <li class="on"></li> <li></li> <li></li> <li></li> </ol> <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="prev" id="prev"><</a> <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="next" id="next">></a> </div>
css代碼:
*{margin: 0; padding: 0;} li{ list-style: none;} #tab{ width: 670px; height: 240px; border: 1px solid #ccc; margin: 50px auto; position: relative; } #tab ul{ width: 2680px; height: 240px; position: absolute; left: 0; top: 0; overflow: hidden; } #tab ul li{ float: left; width: 670px; } #tab ul li img{ width: 670px; } #tab ol{ width: 80px; position: absolute; bottom: 10px; left: 50%; margin-left: -40px; overflow: hidden; } #tab ol li{ float: left; width: 10px; height: 10px; background: #ccc; border-radius: 50%; margin: 5px; cursor: pointer; } #tab ol .on{ background: #f00; } #tab .prev,#tab .next{ display: none; width: 40px; height: 60px; background: rgba(0,0,0,.3); filter:alpha(opacity:30); text-decoration: none; text-align: center; line-height: 60px; font-size: 30px; color: #fff; position: absolute; top: 50%; margin-top: -30px; } #tab .prev{ left: 0; } #tab .next{ right: 0; }
js 代碼:
其中animate()是封裝好的運(yùn)動(dòng)框架,最后面附有說明
window.onload = function(){ var oTab = document.getElementById('tab'); var oUl = oTab.getElementsByTagName('ul')[0]; var aLi1 = oUl.children; var oOl = oTab.getElementsByTagName('ol')[0]; var aLi2 = oOl.children; var prev = document.getElementById('prev'); var next = document.getElementById('next'); //設(shè)置ul的初始位置 var iNow = 1; oUl.style.left=-aLi1[0].offsetWidth*iNow+'px'; //定時(shí)器 var timer = null; //克隆第一張圖片 添加在ul的最后面 var oLi1 = aLi1[0].cloneNode(true); //克隆最后一張圖片 添加在ul的最前面 var oLi2 = aLi1[aLi1.length-1].cloneNode(true); oUl.appendChild(oLi1); oUl.insertBefore(oLi2,aLi1[0]); oUl.style.width = aLi1[0].offsetWidth*aLi1.length+"px"; //鼠標(biāo)移入tab: 關(guān)閉定時(shí)器,左右按鈕顯示 oTab.onmouseover = function(){ clearInterval(timer); prev.style.display = 'block'; next.style.display = 'block'; } //鼠標(biāo)移出tab: 開啟定時(shí)器,左右按鈕隱藏 oTab.onmouseout = function(){ timer = setInterval(function(){ toNext(); },2000); prev.style.display = 'none'; next.style.display = 'none'; } //點(diǎn)擊小圓點(diǎn) for(var i=0;i<aLi2.length;i++){ (function(index){ aLi2[index].onclick = function(){ iNow = index+1; for(var i=0;i<aLi2.length;i++){ aLi2[i].className = ''; } aLi2[index].className = 'on'; animate(oUl,{left: -iNow*aLi1[0].offsetWidth}); } })(i); } //上一個(gè) prev.onclick=function(){ iNow--; animate(oUl,{left: -iNow*aLi1[0].offsetWidth},{complete:function(){ if(iNow == 0){ iNow = aLi1.length-2; oUl.style.left=-aLi1[0].offsetWidth*iNow+'px'; } for(var i=0;i<aLi2.length;i++){ aLi2[i].className = ''; } aLi2[iNow-1].className = 'on'; }}); } //下一個(gè) next.onclick=function(){ toNext(); } function toNext(){ iNow++; animate(oUl,{left: -iNow*aLi1[0].offsetWidth},{complete:function(){ if(iNow == aLi1.length-1){ iNow = 1; oUl.style.left=-aLi1[0].offsetWidth*iNow+'px'; } for(var i=0;i<aLi2.length;i++){ aLi2[i].className = ''; } aLi2[iNow-1].className = 'on'; }}); } //設(shè)置定時(shí)器 timer = setInterval(function(){ toNext(); },2000); }
封裝的animate()運(yùn)動(dòng)框架
/* * 參數(shù)說明: * obj: 運(yùn)動(dòng)對(duì)象 * json(json形式): 需要修改的屬性 * options(json形式): * duration: 運(yùn)動(dòng)時(shí)間 * easing: 運(yùn)動(dòng)方式(勻速、加速、減速) * complete: 運(yùn)動(dòng)完成后執(zhí)行的函數(shù) */ function animate(obj,json,options){ var options=options || {}; var duration=options.duration || 500; //運(yùn)動(dòng)時(shí)間,默認(rèn)值為500ms; var easing=options.easing || 'linear'; //運(yùn)動(dòng)方式,默認(rèn)為linear勻速 var start={}; var dis={}; for(var name in json){ start[name]=parseFloat(getStyle(obj,name)); //起始位置 dis[name]=json[name]-start[name]; //總距離 } var count=Math.floor(duration/30); //總次數(shù) var n=0; //次數(shù) clearInterval(obj.timer); obj.timer=setInterval(function(){ if(n>count){ clearInterval(obj.timer); options.complete && options.complete(); }else{ for(var name in json){ switch(easing){ //勻速 case 'linear': var a=n/count; var cur=start[name]+dis[name]*a; //當(dāng)前位置 break; //加速 case 'ease-in': var a=n/count; var cur=start[name]+dis[name]*a*a*a; break; //減速 case 'ease-out': var a=1-n/count; var cur=start[name]+dis[name]*(1-a*a*a); break; } if(name=='opacity'){ obj.style.opacity=cur; obj.style.filter = 'alpha(opacity='+cur*100+')'; //兼容IE8及以下 }else{ obj.style[name]=cur+'px'; } } } n++; },30); } //獲取非行間樣式 function getStyle(obj,sName){ return (obj.currentStyle || getComputedStyle(obj,false))[sName]; }
以上這篇原生JS實(shí)現(xiàn)圖片無縫滾動(dòng)方法(附帶封裝的運(yùn)動(dòng)框架)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- JS實(shí)現(xiàn)運(yùn)動(dòng)緩沖效果的封裝函數(shù)示例
- JS實(shí)現(xiàn)勻速與減速緩慢運(yùn)動(dòng)的動(dòng)畫效果封裝示例
- 原生JS封裝animate運(yùn)動(dòng)框架的實(shí)例
- 原生JS實(shí)現(xiàn)風(fēng)箱式demo,并封裝了一個(gè)運(yùn)動(dòng)框架(實(shí)例代碼)
- 原生js封裝運(yùn)動(dòng)框架的示例講解
- JS實(shí)現(xiàn)勻速運(yùn)動(dòng)的代碼實(shí)例
- 使用JavaScript 實(shí)現(xiàn)對(duì)象 勻速/變速運(yùn)動(dòng)的方法
- JavaScript中的勻速運(yùn)動(dòng)和變速(緩沖)運(yùn)動(dòng)詳細(xì)介紹
- 原生javascript實(shí)現(xiàn)勻速運(yùn)動(dòng)動(dòng)畫效果
- 淺談Javascript中勻速運(yùn)動(dòng)的停止條件
- js指定步長(zhǎng)實(shí)現(xiàn)單方向勻速運(yùn)動(dòng)
- 原生javascript運(yùn)動(dòng)函數(shù)的封裝示例【勻速、拋物線、多屬性的運(yùn)動(dòng)等】
相關(guān)文章
七個(gè)基于JavaScript實(shí)現(xiàn)的情人節(jié)表白特效
情人節(jié)將至 程序員證明自己不是直男的時(shí)候到啦 我們也有自己的專屬代碼浪漫。本文將介紹七個(gè)利用JavaScript實(shí)現(xiàn)的情人節(jié)表白特效,需要的可以參考一下2022-01-01xmlplus組件設(shè)計(jì)系列之下拉刷新(PullRefresh)(6)
xmlplus 是一個(gè)JavaScript框架,用于快速開發(fā)前后端項(xiàng)目。這篇文章主要介紹了xmlplus組件設(shè)計(jì)系列之下拉刷新,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05js操作輸入框提示信息且響應(yīng)鼠標(biāo)事件
注冊(cè)網(wǎng)站的輸入框就有默認(rèn)提示值,當(dāng)獲取鼠標(biāo)焦點(diǎn)的時(shí)候,默認(rèn)值被刪除,當(dāng)用戶沒輸入東西焦點(diǎn)離開的時(shí)候,又恢復(fù)默認(rèn)提示值2014-03-03ES6新特性之函數(shù)的擴(kuò)展實(shí)例詳解
這篇文章主要介紹了ES6新特性之函數(shù)的擴(kuò)展,實(shí)例形式較為詳細(xì)的分析了ES6針對(duì)函數(shù)參數(shù)、運(yùn)算符及相關(guān)新特性的擴(kuò)展操作與注意事項(xiàng),需要的朋友可以參考下2017-04-04js判斷兩個(gè)數(shù)組是否存在相同元素的四種方法
這篇文章主要給大家介紹了關(guān)于js判斷兩個(gè)數(shù)組是否存在相同元素的四種方法,js中是不能直接用==或者===來計(jì)算兩個(gè)數(shù)組是否相等的,那么就需要對(duì)數(shù)組的值進(jìn)行比較,需要的朋友可以參考下2023-07-07