一、緩動效果原理
緩動動畫就是讓元素運動速度有所變化,最常見的就是讓元素慢慢停下來
思路:
- 讓盒子每次移動的距離慢慢變小,速度就會慢慢降下來
- 核心算法:(目標值-現在位置)/10作為每次移動距離的步長
- 停止條件:讓盒子位置等于目標位置就停止計時器
案例:點擊按鈕后盒子緩停
css:
div {position: absolute;left: 0;top: 40px;width: 200px;height: 200px;background-color: pink;
}
?HTML:
<div></div>
<button>點我開始走</button>
JavaScript:
function annimate(obj, target) {clearInterval(obj.timer);obj.timer = setInterval(function () {var step = (target - obj.offsetLeft) / 10;if (obj.offsetLeft == target) {clearInterval(obj.timer);}obj.style.left = obj.offsetLeft + step + 'px';}, 15)
}
var div = document.querySelector('div');
var button = document.querySelector('button');
button.addEventListener('click', function () {annimate(div, 500);
})
寫完運行發現,這個案例有小bug,它并沒有準準的停在我們設置的目標位置,因為它涉及到了除法,有小數點后就慢慢沒那么精確了
那么我們就把step向上取整,盡量避免小數運算,向上取整是因為能延緩速度的變化,讓緩動效果更加柔和
var step = Math.ceil(target - obj.offsetLeft) / 10;
不過這樣寫忽略了后退時的效果,比如
<div></div>
<button>點我到500</button>
<button>點我到800</button>
function annimate(obj, target) {clearInterval(obj.timer);obj.timer = setInterval(function () {var step = (target - obj.offsetLeft) / 10;if (obj.offsetLeft == target) {clearInterval(obj.timer);}obj.style.left = obj.offsetLeft + step + 'px';}, 15)
}
var div = document.querySelector('div');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function () {annimate(div, 500);
})
btn800.addEventListener('click', function () {annimate(div, 800);
})
在這個時候前進能準確到目標位置,但是后退時不能,按照上面修復bug的思路看,是取整出現問題了,和前面相似,后退時應該向下取整
那我們給step加上一個判斷條件,如果大于0則向上取整,小于0則向下取整
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
二、動畫函數添加回調函數
回調函數原理:函數可以當成一個參數,把一個函數作為參數傳到另一個函數里面,那個函數執行完后再來執行傳進去的參數,這個過程叫回調
回調函數寫的位置:定時器結束的位置
?案例:在移動完后輸出你好
css:
* {margin: 0px;padding: 0px;
}div {position: absolute;left: 0;top: 40px;width: 200px;height: 200px;background-color: pink;
}
HTML:?
<div></div>
<button>點我到500</button>
<button>點我到800</button>
JavaScript:?
function annimate(obj, target) {clearInterval(obj.timer);obj.timer = setInterval(function () {var step = (target - obj.offsetLeft) / 10;if (obj.offsetLeft == target) {clearInterval(obj.timer);if (callback) {callback();}}obj.style.left = obj.offsetLeft + step + 'px';}, 15)
}
var div = document.querySelector('div');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function () {annimate(div, 800, function () {alert('你好');});
})
btn800.addEventListener('click', function () {annimate(div, 800, function () {alert('你好');});
})
三、動畫函數封裝到單獨JS文件里面
因為以后要常用動畫函數,所以我們把它封裝到JS文件里面,下次要用直接引用就可以了
?步驟:
- 單獨新建一個JS文件
- 把我們寫的這個函數復制進JS文件里
- 調用JS文件
- 直接調用動畫函數
案例:鼠標經過它后滑出來‘問題反饋’
css:
.sliderbar {position: relative;left: -9px;height: 40px;width: 40px;text-align: center;line-height: 40px;color: #fff;background-color: purple;
}.con {position: absolute;padding: 0 5px;left: -130px;height: 40px;width: 160px;background-color: purple;z-index: -1;
}
HTML:
記得不要忘記調用JS文件
<script src="annimater.js"></script>
<div class="sliderbar"><span>→</span><div class="con">問題反饋</div>
</div>
JavaScript:
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
sliderbar.addEventListener('mouseenter', function () {annimate(con, 40, function () {sliderbar.children[0].innerHTML = '←';})
})
sliderbar.addEventListener('mouseleave', function () {annimate(con, -160,, function () {sliderbar.children[0].innerHTML = '→';})
})
四、網頁特效案例
案例:網頁輪播圖
css:
.main {width: 980px;height: 455px;margin-left: 242px;
}.focus {position: relative;width: 715px;height: 455px;overflow: hidden;
}.focus ul {position: absolute;top: 0;left: 0;width: 1100%;
}.focus li {float: left;
}.focus img {/* width: 715px; */height: 455px;
}.lft,
.rit {background: rgba(72, 68, 69, .3);width: 15px;height: 20px;z-index: 999;display: none;
}.lft {position: absolute;top: 231px;left: 0;
}.rit {position: absolute;top: 231px;right: 0px;
}.lft a,
.rit a {color: #f9f9f9;
}.lft,
.rit a:hover {color: #ccc;
}.circle {position: absolute;bottom: 10px;left: 295px;
}.circle li {float: left;width: 8px;height: 8px;border: 2px solid rgba(255, 255, 255, .5);margin: 0 3px;border-radius: 50%;cursor: pointer;
}.current {background-color: #fff;
}
HTML:
<div class="focus fl"><div class="lft"><a href="javascript:;"><</a></div><div class="rit"><a href="javascript:;">></a></div><ul><li><a href="#"><img src="images/loginbg.png" alt=""></a></li><li><a href="#"><img src="images/loginbg.png" alt=""></a></li><li><a href="#"><img src="images/loginbg.png" alt=""></a></li><li><a href="#"><img src="images/loginbg.png" alt=""></a></li><li><a href="#"><img src="images/loginbg.png" alt=""></a></li><li><a href="#"><img src="images/loginbg.png" alt=""></a></li></ul><ol class="circle"></ol>
</div>
JavaScript:
window.addEventListener('load', function () {var lft = document.querySelector('.lft');var rit = document.querySelector('.rit');var focus = document.querySelector('.focus');focus.addEventListener('mouseenter', function () {lft.style.display = 'block';rit.style.display = 'block';clearInterval(timer);timer = null;})focus.addEventListener('mouseleave', function () {lft.style.display = 'none';rit.style.display = 'none';timer = setInterval(function () {rit.click();}, 2000)})var ul = focus.querySelector('ul');var ol = focus.querySelector('.circle');for (var i = 0; i < ul.children.length; i++) {var li = document.createElement('li');li.setAttribute('index', i);ol.appendChild(li);li.addEventListener('click', function () {for (var i = 0; i < ol.children.length; i++) {ol.children[i].className = '';}this.className = 'current';var index = this.getAttribute('index');num = index;circle = index;var focusWidth = focus.offsetWidth;annimate(ul, -index * 1044);})}ol.children[0].className = 'current';var first = ul.children[0].cloneNode(true);ul.appendChild(first);var num = 0;var circle = 0;rit.addEventListener('click', function () {if (num == ul.children.length - 1) {ul.style.left = 0;num = 0}num++;annimate(ul, -num * 1044)circle++;if (circle == ol.children.length) {circle = 0;}circleChange();})lft.addEventListener('click', function () {if (num == 0) {num = ul.children.length - 1;ul.style.left = -num * 1044 + 'px';}num--;annimate(ul, -num * 1044)circle--;if (circle < 0) {circle = ol.children.length - 1;}circleChange();})function circleChange() {for (var i = 0; i < ul.children.length; i++) {ol.children[i].className = '';ol.children[circle].className = 'current';}}var timer = setInterval(function () {rit.click();}, 2000)
})
?