動畫
動畫原理

動畫原理.png
// 動畫原理
// 1. 獲得盒子當前位置
// 2. 讓盒子在當前位置加上1個移動距離
// 3. 利用定時器不斷重復這個操作
// 4. 加一個結束定時器的條件
// 5. 注意此元素需要添加定位, 才能使用element.style.left
var div = document.querySelector('div');
var btn = document.querySelector('button');
btn.addEventListener("click", function () {
var timer = setInterval(function () {
if (div.offsetLeft > 400) {
clearInterval(timer);
}
div.style.left = div.offsetLeft + 1 + 'px';
}, 10);
})
動畫函數封裝
// 給對象添加屬性的方法
// var obj = {};
// obj.name = 'andy';
// 動畫函數封裝
// 用添加對象屬性的方式,給不同對象添加不同屬性的定時器,節(jié)省內存空間
function animate(obj, target, step){
// 另外,在調用函數之前先清楚掉原來的定時器,以免多次點擊按鈕之后定時器累加造成動畫加速
clearInterval(obj.timer);
obj.timer = setInterval(function () {
if (obj.offsetLeft > target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 10);
}
var box1 = document.querySelector('.box1');
var box2 = document.querySelector('.box2');
var box3 = document.querySelector('.box3');
var btn = document.querySelector('button');
// 調用函數
btn.addEventListener("click", function () {
animate(box1, 400, 1);
animate(box2, 500, 3);
animate(box3, 600, 5);
})
緩動動畫
緩動動畫原理

緩動動畫原理.png
// 緩動動畫原理:
// 1. 讓盒子每次移動的距離慢慢變小, 速度就會慢慢落下來。
// 2. 核心算法:(目標值 - 現在的位置) / 10 做為每次移動的距離 步長
// 3. 停止的條件是: 讓當前盒子位置等于目標位置就停止定時器
function animate(obj, target, speed){
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 緩動動畫需要寫在定時器里面
var step = (target - obj.offsetLeft) / speed;
if (obj.offsetLeft > target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 10);
}
var box1 = document.querySelector('.box1');
var box2 = document.querySelector('.box2');
var box3 = document.querySelector('.box3');
var btn = document.querySelector('button');
// 調用函數
btn.addEventListener("click", function () {
animate(box1, 400, 10);
animate(box2, 500, 20);
animate(box3, 600, 40);
})
緩動動畫在多個目標點之間的移動
// 緩動動畫在多個目標點之間的移動:
function animate(obj, target, speed){
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 緩動動畫需要寫在定時器里面
// JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
var step = (target - obj.offsetLeft) / speed;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 20);
}
var box1 = document.querySelector('.box1');
var btn = document.querySelector('button');
var flag = true;
// 調用函數
btn.addEventListener("click", function () {
if(flag){
animate(box1, 610, 10);
flag = false;
}else{
animate(box1, 10, 10);
flag = true;
}
})
點擊animate按鈕,圖片會在指定位置來回移動
添加回調函數
回調函數作為參數傳進動畫函數當中,會在動畫效果結束后執(zhí)行:
// 緩動動畫添加回調函數:
function animate(obj, target, callback){
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 緩動動畫需要寫在定時器里面
// JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
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';
}, 20);
}
var box1 = document.querySelector('.box1');
var btn = document.querySelector('button');
var flag = true;
// 調用函數
btn.addEventListener("click", function () {
if(flag){
animate(box1, 610, function(){
box1.style.backgroundImage = "url('pic/Megumin.jpg')";
});
flag = false;
}else{
animate(box1, 10, function(){
box1.style.backgroundImage = "url('pic/Kana.jpg')";
});
flag = true;
}
})
上面的例子,緩動動畫效果結束后會更改盒子內的圖片
JS封裝
// 緩動動畫添加回調函數:
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 緩動動畫需要寫在定時器里面
// JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
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();
} */
// 使用邏輯中斷來代替判斷語句
callback&&callback();
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 20);
}
在使用的時候,別忘了在頭文件里引用該js文件:
<script src='animate.js'></script>
輪播圖效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet">
<style>
/*清除元素默認的內外邊距 */
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
}
.main {
width: 610px;
margin: 0 auto;
margin-top: 60px;
}
.focus {
position: relative;
width: 600px;
height: 300px;
border: red 2px solid;
overflow: hidden;
}
img {
width: 600px;
}
li {
list-style: none;
}
ul {
position: absolute;
top: 0;
left: 0;
width: 600%;
}
ul li {
float: left;
}
.arrow-l,
.arrow-r {
display: none;
position: absolute;
top: 50%;
margin-top: -20px;
width: 24px;
height: 40px;
background: rgba(0, 0, 0, .3);
text-align: center;
line-height: 40px;
color: #fff;
font-family: 'icomoon';
font-size: 18px;
z-index: 2;
}
.arrow-r {
right: 0;
}
.circle {
position: absolute;
bottom: 10px;
left: 50px;
}
.circle li {
float: left;
width: 8px;
height: 8px;
/*background-color: #fff;*/
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
border-radius: 50%;
/*鼠標經過顯示小手*/
cursor: pointer;
}
.current {
background-color: #fff;
}
</style>
<script src='animate.js'></script>
</head>
<body>
<div class="main">
<div class="focus">
<!-- 左側按鈕 -->
<a href="javascript:;" class="arrow-l">←</a>
<!-- 右側按鈕 -->
<a href="javascript:;" class="arrow-r">→</a>
<!-- 核心的滾動區(qū)域 -->
<ul>
<li>
<a href="#"><img
src="https://patchwiki.biligame.com/images/blhx/8/87/1axukjehcwyowqeh8f4xobkbvjyija7.jpg"
alt=""></a>
</li>
<li>
<a href="#"><img
src="https://patchwiki.biligame.com/images/blhx/5/5d/aqs86t38ezjjwl1qjlgz9lylsdcojle.jpg"
alt=""></a>
</li>
<li>
<a href="#"><img
src="https://patchwiki.biligame.com/images/blhx/6/66/ntqh7jf5f4ce20qopr5192qxgadbw2x.jpg"
alt=""></a>
</li>
<li>
<a href="#"><img
src="https://patchwiki.biligame.com/images/blhx/f/f4/izxkrqb9iey4ooqws4dimq8r0yttx7b.jpg"
alt=""></a>
</li>
<li>
<a href="#"><img
src="https://patchwiki.biligame.com/images/blhx/3/33/0kz6xpi03oisfing6l3w4547hag1kpr.jpg"
alt=""></a>
</li>
</ul>
<!-- 小圓圈 -->
<ol class="circle">
</ol>
</div>
</div>
<script>
// 網頁輪播圖
// 需求:
// 1. 鼠標經過輪播圖模塊,左右按鈕顯示,離開即隱藏兩個按鈕
// 2. 點擊右側按鈕一次,圖片往左播放一次,反之則向右播放一張
// 3. 圖片播放時,下面的小圓點跟隨一起變化
// 4. 點擊小圓點,可以播放對應的圖片
// 5. 鼠標不經過輪播圖模塊,會自動播放圖片
// 6. 鼠標經過時,自動播放停止
// 獲取元素
var box = document.querySelector('.focus');
var arrow_l = document.querySelector('.arrow-l');
var arrow_r = document.querySelector('.arrow-r');
var pic = document.querySelector('img');
var ul = document.querySelector('ul');
var ol = document.querySelector('.circle');
var num = 0;
var dot = 0;
var flag = true; // 節(jié)流閥
// 顯示/隱藏箭頭
box.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block'
arrow_r.style.display = 'block'
clearInterval(timer);
timer = null; // 清楚定時器變量
});
box.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none'
arrow_r.style.display = 'none'
timer = setInterval(function () {
arrow_r.click();
}, 2000);
});
// 動態(tài)生成小圓圈
// console.log(pic.length);
for (var i = 0; i < ul.children.length; i++) {
var li = document.createElement('li');
li.setAttribute('index', i);
ol.append(li);
// 小圓圈的排他算法
li.addEventListener('click', function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = '';
}
this.className = 'current';
// 對應圖片跳轉
var index = this.getAttribute('index');
// console.log(index);
animate(ul, -index * pic.clientWidth);
num = index;
dot = index;
})
}
ol.children[0].className = 'current';
/* ol.addEventListener('click',function(e){
for(var i = 0; i < ul.children.length; i++){
ol.children[i].className = '';
}
e.target.className = 'current';
console.log(e.target);
}) */
// 這里雖然想到用事件委托,雖然點擊圓點也能實現相應效果
// 但是如果不小心點到圓點之間的間隔,e.target會判定是ol,所有小圓點都會消失
// 將第一張圖片復制到最后面,利用視覺差來做出循環(huán)效果
// 因為克隆是在小圓點生成之后,所以不會影響小圓點的總數量
var firstPic = ul.children[0].cloneNode(true); // 完全克隆
ul.appendChild(firstPic);
// 點擊箭頭跳轉圖片
arrow_r.addEventListener('click', function () {
if (flag) {
flag = false; // 關閉節(jié)流閥
// 圖片無縫滾動
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * pic.clientWidth, function () {
flag = true; // 打開節(jié)流閥
});
dot++;
if (dot == ol.children.length) {
dot = 0;
}
circleChange();
}
});
arrow_l.addEventListener('click', function () {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * pic.clientWidth + 'px';
}
num--;
animate(ul, -num * pic.clientWidth, function(){
flag = true;
});
dot--;
dot = dot < 0 ? ol.children.length - 1 : dot;
circleChange();
}
});
// 更改圓點位置
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[dot].className = 'current';
};
// 自動輪播功能
var timer = setInterval(function () {
// 手動調用事件
arrow_r.click();
}, 2000);
</script>
</body>
</html>
說明一下什么是節(jié)流閥:

節(jié)流閥.png
返回頂部動畫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet">
<style>
.slide-bar {
position: absolute;
left: 50%;
top: 300px;
margin-left: 600px;
width: 45px;
height: 130px;
background-color: pink;
}
.w {
width: 1200px;
margin: 10px auto;
}
.header {
height: 150px;
background-color: purple;
}
.banner {
height: 250px;
background-color: skyblue;
}
.main {
height: 1000px;
background-color: yellowgreen;
}
span {
display: none;
position: absolute;
bottom: 0;
}
.goBack {
display: none;
}
</style>
</head>
<body>
<div class="slide-bar">
<a class="goBack">Top</a>
</div>
<div class="header w">Header</div>
<div class="banner w">Bannner</div>
<div class="main w">Main</div>
<script>
// 仿淘寶側邊固定欄
var slide_bar = document.querySelector('.slide-bar');
var banner = document.querySelector('.banner');
var bannerTop = banner.offsetTop;
var slideBarTop = slide_bar.offsetTop - bannerTop;
var main = document.querySelector('.main');
var btn = document.querySelector('.goBack');
var mainTop = main.offsetTop;
// 頁面滾動事件
document.addEventListener('scroll', function () {
// window.pageYOffset 頁面被卷去的頭部
console.log(window.pageYOffset);
// 當頁面卷到banner欄時,固定slideBar在頁面的顯示位置,
if (window.pageYOffset >= bannerTop) {
slide_bar.style.position = 'fixed'
slide_bar.style.top = slideBarTop + 'px';
} else {
slide_bar.style.position = 'absolute';
slide_bar.style.top = '300px';
}
// 當頁面卷到main盒子時,顯示top模塊
if (window.pageYOffset >= mainTop) {
btn.style.display = 'block';
} else {
btn.style.display = 'none';
}
});
slide_bar.addEventListener('click',function(){
animate(window, 0);
})
// 緩動動畫添加回調函數:
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 緩動動畫需要寫在定時器里面
// JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
var step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (window.pageYOffset == target) {
clearInterval(obj.timer);
// 回調函數寫在清除定時器的判斷條件里
/* if (callback) {
callback();
} */
// 使用邏輯中斷來代替判斷語句
callback && callback();
}
// obj.style.left = obj.offsetLeft + step + 'px';
window.scroll(0, window.pageYOffset + step);
}, 20);
}
</script>
</body>
</html>
其實只需要把動畫的目標地點從水平更改為垂直就行了