JavaScript之運動(各種運動)
阿新 • • 發佈:2021-01-29
一、勻速運動
首先,我們的想法只是簡單的向右勻速運動,運用到的是計時器方法。
<div id="oDiv"></div>
<span id="oSpan"></span>
<button id="btn">開始</button>
<script>
var oDiv = document.getElementById('oDiv');
var btn = document.getElementById('btn');
btn.onclick = function() {
var iSpend = null;
setInterval(function() {
iSpeed = 3;
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}, 30);
}
</script>
此時,div會以30毫秒向右移動3個畫素,oDiv.offsetLeft是獲取div當前的left值(數值型別),此時存在問題,div會不停的向右運動,下方會出現滾動條,每次點選按鈕,div還會加速,加速的原因是因為每點選一次都會觸發一個計時器疊加。
1、我們將span設定成一條黑線,在右方400px位置,讓div到位置自動停下。
2、每次點選會將計時器清空一次,重新建立一個計時器,解決加速問題。
直接看優化程式碼
<div id="oDiv"></div>
<span id="oSpan"></span>
<button id="btn">開始</button>
<script>
var oDiv = document.getElementById('oDiv' );
var btn = document.getElementById('btn');
var timer = null;
btn.onclick = function() {
clearInterval(timer);
var iSpend = null;
timer = setInterval(function() {
iSpeed = 4;
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
if (oDiv.offsetLeft == 400) {
clearInterval(timer);
}
}, 30);
}
</script>
看效果圖
上面程式碼我們將iSpeed設定成4,是400的倍數,在判斷位置的時候剛好能在指定位置停下,此時又存在兩個問題。
新的問題
1、如果iSpeed的值不能被400整除,div將不會停下
2、如果div在固定位置的右邊
在優化這兩個問題同時,我們把這個勻速運動功能封裝成函式。
<script>
var oDiv = document.getElementById('oDiv');
var btn = document.getElementById('btn');
btn.onclick = function() {
startMove(oDiv, 400)
// clearInterval(timer);
// timer = setInterval(function() {
// var iSpeed = -oDiv.offsetLeft;
// oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
// if (oDiv.offsetLeft == 400) {
// clearInterval(timer);
// }
// }, 30);
}
function startMove(dom, target) {
var timer = null;
clearInterval(timer);
var iSpeed = target - dom.offsetLeft > 0 ? 7 : -7;
timer = setInterval(function() {
if (Math.abs(target - dom.offsetLeft) < Math.abs(iSpeed)) {
clearInterval(timer);
dom.style.left = target + 'px';
} else {
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}
}, 30);
}
</script>
上面的div的left的值被設定為700px,截止到此,勻速運動問題基本解決。
二、緩衝運動
物體的速度 距離目標點越近 就越小 當到達目標點時 速度減小為0
var oDiv = document.getElementById('oDiv');
var btn = document.getElementById('btn');
btn.onclick = function () {
startMove(oDiv, 400);
}
function startMove (dom, target) {
clearInterval(timer);
var iSpeed = null,timer = null;
timer = setInterval(function () {
iSpeed = (target - oDiv.offsetLeft) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (oDiv.offsetLeft == target) {
clearInterval(timer);
}else {
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}
}, 30);
}
Math.ceil() “向上取整”, 即小數部分直接捨去,並向正數部分進1
Math.floor() “向下取整” ,即小數部分直接捨去
透明度緩衝變化
<div id="oDiv"></div>
<span id="oSpan"></span>
<button id="btn">開始</button>
<script>
var oDiv = document.getElementById('oDiv');
var btn = document.getElementById('btn');
btn.onclick = function() {
startMove(oDiv, 50);
}
function getStyle(dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
} else {
return dom.currentStyle[attr];
}
}
function startMove(dom, target) {
var timer = null;
clearInterval(timer);
var iSpeed = null,
iCur = null;
timer = setInterval(function() {
iCur = parseFloat(getStyle(dom, 'opacity')) * 100;
iSpeed = (target - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(timer);
} else {
// 0 - 1 iCur * 100 target * 100 iSpeed * 100 iCur + iSpeed 0 - 100 / 100
dom.style.opacity = (iCur + iSpeed) / 100;
}
}, 30);
}
點選之後,div顏色慢慢變成0.5
多物體運動
<div></div>
<div></div>
<div></div>
<div></div>
var oDivArray = document.getElementsByTagName('div');
for (var i = 0; i < oDivArray.length; i++) {
oDivArray[i].onmouseenter = function () {
startMove(this, 400);
}
oDivArray[i].onmouseleave = function () {
startMove(this, 100);
}
}
function getStyle(dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
} else {
return dom.currentStyle[attr];
}
}
function startMove (dom, target) {
var timer = null;
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
iCur = parseInt( getStyle(dom, 'width') );
iSpeed = ( target - iCur ) / 7;
// ....
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(dom.timer);
}else {
dom.style.width = iCur + iSpeed + 'px';
}
}, 30);
}
多物體不同值的運動
<div></div>
<div></div>
<div></div>
<div></div>
var timer = null;
var oDivArray = document.getElementsByTagName('div');
oDivArray[0].onclick = function () {
startMove(this, 'width', 400);
}
oDivArray[1].onclick = function () {
startMove(this, 'height', 400);
}
oDivArray[2].onclick = function () {
startMove(this, 'borderWidth', 20);
}
oDivArray[3].onclick = function () {
startMove(this, 'opacity', 50);
}
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, attr, target) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
if (attr == 'opacity') {
iCur = parseFloat( getStyle(dom, attr) ) * 100;
}else {
iCur = parseInt( getStyle(dom, attr) );
}
iSpeed = (target - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(dom.timer);
}
if (attr == 'opacity') {
dom.style.opacity = ( iCur + iSpeed ) / 100;
}else {
dom.style[attr] = iCur + iSpeed + 'px';
}
}, 30);
}
四個不同的div各自變化各自的一個值
多物體多值運動+回撥機制
div {
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background: red;
opacity: 1;
}
#topDiv {
top: 200px;
}
#bottomDiv {
top: 400px;
}
<div id='topDiv'></div>
<div id="bottomDiv"></div>
<script>
// js div
// width -> 100 400 height 100 400 left 0 200 top 200 300 opacity 1 0.5
// {width: 400, height: 400, left: 200, top: 300, opacity: 50}
var oTopDiv = document.getElementById('topDiv');
var oBottomDiv = document.getElementById('bottomDiv');
oTopDiv.onclick = function () {
startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
startMove(oBottomDiv, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
alert('over');
})
})
}
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, attrObj, callback) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
var bStop = true;
for (var attr in attrObj) {
// 'width' 'height'
if (attr == 'opacity') {
iCur = parseFloat( getStyle(dom, attr) ) * 100;
}else {
iCur = parseInt( getStyle(dom, attr) );
}
iSpeed = (attrObj[attr] - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (attr == 'opacity') {
dom.style.opacity = (iCur + iSpeed) / 100;
}else {
dom.style[attr] = iCur + iSpeed + 'px';
}
if (iCur != attrObj[attr]) {
bStop = false;
}
}
if (bStop) {
clearInterval(dom.timer);
typeof callback == 'function' && callback();
}
}, 30);
}
運動基本上就結束了,之後還有加速運動、彈性運動等