緩封動畫的原理和封
學習目標:網頁輪播圖的實現
1.offset .client. scroll 三大家族
2.緩動動畫的原理和封
3.網頁輪播圖實現
4.節流閥 返回頂部及筋斗雲案例
5.移動端輪播圖實現
6.移動端外掛使用 及輪播圖的實現
7.html5本地儲存及記住使用者名稱案例
學習內容:
1.mouseover與mouseenter的區別
mousedown才是滑鼠按下觸發
(1)當滑鼠移動到元素上時就會觸發mouseenter事件
(2)類似mouseover ,但是二者有差別
(3) mouseover 滑鼠經過自身盒子會觸發,經過子盒子還會觸發。
mouseenter 只會經過自身盒子觸發
(5) 跟mousrenter搭配使用的mouseleave 同樣不會冒泡
//給父親新增一個事件
father.addEventListener ( 'mouseover' , function() {
alert(11);
}
//輸出:mouseover經過子盒子,因為會冒泡,所以會執行父盒子的函式(冒泡:son~father~body~html~document)
2.動畫原理
核心原理:通過定時器setInterval()不斷地移動盒子位置。
實現步驟:
(1)獲得盒子當前的位置。
(2)讓盒子在當前位置上加1個移動距離。
<style> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } </style> <body> <div></div> <script> //(1)獲得盒子當前的位置。 // (2)讓盒子在當前位置上加1個移動距離。 // (3)利用定時器不斷重複這個操作。 //4.加一個結束定時器的條件 //5.注意此元素需要新增定位,才能使用element.style.left var div = document.querySelector('div'); var timer = window.setInterval( function() { if(div.offsetLeft >= 400 ) { //停止動畫(停止定時器) clearInterval(timer); } div.style.left = div.offsetLeft + 5 +'px'; },500); </script> </body>
3.簡單動畫封裝
//animate:動畫 target:目標
function animate(obj, target) {
var timer = window.setInterval(function () {
if (obj.offsetLeft >= target) {
//停止動畫(停止定時器)
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 5 + 'px';
}, 500);
}
var div = document.querySelector('div');
//呼叫函式(這裡是普通函式)
animate(div, 400);
5.動畫函式-給不同元素記錄不同的定時器
1.給不同的元素記錄不同的定時器
首先給物件新增屬性的方法
//給物件新增屬性
var obj = {};
obj.name= 'a';
其次
function animate(obj, target) {
obj.timer = window.setInterval(function () {
//用obj.timer 相比var timer的好處: 1.只是給obj添加了一個屬性不會開闢新的空間消耗記憶體
//var宣告會佔記憶體 2.每個物件都有自己獨立的定時器了
if (obj.offsetLeft >= target) {
//停止動畫(停止定時器)
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 10 + 'px';
}, 30);
}
2.會有bug 當你給動畫加了執行按鈕,重複點選按鈕時,元素的速度會越來越快
(因為開啟了太多的定時器)
<body>
<button>執行</button>
<div></div>
<script>
// //給物件新增屬性
// var obj = {};
// obj.name= 'a';
function animate(obj, target) {
//執行時先清除定時器
clearInterval(obj.timer);
obj.timer = window.setInterval(function () {
//用obj.timer 相比var timer的好處: 1.只是給obj添加了一個屬性不會開闢新的空間消耗記憶體
//var宣告會佔記憶體 2.每個物件都有自己獨立的定時器了
if (obj.offsetLeft >= target) {
//停止動畫(停止定時器)
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 10 + 'px';
}, 30);
}
var div = document.querySelector('div');
var btn = document.querySelector('button');
//呼叫函式(這裡是普通函式)
btn.addEventListener('click',function() {
animate(div,400);
})
</script>
</body>
重點
function animate(obj, target) {
//執行時先清除定時器
clearInterval(obj.timer);
obj.timer = window.setInterval(function () {
6.緩動函式原理
緩動動畫就是讓元素運動有所變化,最常見的是讓速度慢慢停下來(效果柔和)
(1)讓盒子每次移動的距離慢慢變小,速度就會慢慢落下來
(2)核心演算法:(目標值-現在的位置)/10 作為每次移動的距離步長
(3)停止的條件:讓當前的盒子位置等於目標位置就停止定時器
<button>執行</button>
<div></div>
<script>
// (1)讓盒子每次移動的距離慢慢變小,速度就會慢慢落下來
// (2)核心演算法:(目標值-現在的位置)/10 作為每次移動的距離步長
function animate(obj, target) {
//執行時先清除定時器
clearInterval(obj.timer);
obj.timer = window.setInterval(function () {
//步長值寫在定時器的裡面(隨著改變的)
var step = (target - obj.offsetLeft)/10;
if (obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 50);
}
var div = document.querySelector('div');
var btn = document.querySelector('button');
//呼叫函式(這裡是普通函式)
btn.addEventListener('click',function() {
animate(div,400);
})
</script>
勻速動畫:盒子當前的位置 + 固定的值
緩動動畫: 盒子當前的位置 + 慢慢變小的值
但是有bug,即盒子在按鈕點選後並沒有在400停下,而是395.5:(有了小數就無法達到目標值)——把步長值改為整數,不要出現小數的問題。
/把步長值改為整數,不要出現小數的問題。
//取整步長值Math.ceil 向上取整數
var step = Math.ceil((target - obj.offsetLeft)/10);
7.緩動動畫多個目標值之間移動
使盒子在400~800間來回移動
<body>
<button class="btn400">執行到400</button>
<button class="btn800">執行到800</button>
<div></div>
<script>
// (1)讓盒子每次移動的距離慢慢變小,速度就會慢慢落下來
// (2)核心演算法:(目標值-現在的位置)/10 作為每次移動的距離步長
function animate(obj, target) {
//執行時先清除定時器
clearInterval(obj.timer);
obj.timer = window.setInterval(function () {
//步長值寫在定時器的裡面(隨著改變的)
//把步長值改為整數,不要出現小數的問題。
//取整步長值 往上取整Math.ceil 往下取整Math.floor
//前進的時候 步長取整 8.1 取 9 往大了取
//返回的時候,步長取整是負數,-8.1 應該取-9 ,往小了取
var step =(target - obj.offsetLeft)/10;
//加判斷條件,step是正是負
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {//這裡不能用>= 得用== 不然沒法回來
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 50);
}
var div = document.querySelector('div');
var btn400 = document.querySelector('.btn400');
var btn800 = document.querySelector('.btn800');
//呼叫函式(這裡是普通函式)
btn400.addEventListener('click',function() {
animate(div,400);
})
btn800.addEventListener('click',function() {
animate(div,800);
})
</script>
</body>
8.給緩動動畫添加回調函式
回撥函式原理:函式可以作為一個引數,將這個函式作為引數傳遞到另一個函式裡面,當那個函式執行完之後,再執行傳進去這個函式,這個過程就叫做回撥(callback)。
回撥函式寫的位置:定時器結束
function animate(obj, target,callback) {
//執行時先清除定時器
clearInterval(obj.timer);
obj.timer = window.setInterval(function () {
var step =(target - obj.offsetLeft)/10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
//回撥函式寫到定時器裡面
if (callback) {
//呼叫函式
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 50);
}
btn800.addEventListener('click',function() {
animate(div,800,function() {});
})
重點
1. function animate(obj, target,callback) {
2. clearInterval(obj.timer);
//回撥函式寫到定時器裡面 定時器結束才執行回撥函式
if (callback) {
//呼叫函式
callback();
}
3.btn800.addEventListener('click',function() {
animate(div,800,function() {});
})
9.動畫函式的使用
(1)動畫函式封裝到一個單獨的Js檔案,使用的時候可以引用這個函式
注意offsetleft返回以帶定位父元素的偏移值(父元素有定位,返回與父元素的偏移值)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.sliderbar {
position: fixed;
right: 0;
bottom: 100px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
color: #fff;
}
.con {
/* 父親加了固定定位,以父親為準 */
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: purple;
z-index: -1;
}
</style>
<script src="animate.js"></script>
</head>
<body>
<div class="sliderbar">
<span>←</span>
<div class="con">問題反饋</div>
</div>
<script>
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
sliderbar.addEventListener('mouseenter', function() {//不會冒泡
animate(con,-160,function() {
//當我們動畫執行完畢,就把⬅改為➡
sliderbar.children[0].innerHTML = '➡';
})//沒有callback就直接忽略
})
sliderbar.addEventListener('mouseleave', function() {//不會冒泡
animate(con,0,function() {
//當我們動畫執行完畢,就把⬅改為➡
sliderbar.children[0].innerHTML = '➡';
})//沒有callback就直接忽略
})
</script>
</body>
</html>
重點
<script src="animate.js"></script>
效果