JS輪播圖中緩動(dòng)函數(shù)的封裝
輪播圖的根本其實(shí)就是緩動(dòng)函數(shù)的封裝,如果說輪播圖是一輛跑動(dòng)的汽車,那么緩動(dòng)函數(shù)就是它的發(fā)動(dòng)機(jī),今天本文章就帶大家由簡(jiǎn)入繁,封裝屬于自己的緩動(dòng)函數(shù)~~
我們從需求的角度開始,首先給出一個(gè)簡(jiǎn)單需求:
1、我想讓頁面中的一個(gè)盒子從開始的位置勻速向右運(yùn)動(dòng)到200px的地方,該怎么實(shí)現(xiàn)?
分析:
1)我們需要知道盒子在哪個(gè)地方,這個(gè)可以通過offsetLeft屬性去獲??;
2)要讓盒子勻速運(yùn)動(dòng),對(duì)于js肯定需要setInterval了;
3)要讓盒子向右邊跑起來?那就是需要不停改變盒子與左邊起始點(diǎn)的距離,有margin-left,還有定位的left,這里我選擇了改變絕對(duì)定位的left;
4)跑到離開始點(diǎn)200px的距離我們要停下來,使用clearInterval就可以了。
接下來直接上代碼了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
div {
position: absolute;
top: 50px;
width: 100px;
height: 100px;
background-color: red;
}
input {
width: 100px;
height: 30px;
color: #fff;
background-color: yellowgreen;
}
</style>
</head>
<body>
<div></div>
<input type="button" value="移動(dòng)到200" />
<script type="text/javascript">
// 獲取到元素(這里有個(gè)小細(xì)節(jié),如果給元素設(shè)置了id名,即便不使用獲取元素的方法,也能通過這個(gè)id名獲取到元素哦~~大家可以自己嘗試一下)
var btn = document.querySelector('input'),
dv = document.querySelector('div');
// 添加點(diǎn)擊事件
btn.addEventListener('click',function() {
var timer = null,// 保存定時(shí)器
currentDistance = dv.offsetLeft, // 當(dāng)前離父盒子的距離
step = 8,// 每次改變的距離
target = 200;// 目標(biāo)距離
timer = setInterval(function() {
currentDistance += step;// 當(dāng)前距離 = 上一個(gè)當(dāng)前距離 + 改變的距離
if((target - currentDistance) < step) {
currentDistance = target; // 如果目標(biāo)距離與當(dāng)前距離的差小于了要改變的距離,這時(shí)候我們就直接讓當(dāng)前距離等于目標(biāo)距離,防止盒子停下來的時(shí)候有誤差
clearInterval(timer); // 清楚定時(shí)器
timer = null; // 將timer解綁,釋放內(nèi)存
}
dv.style.left = currentDistance + 'px'; // 最核心的一步,改變盒子的left為當(dāng)前距離
},17)
})
</script>
</body>
</html>
2、一個(gè)初步運(yùn)動(dòng)的效果實(shí)現(xiàn)了,那么接下來我們改進(jìn)了需求:
盒子運(yùn)動(dòng)到200px的位置后,我們要讓盒子繼續(xù)運(yùn)動(dòng)到400px的位置?
分析:
1)、這時(shí)候要有兩個(gè)按鈕點(diǎn)擊,一個(gè)運(yùn)動(dòng)到200px,一個(gè)運(yùn)動(dòng)到400px
2)、雖然有兩個(gè)運(yùn)動(dòng),但是其使用的功能都是一樣,都是從一個(gè)點(diǎn)移動(dòng)到另一個(gè)點(diǎn),所以我們考慮將1中的運(yùn)動(dòng)封裝一個(gè)函數(shù),以供復(fù)用。
上代碼~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
div {
position: absolute;
top: 50px;
width: 100px;
height: 100px;
background-color: red;
}
input {
width: 100px;
height: 30px;
color: #fff;
background-color: yellowgreen;
}
</style>
</head>
<body>
<div></div>
<input type="button" value="移動(dòng)到200" />
<input type="button" value="移動(dòng)到400" />
<script type="text/javascript">
// 封裝函數(shù),盒子和目標(biāo)距離都是不確定的,我們可以將他們作為參數(shù)傳遞。
function animation(tag,target) {
var timer = null,
currentDistance = tag.offsetLeft,
step = 5;
step = currentDistance < target? step: -step;// 判斷step的正負(fù),200到400時(shí)是遞增,400到200時(shí)是遞減
timer = setInterval(function() {
if(Math.abs(currentDistance - target) > Math.abs(step)) { // 這里判斷條件也要略作改動(dòng),使用絕對(duì)值進(jìn)行比較
currentDistance += step; /
tag.style.left = currentDistance + 'px';
}else {
tag.style.left = target + 'px' // 當(dāng)當(dāng)前距離與目標(biāo)距離之間的差值小于step改變的距離時(shí),我們直接讓盒子移動(dòng)到目標(biāo)距離。
clearInterval(timer);
timer = null;
}
},17)
}
var btns = document.querySelectorAll('input'),
dv = document.querySelector('div');
btns[0].addEventListener('click',function() {
animation(dv,200);
})
btns[1].addEventListener('click',function() {
animation(dv,400);
})
</script>
</body>
</html>
3、盒子來回運(yùn)動(dòng)的函數(shù)我們封裝好了,但是我們?cè)傧胍幌螺啿D的滾動(dòng)效果,它并不是勻速移動(dòng),而是最開始很塊,在接近滾動(dòng)完成時(shí),速度又逐漸減低。
需求: 讓盒子緩動(dòng)(也就是變速運(yùn)動(dòng))
上代碼~
function animation(tag,target) {
var timer = null;
timer = setInterval(function() {
var currentDistance = tag.offsetLeft,
step = (target - currentDistance) / 5;// 通過目標(biāo)距離與當(dāng)前距離的差除以5便達(dá)到了我們需要的變速運(yùn)動(dòng),因?yàn)閟tep每次定制器執(zhí)行都要改變,所以放入定時(shí)器內(nèi)
step = step > 0 ? Math.ceil(step):Math.floor(step);// 這里如果將currentDistance定時(shí)器外面聲明可以不用寫,如果放在定時(shí)器內(nèi)聲明,因?yàn)閛ffsetLeft取整的特性,要對(duì)step進(jìn)行取整
if(Math.abs(currentDistance - target) > Math.abs(step)) {
currentDistance += step;
tag.style.left = currentDistance + 'px';
}else {
tag.style.left = target + 'px'
clearInterval(timer);
timer = null;
}
},17)
好了,一個(gè)輪播圖需要的最基本的緩動(dòng)函數(shù)完成了~
這里補(bǔ)充一個(gè)比較完整的緩動(dòng)函數(shù):它的功能更全面一點(diǎn),可以同時(shí)更改多樣式。
function perfectAnimate(tag, obj, fn) {// 傳三個(gè)參數(shù),運(yùn)動(dòng)的盒子,對(duì)象(可以傳多個(gè)屬性),回調(diào)函數(shù)(在執(zhí)行完后可以再執(zhí)行自定義的功能)
clearInterval(tag.timer);// 這里將定時(shí)器作為tag標(biāo)簽的屬性保存,可以多次調(diào)用函數(shù)清除上一個(gè)定時(shí)器。
tag.timer = setInterval(function () {
var flag = true;
for (var k in obj) {
// 因?yàn)椴⒉皇撬袑傩远紟x單位,所以這里進(jìn)行判斷分別設(shè)置
if (k == 'opacity') {
var currentDistance = getStyle(tag, k) * 100,
target = obj[k] * 100,
step = (target - currentDistance) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
currentDistance += step;
tag.style[k] = currentDistance / 100;
} else if (k == 'zIndex') {
tag.style[k] = obj[k];
else {
var currentDistance = parseInt(getStyle(tag, k)) || 0,
target = obj[k],
step = (target - currentDistance) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
currentDistance += step;
tag.style[k] = currentDistance + 'px';
}
if (target != currentDistance) {
flag = false // 只要還有屬性沒有運(yùn)動(dòng)完成,就不會(huì)清楚定時(shí)器
}
}
if (flag) {
clearInterval(tag.timer)
fn && fn();// 所有定時(shí)器走完,這里執(zhí)行回調(diào)函數(shù),短路操作避免不傳回調(diào)函數(shù)也不會(huì)報(bào)錯(cuò)。
}
}, 17)
}
// 獲取樣式的兼容函數(shù),上面的緩動(dòng)函數(shù)的依賴
function getStyle(tag, attr) {
if (tag.currentStyle) {
return tag.currentStyle[attr];
} else {
return getComputedStyle(tag, null)[attr];
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS/FLASH實(shí)現(xiàn)復(fù)制代碼到剪貼板(兼容所有瀏覽器)
使用javascript來寫復(fù)制到剪貼板的代碼,一般都是瀏覽器不兼容的。所以采用flash的方式,模擬一個(gè)層,再來復(fù)制,就可以做到全部瀏覽器都適用,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-05-05
js和C# 時(shí)間日期格式轉(zhuǎn)換的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)硪黄猨s和C# 時(shí)間日期格式轉(zhuǎn)換的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05
js跳轉(zhuǎn)頁面方法實(shí)現(xiàn)匯總
js跳轉(zhuǎn)頁面的方法有很多,本文搜集整理了一些,個(gè)人感覺還不錯(cuò),希望對(duì)大家有所幫助2014-02-02
解決html按鈕切換綁定不同函數(shù)后點(diǎn)擊時(shí)執(zhí)行多次函數(shù)問題
這篇文章主要介紹了如何解決html按鈕切換綁定不同函數(shù)后點(diǎn)擊時(shí)執(zhí)行多次函數(shù)問題,需要的朋友可以參考下2014-05-05
微信小程序?qū)崿F(xiàn)跟隨菜單效果和循環(huán)嵌套加載數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)跟隨菜單效果和循環(huán)嵌套加載數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
JavaScript?雙位非運(yùn)算(~~?操作符)使用場(chǎng)景實(shí)例探索
本文為大家介紹JavaScript中雙位非運(yùn)算?~~,?~~?操作符是一個(gè)強(qiáng)大且經(jīng)常被忽視的特性,它提供了一種快速、簡(jiǎn)潔的方式來處理數(shù)字和執(zhí)行類型轉(zhuǎn)換,通常可以被用于數(shù)學(xué)計(jì)算和類型轉(zhuǎn)換,我們先了解一下?~~?的基本概念和它的一些應(yīng)用場(chǎng)景2024-01-01
JavaScript瀑布流的實(shí)現(xiàn)你學(xué)會(huì)了嗎
這篇文章主要為大家詳細(xì)介紹了JavaScript瀑布流的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02
JS限制Textarea文本域字符個(gè)數(shù)的具體實(shí)現(xiàn)
這篇文章介紹了JS限制Textarea文本域字符個(gè)數(shù)的具體實(shí)現(xiàn),有需要的朋友可以參考一下2013-08-08
JavaScript 計(jì)算笛卡爾積實(shí)例詳解
這篇文章主要介紹了JavaScript 計(jì)算笛卡爾積實(shí)例詳解的相關(guān)資料,這里附有實(shí)例代碼,需要的朋友可以參考下2016-12-12

