原生js封裝無縫輪播功能
原生js封裝無縫輪播插件,供大家參考,具體內(nèi)容如下
說明:
這是一個使用原生js、es5語法寫出的無縫輪播程序,代碼中對相關(guān)api進(jìn)行了封裝,使得在引入該輪播js文件后,只需要在自己的js文件中添加兩行代碼即可在網(wǎng)頁中實(shí)現(xiàn)一個基本的無縫輪播圖效果。
基本使用步驟為:獲取dom元素?cái)?shù)組、向輪播對象中傳參、輪播對象調(diào)用自動輪播方法。
除基本的定時器自動輪播功能外,該程序還支持設(shè)置過渡動畫時間、設(shè)置鼠標(biāo)移入元素自動輪播停止、設(shè)置點(diǎn)擊左右側(cè)邊按鈕時輪播、設(shè)置點(diǎn)擊下方按鈕時輪播功能。
該程序不需要依賴css、html文件、但需要你的css、html布局遵循一定的規(guī)則。
注意該程序不支持曲線過渡速度、且在將瀏覽器切換瀏覽器窗口后有時會出現(xiàn)輪播圖錯亂的bug,暫時找不到問題的所在。
該程序僅是我一個初學(xué)者對無縫輪播函數(shù)的簡單封裝,僅能夠做學(xué)習(xí)和參考使用。
下面除輪播代碼外,我還會給出示例程序。
運(yùn)行效果:

思路:
根據(jù)輪播的方向確定所有輪播圖元素的排列順序,如果當(dāng)前輪播圖已到達(dá)所有輪播圖的邊界,則將相對方向上的最后一張輪播圖瞬間移動到相應(yīng)位置。
使用這種方法實(shí)現(xiàn)輪播圖所需要的最少輪播圖數(shù)為3張,針對輪播圖數(shù)量為一張和兩張的情況則需要對其單獨(dú)處理,一張情況下,復(fù)制添加兩張和當(dāng)前輪播圖相同的輪播圖元素,兩張情況下,需要按順序?qū)Ξ?dāng)前輪播圖進(jìn)行復(fù)制添加。
編譯環(huán)境:
Chrome 86.0.4240.183
代碼:
slide.js 封裝輪播圖代碼
(function(window, undefined) {
// 獲取元素css屬性值
function getCss(elem, attr) {
return elem.currentStyle ?
elem.currentStyle[attr] :
window.getComputedStyle(elem, null)[attr];
}
// 去除字符串中的非數(shù)字,不包括負(fù)號
function toInt(str) {
var rex = /[^0-9]/ig;
return Number((str[0] === '-' && str[1] !== '=') ? '-' + str.replace(rex, '') : str.replace(rex, ''));
}
// 封裝動畫函數(shù),參數(shù):dom對象、css屬性值對象、動畫執(zhí)行時間、動畫完成后回調(diào)
function animation(elem, params, speed, callback) {
for (var param in params) {
(function(param) {
var elemValue = toInt(getCss(elem, param)),
targetValue = toInt(params[param]),
currentDis = elemValue,
unit = params[param].substr(params[param].indexOf('[A-Za-z]+') - 1);
if (params[param].length > 2) {
var prefix = params[param].substr(0, 2);
if (prefix === '+=')
targetValue = elemValue + targetValue;
else if (prefix === '-=')
targetValue = elemValue - targetValue;
}
var dis = (targetValue - elemValue) / speed,
sizeFlag = targetValue < elemValue;
var timer = setInterval(function() {
elemValue = toInt(getCss(elem, param));
if (sizeFlag) {
if (currentDis <= targetValue) {
clearInterval(timer);
elem.style[param] = targetValue + unit;
} else {
currentDis += dis;
elem.style[param] = currentDis + unit;
}
}
else {
if (currentDis >= targetValue) {
clearInterval(timer);
elem.style[param] = targetValue + unit;
} else {
currentDis += dis;
elem.style[param] = currentDis + unit;
}
}
}, 1);
})(param);
}
if (typeof callback === 'function')
callback();
};
// 向右輪播數(shù)組移動
function rightRoundArrayMove() {
var winsLen = wins.length;
var lastWin = wins[winsLen - 1];
for (var i = winsLen - 1; i > 0; i--)
wins[i] = wins[i - 1];
wins[0] = lastWin;
}
// 向左輪播
function rightRound(time) {
rightRoundArrayMove();
wins.forEach(function(win, index) {
(index === 0) ?
win.style.left = index * winWidth - winWidth + 'px' :
animation(win, {left: '+=' + winWidth + 'px'}, time ? time : animationTime);
});
}
// 向右輪播
function leftRound(time) {
var winsLen = wins.length;
var firstWin = wins[0];
for (var i = 0; i < winsLen - 1; i++)
wins[i] = wins[i + 1];
wins[winsLen - 1] = firstWin;
wins.forEach(function(win, index) {
(index === wins.length - 1) ?
win.style.left = index * winWidth - winWidth + 'px' :
animation(win, {left: '-=' + winWidth + 'px'}, time ? time : animationTime);
});
}
var
// wins, btns, sbtns用于保存構(gòu)造函數(shù)的參數(shù)
wins,
btns,
sbtns,
// 窗口的寬度
winWidth,
// 過渡動畫時間(毫秒),默認(rèn)為100
animationTime = 100,
// 點(diǎn)擊按鈕輪播間隔
clickInterval = animationTime << 2,
// 保存自動輪播定時器、定時器間隔、是否向右輪播
autoRoundTimer,
qinterval,
qisRight,
// slide構(gòu)造函數(shù),參數(shù):窗口數(shù)組,按鈕數(shù)組,側(cè)邊按鈕數(shù)組
slide = function(wins, btns, sbtns) {
return new slide.prototype.init(wins, btns, sbtns);
};
slide.prototype = {
// 初始化窗口元素
init: function(awins, abtns, asbtns) {
if (!awins)
throw new Error('The window array cannot be empty.');
wins = Object.values(awins), btns = abtns, sbtns = asbtns;
// 處理窗口少于3個的情況
if (wins.length === 1) {
var winParent = wins[0].parentNode;
var winHTML = wins[0].outerHTML;
winParent.innerHTML += winHTML + winHTML;
wins = Object.values(winParent.children);
}
else if (wins.length === 2) {
var winParent = wins[0].parentNode;
winParent.innerHTML += wins[0].outerHTML + wins[1].outerHTML;
wins = Object.values(winParent.children);
}
winWidth = wins[0].offsetWidth;
wins.forEach(function(win, index) {
win.style.position = 'absolute';
win.index = index;
});
rightRoundArrayMove();
wins.forEach(function(win, index) {
win.style.left = index * winWidth - winWidth + 'px';
});
},
// 設(shè)置過渡動畫時間
setAnimationTime: function(time) {
animationTime = time;
clickInterval = animationTime << 2;
},
// 自動輪播,參數(shù):輪播時間間隔、是否為向右輪播
autoRound: function(interval, isRight) {
autoRoundTimer = setInterval(function() {
isRight ? rightRound() : leftRound();
}, interval);
qinterval = interval;
qisRight = isRight;
},
// 側(cè)邊按鈕點(diǎn)擊,參數(shù)為側(cè)邊按鈕元素?cái)?shù)組,該參數(shù)可在構(gòu)造函數(shù)中傳遞或現(xiàn)在傳遞
sideBtnClickRound: function(sabtns) {
var leftBtn = sabtns ? sabtns[0] : sbtns[0],
rightBtn = sabtns ? sabtns[1] : sbtns[1];
var isclick= true;
leftBtn.onclick = function () {
if(isclick) {
isclick= false;
rightRound();
setTimeout(function() {
isclick = true;
}, clickInterval);
}
};
rightBtn.onclick = function () {
if(isclick) {
isclick= false;
leftRound();
setTimeout(function() {
isclick = true;
}, clickInterval);
}
};
},
// 普通按鈕點(diǎn)擊,參數(shù):普通按鈕數(shù)組、回調(diào)
btnsClickRound: function(abtns, callback) {
var ibtns = abtns ? abtns : btns;
var isclick= true;
ibtns.forEach(function(btn, index) {
btn.onclick = function() {
if(isclick) {
isclick= false;
if (typeof callback === 'function')
callback(ibtns, btn, index);
var poor = index - wins[1].index;
var count = Math.abs(poor);
if (poor < 0) {
var absPoor = count;
var timer = setInterval(function() {
console.log((absPoor + 1))
rightRound(animationTime / (absPoor + 2));
if ((--count) === 0)
clearInterval(timer);
}, animationTime);
}
else if (poor > 0) {
var timer = setInterval(function() {
leftRound(animationTime / (poor + 2));
if ((--count) === 0)
clearInterval(timer);
}, animationTime);
}
setTimeout(function() {
isclick = true;
}, clickInterval << 1);
}
}
});
},
// 設(shè)置鼠標(biāo)移入取消自動輪播,參數(shù):移入的元素、移入元素回調(diào)、移出元素回調(diào)
setOverStop: function(box, overCallback, outCallback) {
box.onmouseover = function(e) {
clearInterval(autoRoundTimer);
if (typeof overCallback === 'function')
overCallback(e);
}
box.onmouseout = function(e) {
slide.prototype.autoRound(qinterval, qisRight);
if (typeof outCallback === 'function')
outCallback(e);
}
}
}
slide.prototype.init.prototype = slide.prototype;
window.slide = _slide = slide;
})(window);
test.js 測試示例js代碼:
onload = function() {
var wins = document.querySelectorAll('.wins > li');
var btns = document.querySelectorAll('.btns > li');
var sideBtns = document.querySelectorAll('.side-btns > div');
var box = document.querySelector('.box');
var s = slide(wins, btns, sideBtns); // 創(chuàng)建輪播對象,參數(shù):窗口dom數(shù)組、下方按鈕dom數(shù)組(可選)、
s.autoRound(2000); // 設(shè)置自動輪播
s.setAnimationTime(200); // 設(shè)置過渡動畫時間
s.setOverStop(box); // 設(shè)置鼠標(biāo)移入元素時自動輪播停止,參數(shù):移入的dom元素、移入元素回調(diào)、移出元素回調(diào)
s.sideBtnClickRound(); // 設(shè)置點(diǎn)擊側(cè)邊按鈕時輪播,參數(shù):按鈕dom數(shù)組(可選)
s.btnsClickRound(); // 設(shè)置下方按鈕點(diǎn)擊時輪播,參數(shù):按鈕dom數(shù)組(可選)、回調(diào)
}
html、css示例代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.box {
width: 1000px;
height: 400px;
margin: 20px auto;
display: flex;
align-items: center;
position: relative;
overflow: hidden;
}
.box > * {
position: absolute;
}
.side-btns {
width: inherit;
height: 100px;
display: flex;
justify-content: space-between;
z-index: 2;
}
.side-btns > div {
width: 50px;
height: inherit;
text-align: center;
line-height: 100px;
font-size: 18px;
background-color: rgba(0, 0, 0, .3);
color: white;
cursor: pointer;
user-select: none;
}
.btns {
width: inherit;
height: 20px;
display: flex;
justify-content: flex-end;
z-index: 2;
position: absolute;
bottom: 20px;
}
.btns > li {
width: 16px;
height: 16px;
border-radius: 50%;
margin-right: 12px;
cursor: pointer;
background-color: rgba(0, 0, 0, .2);
}
.wins {
width: inherit;
height: inherit;
display: flex;
}
.wins > li {
width: inherit;
height: inherit;
flex-grow:0;
flex-shrink:0;
}
</style>
<script src="js/slide.js"></script>
<script src="js/test.js"></script>
</head>
<body>
<div class="box">
<div class="side-btns">
<div class="left-btn"><</div>
<div class="right-btn">></div>
</div>
<ul class="btns">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<ul class="wins">
<li style="background-color: antiquewhite;">a</li>
<li style="background-color: aquamarine;">b</li>
<li style="background-color: green;">c</li>
<li style="background-color: brown;">d</li>
</ul>
</div>
</body>
</html>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js確認(rèn)框confirm()用法實(shí)例詳解
這篇文章主要針對js確認(rèn)框confirm()用法進(jìn)行實(shí)例講解,介紹了javascript確認(rèn)框的三種使用方法,感興趣的小伙伴們可以參考一下2016-01-01
TypeScript使用函數(shù)重載確定返回類型的實(shí)現(xiàn)方法
這篇文章主要介紹了TypeScript使用函數(shù)重載確定返回類型的實(shí)現(xiàn)方法,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03
Three.js如何用軌跡球插件(trackball)增加對模型的交互功能詳解
這篇文章主要給大家介紹了關(guān)于Three.js如何用軌跡球插件,也就是trackball增加對模型的交互功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09

