封裝運動框架實戰(zhàn)左右與上下滑動的焦點輪播圖(實例)
在這篇文章打造通用的勻速運動框架(實例講解)中,封裝了一個勻速運動框架,我們在這個框架的基礎(chǔ)之上,加上緩沖運動效果,然后用運動框架來做幻燈片(上下,左右)。

緩沖運動通常有兩種常見的表現(xiàn):比如讓一個div從0運動到500,一種是事件觸發(fā)的時候,速度很快, 一種是事件觸發(fā)的時候慢,然后慢慢加快.我們來實現(xiàn)先塊后慢的,常見的就是開車,比如剛從高速路上下來的車,就是120km/小時,然后進入匝道,變成40km/時. 或者40km/小時進入小區(qū),最后停車,變成0km/小時. 從120km/小時->40km/小時, 或者40km->0km/小時,都是速度先塊后慢,這種運動怎么用程序來表示呢?

可以用目標(biāo)距離( 500 ) - 當(dāng)前距離( 200 ) / 一個系數(shù)( 比如12 ),就能達(dá)到速度由塊而慢的變化,當(dāng)前距離在起點,分子(500 - 0 )最大,所以速度最大,如果當(dāng)前距離快要接近500,分子最小,除完之后的速度也是最小。
<style>
div{
width: 200px;
height: 200px;
background:red;
position: absolute;
left: 0px;
}
</style>
<script>
window.onload = function(){
var oBtn = document.querySelector( "input" ),
oBox = document.querySelector( '#box' ),
speed = 0, timer = null;
oBtn.onclick = function(){
timer = setInterval( function(){
speed = ( 500 - oBox.offsetLeft ) / 8;
oBox.style.left = oBox.offsetLeft + speed + 'px';
}, 30 );
}
}
</script>
</head>
<body>
<input type="button" value="動起來">
<div id="box"></div>
</body>
你會發(fā)現(xiàn),速度永遠(yuǎn)都在0.375這里停著,獲取到的當(dāng)前的距離停在497px? 這里有個問題,我們的div不是停在497.375px嗎,怎么獲取到的沒有了后面的小數(shù)0.375呢?計算機在處理浮點數(shù)會有精度損失。我們可以單獨做一個小測試:
<div id="box"></div> <script> var oBox = document.querySelector( '#box' ); alert( oBox.offsetLeft ); </script>
你會發(fā)現(xiàn)這段代碼獲取到左偏移是30px而不是行間樣式中寫的30.2px。因為在獲取當(dāng)前位置的時候,會舍去小數(shù),所以速度永遠(yuǎn)停在0.375px, 位置也是永遠(yuǎn)停在497,所以,為了到達(dá)目標(biāo),我們就得把速度變成1,對速度向上取整( Math.ceil ),我們就能把速度變成1,div也能到達(dá)500
oBtn.onclick = function(){
timer = setInterval( function(){
speed = ( 500 - oBox.offsetLeft ) / 8;
if( speed > 0 ) {
speed = Math.ceil( speed );
}
console.log( speed, oBox.offsetLeft );
oBox.style.left = oBox.offsetLeft + speed + 'px';
}, 30 );
}
第二個問題,如果div的位置是在900,也就是說從900運動到500,有沒有這樣的需求呢? 肯定有啊,輪播圖,從右到左就是這樣的啊。
<style>
#box{
width: 200px;
height: 200px;
background:red;
position: absolute;
left: 900px;
}
</style>
<script>// <![CDATA[
window.onload = function(){
var oBtn = document.querySelector( "input" ),
oBox = document.querySelector( '#box' ),
speed = 0, timer = null;
oBtn.onclick = function(){
timer = setInterval( function(){
speed = ( 500 - oBox.offsetLeft ) / 8;
if( speed > 0 ) {
speed = Math.ceil( speed );
}
oBox.style.left = oBox.offsetLeft + speed + 'px';
}, 30 );
}
}
// ]]></script>
</head>
<body>
<input type="button" value="動起來">
<div id="box"></div>
</body>

oBtn.onclick = function(){
timer = setInterval( function(){
speed = ( 500 - oBox.offsetLeft ) / 8;
if( speed > 0 ) {
speed = Math.ceil( speed );
}else {
speed = Math.floor( speed );
}
console.log( speed, oBox.offsetLeft );
oBox.style.left = oBox.offsetLeft + speed + 'px';
}, 30 );
}
然后我們把這個緩沖運動整合到勻速運動框架,就變成:
function css(obj, attr, value) {
if (arguments.length == 3) {
obj.style[attr] = value;
} else {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
function animate(obj, attr, fn) {
clearInterval(obj.timer);
var cur = 0;
var target = 0;
var speed = 0;
obj.timer = setInterval(function () {
var bFlag = true;
for (var key in attr) {
if (key == 'opacity ') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, key));
}
target = attr[key];
speed = ( target - cur ) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if (cur != target) {
bFlag = false;
if (key == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";
} else {
obj.style[key] = cur + speed + "px";
}
}
}
if (bFlag) {
clearInterval(obj.timer);
fn && fn.call(obj);
}
}, 30 );
}
有了這勻速運動框架,我們就來做幻燈片:
上下幻燈片的html樣式文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>slide - by ghostwu</title> <link rel="stylesheet" href="css/slide3.css" rel="external nofollow" > <script src="js/animate.js"></script> <script src="js/slide.js"></script> </head> <body> <div id="slide"> <div id="slide-img"> <div id="img-container"> <img src="./img/1.jpg" alt=""> <img src="./img/2.jpg" alt=""> <img src="./img/3.jpg" alt=""> <img src="./img/4.jpg" alt=""> <img src="./img/5.jpg" alt=""> </div> </div> <div id="slide-nums"> <ul> <li class="active"></li> <li></li> <li></li> <li></li> <li></li> </ul> </div> </div> </body> </html>
slide3.css文件:
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
#slide {
width: 800px;
height: 450px;
position: relative;
margin:20px auto;
}
#slide-img {
position: relative;
width: 800px;
height: 450px;
overflow: hidden;
}
#img-container {
position: absolute;
left: 0px;
top: 0px;
height: 2250px;
/*font-size:0px;*/
}
#img-container img {
display: block;
float: left;
}
#slide-nums {
position: absolute;
right:10px;
bottom:10px;
}
#slide-nums li {
float: left;
margin:0px 10px;
background: white;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
border-radius:10px;
text-indent:-999px;
opacity:0.6;
filter:alpha(opacity:60);
cursor:pointer;
}
#slide-nums li.active {
background: red;
}
animate.js文件:
function css(obj, attr, value) {
if (arguments.length == 3) {
obj.style[attr] = value;
} else {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
function animate(obj, attr, fn) {
clearInterval(obj.timer);
var cur = 0;
var target = 0;
var speed = 0;
obj.timer = setInterval(function () {
var bFlag = true;
for (var key in attr) {
if (key == 'opacity ') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, key));
}
target = attr[key];
speed = ( target - cur ) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if (cur != target) {
bFlag = false;
if (key == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")";
} else {
obj.style[key] = cur + speed + "px";
}
}
}
if (bFlag) {
clearInterval(obj.timer);
fn && fn.call(obj);
}
}, 30 );
}
slide.js文件:
window.onload = function () {
function Slide() {
this.oImgContainer = document.getElementById("img-container");
this.aLi = document.getElementsByTagName("li");
this.index = 0;
}
Slide.prototype.bind = function () {
var that = this;
for (var i = 0; i < this.aLi.length; i++) {
this.aLi[i].index = i;
this.aLi[i].onmouseover = function () {
that.moveTop( this.index );
}
}
}
Slide.prototype.moveTop = function (i) {
this.index = i;
for( var j = 0; j < this.aLi.length; j++ ){
this.aLi[j].className = '';
}
this.aLi[this.index].className = 'active';
animate( this.oImgContainer, {
"top" : -this.index * 450,
"left" : 0
});
}
var oSlide = new Slide();
oSlide.bind();
}
左右幻燈片只需要改下樣式即可
樣式文件:
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
#slide {
width: 800px;
height: 450px;
position: relative;
margin:20px auto;
}
#slide-img {
position: relative;
width: 800px;
height: 450px;
overflow: hidden;
}
#img-container {
position: absolute;
left: 0px;
top: 0px;
width: 4000px;
}
#img-container img {
display: block;
float: left;
}
#slide-nums {
position: absolute;
right:10px;
bottom:10px;
}
#slide-nums li {
float: left;
margin:0px 10px;
background: white;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
border-radius:10px;
text-indent:-999px;
opacity:0.6;
filter:alpha(opacity:60);
cursor:pointer;
}
#slide-nums li.active {
background: red;
}
js調(diào)用文件:
window.onload = function () {
function Slide() {
this.oImgContainer = document.getElementById("img-container");
this.aLi = document.getElementsByTagName("li");
this.index = 0;
}
Slide.prototype.bind = function () {
var that = this;
for (var i = 0; i < this.aLi.length; i++) {
this.aLi[i].index = i;
this.aLi[i].onmouseover = function () {
that.moveLeft( this.index );
}
}
}
Slide.prototype.moveLeft = function (i) {
this.index = i;
for( var j = 0; j < this.aLi.length; j++ ){
this.aLi[j].className = '';
}
this.aLi[this.index].className = 'active';
animate( this.oImgContainer, {
"left" : -this.index * 800
});
}
var oSlide = new Slide();
oSlide.bind();
}
以上這篇封裝運動框架實戰(zhàn)左右與上下滑動的焦點輪播圖(實例)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript實現(xiàn)網(wǎng)頁截屏的5種方法小結(jié)
本文主要介紹了JavaScript實現(xiàn)網(wǎng)頁截屏的5種方法小結(jié),感興趣的可以了解一下2009-10-10
window.print()前端實現(xiàn)網(wǎng)頁打印功能詳解
JavaScript 函數(shù)window.print()可用于打印你的應(yīng)用的內(nèi)容,但是它針對的是使用默認(rèn)打印體驗打印顯示在屏幕上的內(nèi)容,這篇文章主要給大家介紹了關(guān)于window.print()前端實現(xiàn)網(wǎng)頁打印功能的相關(guān)資料,需要的朋友可以參考下2024-04-04
JavaScript使用delete刪除數(shù)組元素用法示例【數(shù)組長度不變】
這篇文章主要介紹了JavaScript使用delete刪除數(shù)組元素用法,結(jié)合實例形式分析了delete刪除數(shù)組元素的具體用法與注意事項,需要的朋友可以參考下2017-01-01
在原生不支持的舊環(huán)境中添加兼容的Object.keys實現(xiàn)方法
下面小編就為大家?guī)硪黄谠恢С值呐f環(huán)境中添加兼容的Object.keys實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
Ajax與Axios的基礎(chǔ)知識以及詳細(xì)對比總結(jié)
在Web開發(fā)中Ajax和Axios是兩種實現(xiàn)異步數(shù)據(jù)請求的技術(shù),Ajax可以在不刷新頁面的情況下與服務(wù)器通信,Axios是一個基于Promise的HTTP客戶端,簡化了HTTP請求的過程,兩者都能處理多種數(shù)據(jù)格式,這篇文章主要介紹了Ajax與Axios的基礎(chǔ)知識以及詳細(xì)對比總結(jié),需要的朋友可以參考下2024-09-09
js中各種數(shù)據(jù)類型檢測和判定的實戰(zhàn)示例
typeof一般被用于判斷一個變量的類型,我們可以利用typeof來判斷number,string,object,boolean,function,undefined,symbol這七種類型,下面這篇文章主要給大家介紹了關(guān)于js中各種數(shù)據(jù)類型檢測和判定的相關(guān)資料,需要的朋友可以參考下2022-11-11

