## 動畫(熟悉)
### 讓每一個元素記錄一個定時器
在上一節的學習中,我們將動畫封裝到了一個animate函數中。這種封裝動畫的方式存在一個存在一個問題,即此時的animate函數只能針對一個元素開啟一個定時器來執行動畫,如果想在頁面中同時讓多個div的運動起來,做不到!此時我們就需要改進animate函數了。那如何才能讓也個頁面中的多個元素同時運動起來呢?
現在的animate做不到讓多個元素同時運動,是因為我們的timeId是共享的,假如每個元素能存儲自己的timeId,這個問題就能解決了。讓元素存儲timeId其實就是將timeId存儲到元素的屬性中,所以我們可修改代碼為如下。
**需求:**讓每一個元素記錄一個定時器;
html和css代碼
~~~
<style>
? ? ? ?#box {
? ? ? ? ? ?position: relative;
? ? ? ? ? ?background-color: red;
? ? ? ? ? ?width: 100px;
? ? ? ? ? ?height: 100px;
? ? ? }
? ? ? ?#box2 {
? ? ? ? ? ?position: relative;
? ? ? ? ? ?background-color: blue;
? ? ? ? ? ?width: 100px;
? ? ? ? ? ?height: 100px;
? ? ? }
? ?</style>
?
<input type="button" value="移動400" id="btn">
<input type="button" value="移動800" id="btn2">
<div id="box"></div>
<div id="box2"></div>
~~~
JavaScript代碼
~~~
//需求:讓每一個元素記錄一個定時器
?
var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var box = document.getElementById('box');
var box2 = document.getElementById('box2');
?
// 1、點擊按鈕,div向右移動
btn.onclick = function () {
? ?animate(box, 400, 10);
}
?
btn2.onclick = function () {
? ?animate(box2, 800, 3);
}
?
// var timeId = null;
//封裝動畫代碼到函數中
function animate(element, target, frequency){
? ?//判斷當前文檔中是否已經啟用定時器,如果啟用,則先銷毀,保證當前點文檔中只有一個定時器在執行動畫
? ?if (element.timeId) {
? ? ? ?clearInterval(element.timeId);
? ? ? ?element.timeId = null;
? }
?
? ?// 2、div不停地向右移動
? ?element.timeId = setInterval(function () {
?
? ? ? ?//步進,開發中,不應該寫死數據
? ? ? ?var step = 3;
? ? ? ?var current = element.offsetLeft;
?
? ? ? ?// 3、div移動到指定的位置,停止移動
? ? ? ?//如果等于500,就停止移動
? ? ? ?if (element.offsetLeft >= target) {
? ? ? ? ? ?clearInterval(element.timeId);
? ? ? ? ? ?element.style.left = target + 'px';
? ? ? ? ? ?return;
? ? ? }
?
? ? ? ?//累加步長
? ? ? ?current += step;
? ? ? ?element.style.left = current + 'px';
?
? }, frequency);
}
?
~~~
### 完善動畫
以上代碼解決了一個頁面總只能執行一個動畫的問題。現在,新的問題又來了,當我們使用兩個按鈕控制一個div運動時,當點擊"移動800"時,div正常地移動到了800的位置,此時當點擊"移動400"時,div一瞬間跳回了400的位置,這就是問題了!當點擊"移動400"時,我么需要的是div以動畫方式緩緩地移動回400的位置。怎么實現這樣的效果呢?
**需求:**讓div從800的位置緩緩移動到400的位置;
**思路:**div在800的位置,當點擊"移動400"時,只需將div的left從800慢慢遞減到400,即可;
html和css代碼
~~~
<style>
? ?#box {
? ? ? ?position: relative;
? ? ? ?background-color: red;
? ? ? ?width: 100px;
? ? ? ?height: 100px;
? }
? ?#box2 {
? ? ? ?position: relative;
? ? ? ?background-color: blue;
? ? ? ?width: 100px;
? ? ? ?height: 100px;
? }
</style>
?
<input type="button" value="移動400" id="btn">
<input type="button" value="移動800" id="btn2">
<div id="box"></div>
?
~~~
JavaScript代碼
~~~
//需求:讓每一個元素記錄一個定時器
?
var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var box = document.getElementById('box');
// var box2 = document.getElementById('box2');
?
// 1、點擊按鈕,div向右移動
btn.onclick = function () {
? ?animate(box, 400, 30);
}
?
btn2.onclick = function () {
? ?animate(box, 800, 30);
}
?
?
// var timeId = null;
//封裝動畫代碼到函數中
function animate(element, target, frequency){
? ?//判斷當前文檔中是否已經啟用定時器,如果啟用,則先銷毀,保證當前點文檔中只有一個定時器在執行動畫
? ?if (element.timeId) {
? ? ? ?clearInterval(element.timeId);
? ? ? ?element.timeId = null;
? }
?
? ?// 2、div不停地向右移動
? ?element.timeId = setInterval(function () {
?
? ? ? ?//步長,開發中,不應該寫死數據
? ? ? ?var step = 10;
? ? ? ?var current = element.offsetLeft;
?
? ? ? ?//當當前位置 > 目標位置時, 步長 step 取負數
? ? ? ?if(current > target){
? ? ? ? ? ?step = -Math.abs(step);
? ? ? }
?
? ? ? ?// 3、div移動到指定的位置,停止移動
? ? ? ?//當當前位置-目標位置 的絕對值小于或等于step的絕對值,則說明應該停止移動了
? ? ? ?// Math.abs(current - target) <= Math.abs(step);
? ? ? ?if (Math.abs(current - target) <= Math.abs(step)) {
? ? ? ? ? ?clearInterval(element.timeId);
? ? ? ? ? ?element.style.left = target + 'px';
? ? ? ? ? ?return;
? ? ? }
?
? ? ? ?//累加步長
? ? ? ?current += step;
? ? ? ?element.style.left = current + 'px';
?
? }, frequency);
}
~~~
### 解決動畫往回移動慢的問題
~~~
當div的left和offleft不同步或者并不相等時,會導致div從800移動到400時的速度很慢。此時需要在頁面中加入樣式 body { margin: 0; },將left的值和offset的值都是從0開始,這樣就解決了問題。
~~~
最后我們得到的animate函數就是移動元素通用的函數了。所有我們可以將animate函數抽取到js文件中,以供將來重復調用。
## 需求
## 需求
注意,以下需求的代碼實現在當天的項目中。
### 無縫輪播圖(掌握)
~~~
================05_輪播圖-動態生成序號================
分析文檔HTML和css結構,歸納出代碼思路:
1、動態生成序號
2、點擊序號,以動畫的方式切換到相應圖片
3、鼠標放到盒子上顯示箭頭
4、實現上一張和下一張的功能
5、自動切換圖片
?
以下對思路進行代碼實現:
1、動態生成序號
(1)獲取頁面上ul中的li個數,作為序號的個數,生成序號
(2)默認序號1高亮顯示,兩種方式
?
================06_輪播圖-點擊序號================
2、點擊序號,動畫的方式切換到圖片
問題:在li上注冊點擊事件,點擊序號時,具體做什么?
2.1 取消其他li的高亮顯示,讓當前li高亮顯示
2.2 點擊序號,動畫的方式切換到當前點擊的圖片
設置li的自定義屬性,用于記錄li的索引
獲取自定義屬性,移動的距離 = li的索引 * 圖片寬度
注意:調用animate函數,移動的方向:往前是負數,往后是正數
?
================07_輪播圖-顯示箭頭01================
3、鼠標放到盒子上顯示箭頭
到此為止,我們好像做了很多分析,寫了很多代碼。我們把每個大的問題分解成了幾個小問題,實際上每個小問題的解決所寫的代碼并不多。
?
==============08_輪播圖-上一張和下一張===============
arrow:箭頭
4、實現上一張和下一張的功能
思路一:當點擊箭頭時,獲取當前選中的圖片索引,索引+1并將圖片切換一個圖片的長度,此種做法可行,但是需要遍歷獲取到當前選中的li;
思路二:從索引為0的那張圖片開始,每點擊一次箭頭,就調用一下animate做相應方向、大小的移動。
?
問題:無縫滾動問題比較復雜,先不做。
可以先采用這樣的方式實現:當移動到最后一張圖片時,再點擊下一張箭頭,圖片不動
?
問題:圖片切換之后,對應圖片的序號沒有高亮顯示。
解決:使用click()方法觸發當前元素的點擊事件來完成點擊,既解決圖片切換問題,又解決序號高亮顯示問題。
?
================11_輪播圖-下一張無縫滾動================
4、實現上一張和下一張的功能
剛開始接觸這樣的需求,如果沒思路沒關系,但是當我們分析了分析了之后,就要會獨立去分析類似的問題,并解決問題。
無縫滾動實現方式:
頁面加載完成時,復制第一張圖片銜接到最后一張圖片后面;此時,當點擊下一張按鈕時,將圖片切換到最后一張圖片上(也就是html中多復制出來的那一張),當再點擊下一張時,將ul的外置瞬間改變成顯示第1張圖片的位置,然后切換到第2張圖片。
?
================12_輪播圖-上一張無縫滾動================
當點擊上一張按鈕時,如果當前是第1張圖片,此時要在一瞬間將第1張切換到最后一張圖片的位置,
?
================13_輪播圖-自動播放================
隔1秒切換到下一張,使用定時器完成。
思路:隔1秒中,點擊(使用click方法)一下按鈕;
問題:鼠標放到圖片上時,沒有停止滾動
解決:當鼠標放到圖片上時,清除定時器;當鼠標移出圖片時,啟動定時器執行動畫。
?
~~~
### 回到頂部(掌握)
~~~
================15_回到頂部01================
以前:代碼都是放到一個文件夾下,比較亂。
現在:把案例看做一下項目,文件分類,放到不同文件夾中,方便開發人員查找文件、維護代碼。
?
1、當拖動滾動條時,當頁面(內容)滾動出去10px的時候,改變top的高度,并顯示回到頂部的按鈕;
?
問題:如何獲取頁面滾動出去的距離?
document.body.scrollTop;
documentElement 網頁中的根元素html
document.documentElement
common中已經做了兼容性處理
?
注意:top是window對象中的只讀屬性,自定義名稱不能為top,否則無法賦值
?
2、當點擊回到頂部按鈕時,動畫的方式,回到最上面,讓頁面滾動距離為0;
?
================16_回到頂部02================
2、當點擊回到頂部按鈕時,動畫的方式,回到最上面,讓滾動距離為0;
使用簡單動畫的邏輯,參考animate()函數。
?
~~~