Javascript中的運動
阿新 • • 發佈:2018-11-07
一、勻速運動
可以通過offsetLeft/top獲取自身的實時位置,在自身的位置的基礎上,通過定時器不斷執行,每次在自身位置的基礎上再加上一個恆定的速度值,即可形成一個簡單的勻速運動。
function move1(dom, target) { clearInterval(dom.timer); dom.timer = setInterval(function () { if (dom.offsetLeft == target) { clearInterval(dom.timer); dom.style.left = target + 'px'; } else { dom.style.left = dom.offsetLeft + 10 + 'px'; } }, 30); }
二、緩衝運動
緩衝運動也就是速度由快到慢最後停止的一個過程。而方塊的自身動態位置(或透明度)與終點的位置(或透明度)的差值,剛好滿足這樣一個速度變化的趨勢。
//緩衝運動 function move2(dom, target) { clearInterval(dom.timer); dom.timer = setInterval(function () { //offsetLeft越來越大 iSpeed越來越小 var iSpeed = (target - dom.offsetLeft) / 7; //因為offsetLeft取出來會自動取整,忽略小數,最後每次加小數的時候都會死迴圈將自己變成整數不變,此時將最後加的小數取整,解決這個問題; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (dom.offsetLeft == target) { clearInterval(dom.timer); dom.style.left = target + 'px'; } else { dom.style.left = dom.offsetLeft + iSpeed + 'px'; } }, 30); } //緩衝運動---改變透明度 //target應是(0-100)之間的數字 function changeOpacity(dom, target) { clearInterval(dom.timer); dom.timer = setInterval(function () { //因為透明度的值始終是一個0——1之間的數,速度變化太快,所以給它擴大100倍 var iCur = parseFloat(getStyle(dom, 'opacity')) * 100; var iSpeed = (target - iCur) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur == target) { clearInterval(dom.timer); //因為之前擴大了100倍,此處是將其值還原成0-1之間的數字 dom.style.opacity = iCur / 100; } else { //因為之前擴大了100倍,此處是將其值還原成0-1之間的數字 dom.style.opacity = (iCur + iSpeed) / 100; } }, 30); } //多值變化 // var target = { // 'width': 300, // 'opacity': 50 // } function changeMultValue(dom, obj) { clearInterval(dom.timer); var iCur, iSpeed; dom.timer = setInterval(function () { var flag = true; for (var prop in obj) { if (prop == 'opacity') { iCur = parseFloat(getStyle(dom, prop)) * 100; } else { iCur = parseInt(getStyle(dom, prop)); } iSpeed = (obj[prop] - iCur) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (prop == 'opacity') { dom.style[prop] = (iCur + iSpeed) / 100; } else { dom.style[prop] = iCur + iSpeed + 'px'; } if (iCur != obj[prop]) { flag = false; } } if (flag) { //所有值都已變化完成後,才清除定時器 clearInterval(dom.timer); } }, 30); } //多物體多值鏈式變化 function changeMult(dom, obj, callback) { clearInterval(dom.timer); var iCur, iSpeed; dom.timer = setInterval(function () { var flag = true; for (var prop in obj) { if (prop == 'opacity') { iCur = parseFloat(getStyle(dom, prop)) * 100; } else { iCur = parseInt(getStyle(dom, prop)); } iSpeed = (obj[prop] - iCur) / 7; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (prop == 'opacity') { dom.style[prop] = (iCur + iSpeed) / 100; } else { dom.style[prop] = iCur + iSpeed + 'px'; } if (iCur != obj[prop]) { flag = false; } } if (flag) { clearInterval(dom.timer); typeof callback == 'function' ? callback() : ''; } }, 30); } //多物體多值鏈式變化呼叫方式 // var arr = document.getElementsByTagName('div'); // var obj = { // left: 400, // top: 100, // width: 400, // height: 400, // opacity: 50 // }; // //鏈式操作 第一個運動完 第二個立馬開始 // arr[0].onclick = function () { // changeMult(this, obj, function () { // changeMult(arr[1], obj,''); // }); // } //獲取樣式 function getStyle(dom, prop) { if (window.getComputedStyle) { return window.getComputedStyle(dom, null)[prop]; } else { return dom.currentStyle[prop]; } }
三、彈性運動
1、勻加(減)速運動
通過每次給速度值加上一個固定的值,每次速度都會增加,使之變成一個勻加速的運動;
//彈性運動1:target左邊 速度不斷增加 target右邊 速度不斷減小 function move1(dom, target) { clearInterval(dom.timer); var iSpeed = 20; var a = 3; dom.timer = setInterval(function () { if (dom.offsetLeft > target) { iSpeed -= a; } else { iSpeed += a; } dom.style.left = dom.offsetLeft + iSpeed + 'px'; }, 30); }
2、變加(減)速運動
function move(dom, target) {
clearInterval(dom.timer);
var iSpeed = 20;
var a;
var u = 0.9;
dom.timer = setInterval(function () {
a = (target - dom.offsetLeft) /8;
// 這裡將目標值減去當前位置,這種情況下,當距離目標值越近,分子越小,速度越慢,所以為減速運動;當超過目標值的情況下,速度變成負數,在原來speed的基礎上,speed慢慢減少,直到最後變成0,然後變成負數,一旦變成負數,就會開始往反方向也就是往回運動;我們不難發現,其實當物體面向中心的目標值運動時,離得越遠,速度越快。離得越近甚至超過中心點的時候,速度一直在減少;就這樣一個速度變化的趨勢,剛好滿足我們所需要的一個彈性運動 ;
iSpeed += a;
iSpeed *= u;
//給一個相當於摩擦係數u,讓其速度值越來越接近於0,運動一定程度時停止
if (Math.abs(iSpeed) < 1 && Math.abs(target - dom.offsetLeft) < 1) {
//因為當最後速度在減少到非常小的時候,每次乘0.8,會形成很長位數的小數而不會真正歸零,所以我們用絕對值判斷,只要小於1px我們就讓他停止
clearInterval(dom.timer);
} else {
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}
}, 30);
}
四、模擬重力場
var div = document.getElementsByTagName('div')[0];
div.onmousedown = function (e) {
clearInterval(div.timer);
var event = e || window.event;
var disX = event.clientX - this.offsetLeft;
var disY = event.clientY - this.offsetTop;
var lastX = this.offsetLeft;
var lastY = this.offsetTop;
document.onmousemove = function (e) {
//讓方塊隨著滑鼠移動
var event = e || window.event;
var nowX = event.clientX - disX;
var nowY = event.clientY - disY;
iSpeedX = nowX - lastX;
iSpeedY = nowY - lastY;
div.style.left = nowX + 'px';
div.style.top = nowY + 'px';
lastX = nowX;
lastY = nowY;
}
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
//讓方塊以最後位置時的速度作為初速度繼續運動,相當於慣性運動
move(div, iSpeedX, iSpeedY)
}
}
function move(dom, iSpeedX, iSpeedY) {
//進入函式先清除定時器;防止多次觸發;
clearInterval(dom.timer);
var clientX = getSize().w, clientY = getSize().h, newLeft, newTop;
var a = 6, u = 0.8;
dom.timer = setInterval(function () {
iSpeedY += a;
newLeft = dom.offsetLeft + iSpeedX;
newTop = dom.offsetTop + iSpeedY;
//運動到四周邊界時,變換方向,減小速度
if (newTop > clientY - dom.offsetHeight) {
iSpeedY *= -1;//變換方向
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newTop = clientY - dom.offsetHeight;
}
if (newTop < 0) {
iSpeedY *= -1;
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newTop = 0;
}
if (newLeft > clientX - dom.offsetWidth) {
iSpeedX *= -1;
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newLeft = clientX - dom.offsetWidth;
}
if (newLeft < 0) {
iSpeedX *= -1;
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newLeft = 0;
}
if (Math.abs(iSpeedX) <= 1) {
iSpeedX = 0;
}
if (Math.abs(iSpeedY) <= a * 0.8) {
iSpeedY = 0;
}
//運動到底部且兩個方向上的速度都為0,讓其停止,
if (iSpeedX == 0 && iSpeedY == 0 && newTop == (clientY - dom.offsetHeight)) {
clearInterval(dom.timer);
}
dom.style.left = newLeft + 'px';
dom.style.top = newTop + 'px';
}, 30);
}
//獲取視窗大小
function getSize() {
if (window.innerWidth) {
return {
w: window.innerWidth,
h: window.innerHeight
}
} else if (document.body.clinetWidth) {
return {
w: document.body.clinetWidth,
h: document.body.clientHeight
}
} else {
return {
w: document.documentElement.clientWidth,
h: document.documentElement.clientHeight
}
}
}