Hello脓豪,我是江工大初學(xué)者。今天要講的是運(yùn)動(dòng)忌卤。
源碼已上傳至github, 需要的小伙伴可以去下載 https://github.com/17714574361/js-linear-motion_1
既然講到運(yùn)動(dòng)扫夜,我們先看一個(gè)問(wèn)題,物體運(yùn)動(dòng)原理是什么驰徊,知道嗎笤闯,我知道你肯定不知道。物體的運(yùn)動(dòng)原理是:通過(guò)改變物體的位置棍厂,而發(fā)生移動(dòng)變化颗味。沒(méi)錯(cuò),就是這幾個(gè)字牺弹。
那么我們?cè)鯓硬拍茉俅a中設(shè)置運(yùn)動(dòng)呢浦马?我們要給運(yùn)動(dòng)的設(shè)置定位屬性,然后通過(guò)設(shè)置left值张漂、top值來(lái)改變物體運(yùn)動(dòng)的位置晶默。
好的。我們先看怎么來(lái)一個(gè)勻速運(yùn)動(dòng)航攒。
勻速運(yùn)動(dòng)
既然是勻速運(yùn)動(dòng)磺陡,我們先設(shè)置一個(gè)總路程,假設(shè)是600漠畜,當(dāng)我們點(diǎn)擊按鈕的時(shí)候币他,我們先清除老的定時(shí)器(否則在運(yùn)動(dòng)的時(shí)候多次點(diǎn)擊按鈕就會(huì)加速運(yùn)行,速度會(huì)越來(lái)越快)憔狞,然后再開(kāi)啟一個(gè)新的定時(shí)器蝴悉,間隔時(shí)間設(shè)置為50ms(你可以修改自己喜歡的時(shí)間間隔),然后我們?cè)僭O(shè)置一個(gè)速度瘾敢,每隔50ms走多少路程辫封,這樣每次50ms box的運(yùn)動(dòng)距離,即left值為box距離左邊的距離+這個(gè)速度廉丽。當(dāng)box運(yùn)動(dòng)到終點(diǎn)是要干嘛倦微,還要繼續(xù)運(yùn)動(dòng)嗎?當(dāng)然是不需要正压,這是我們只要將box的left值設(shè)為總路程即可欣福,這樣運(yùn)動(dòng)就停止了,然后在清除定時(shí)器焦履。
html代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>勻速運(yùn)動(dòng)</title>
<script src="utils.js"></script>
<script src="linear.js"></script>
<link rel="stylesheet" href="linear.css">
</head>
<body>
<button id="start">start</button>
<div id="box"></div>
</body>
</html>
css代碼:
#box {
width: 100px;
height: 100px;
background: seagreen;
position: absolute;
left: 0;
top: 50px;
}
js代碼:
window.onload = function () {
let start = $("start");
let box = $("box");
//總路程
const TOTAL_DISTANCE = 600;
//速度拓劝,每50ms走多少路程
const SPEED = 15;
start.onclick = function () {
//清除老的定時(shí)器雏逾,box.timer就是我們給box添加一個(gè)自定義屬性
clearInterval(box.timer);
//開(kāi)啟一個(gè)新的定時(shí)器
box.timer = setInterval(function () {
box.style.left = box.offsetLeft + SPEED + "px";
//如果box的left值大于總路程,則設(shè)置總路程郑临,
//并清除定時(shí)器栖博,若不清除定時(shí)器,
//就會(huì)一直運(yùn)行此段代碼厢洞,這樣會(huì)減少性能仇让;
if (Number.parseInt(getStyle(box, "left")) > TOTAL_DISTANCE) {
box.style.left = TOTAL_DISTANCE + "px";
clearInterval(box.timer);
}
}, 50);
}
}
//工具類(lèi)↓↓↓
//獲取id
function $(id) {
return document.getElementById(id);
}
//獲取樣式,返回值是帶px的字符串
function getStyle(element, attr) {
return element.currentStyle ? element.currentStyle[attr] : getComputedStyle(element, null)[attr];
}
折返運(yùn)動(dòng)
折返運(yùn)動(dòng)就是往返運(yùn)動(dòng)躺翻,先運(yùn)動(dòng)到終點(diǎn)丧叽,再折回來(lái)起點(diǎn),再運(yùn)動(dòng)到終點(diǎn)公你,這就是折返運(yùn)動(dòng)踊淳,整個(gè)思路更勻速運(yùn)動(dòng)來(lái)時(shí)一樣的,先清除老的定時(shí)器陕靠,原因一樣迂尝,再開(kāi)啟新的定時(shí)器。關(guān)鍵是核心代碼剪芥,怎么才能折回來(lái)呢雹舀?在勻速運(yùn)動(dòng)的基礎(chǔ)上,當(dāng)運(yùn)動(dòng)到終點(diǎn)的時(shí)候粗俱,我們可以減去速度说榆。直接看代碼吧!這里的代碼只是js代碼不一樣寸认,其他和勻速運(yùn)動(dòng)一樣签财,相同的工具類(lèi)代碼我也不貼了。
js代碼:
window.onload = function () {
let start = $("start");
let box = $("box");
//總路程
const TOTAL_DISTANCE = 600;
//速度
let SPEED = 15;
//最小路程,代碼世界中可以為負(fù)數(shù)
const MIN_DISTANCE = 0;
start.onclick = function () {
//清除老的定時(shí)器
clearInterval(box.timer);
box.timer = setInterval(function () {
//設(shè)置速度
box.style.left = box.offsetLeft + SPEED + "px";
/** 當(dāng)box距離左側(cè)的距離 >= 總路程的時(shí)候偏塞,就把速度 * -1
* 這樣下一次就是減去這個(gè)速度
* box.offsetLeft不能寫(xiě)box的left值,寫(xiě)了left值后就會(huì)一直抖動(dòng)
*
*/
if (box.offsetLeft >= TOTAL_DISTANCE) {
SPEED *= -1;
}
//當(dāng)box距離左側(cè)距離 <= 最小距離是唱蒸,就把速度 * -1
//這樣下一次就是加上這個(gè)速度
if (box.offsetLeft <= MIN_DISTANCE) {
SPEED *= -1;
}
}, 50);
}
}
//此處將這個(gè)獲得樣式的方法改了下,返回結(jié)果為number類(lèi)型的數(shù)值
function getStyle(element, attr) {
let result = element.currentStyle ? element.currentStyle[attr] : getComputedStyle(element, null)[attr];
return Number.parseInt(result);
}
緩沖運(yùn)動(dòng)
什么是緩沖運(yùn)動(dòng)灸叼,緩沖運(yùn)動(dòng)就是由加速到減速就是緩沖運(yùn)動(dòng)神汹,也叫減速運(yùn)動(dòng)。
緩沖運(yùn)動(dòng)的思路:我們依然需要總路程和速度古今,只不過(guò)此時(shí)的速度不一樣屁魏,會(huì)發(fā)生變化,那么我們就要考慮怎樣才能讓速度發(fā)生變化捉腥,我們可以將總路程分為8段(你可以設(shè)置成你自己喜歡的段位)氓拼,然后通過(guò)剩下的路程/8計(jì)算出速度,而且這里的速度還不一樣,我們可以看圖桃漾。
當(dāng)物體運(yùn)動(dòng)到A的位置時(shí)坏匪,剩下的路程restDistance/8 和 當(dāng)物體運(yùn)動(dòng)到B的位置時(shí),剩下的路程restDistance/8撬统,可以發(fā)現(xiàn)當(dāng)restDistance的值越小時(shí)适滓,速度也越小,這樣我們可以讓速度越來(lái)越小恋追。剩下的路程怎么算呢凭迹?剩下的路程restDistance = 總路程 - box.offsetLeft。好了几于,這樣就解決了
html,css,工具類(lèi)代碼都一樣蕊苗,所以直接貼js代碼
window.onload = function () {
let start = $("start");
let box = $("box");
//總路程
const TOTAL_DISTANCE = 600;
start.onclick = function () {
//清除老的定時(shí)器
clearInterval(box.timer);
//開(kāi)啟新的定時(shí)器
box.timer = setInterval(function () {
//獲得當(dāng)前box的left值
let currentPosition = getStyle(box, "left");
//速度=剩下的路程/8沿后,8為8段
let speed = (TOTAL_DISTANCE - currentPosition) / 8;
box.style.left = box.offsetLeft + speed + "px";
if (box.offsetLeft >= TOTAL_DISTANCE) {
BOX.style.left = TOTAL_DISTANCE + "px";
clearInterval(box.timer);
}
}, 50);
}
}
加速運(yùn)動(dòng)
加速運(yùn)動(dòng)剛好與緩沖運(yùn)動(dòng)相反
從圖中可以發(fā)現(xiàn)沿彭,運(yùn)動(dòng)到A處時(shí)蛾找,物體A距離左側(cè)的距離是offsetLeft奸披,運(yùn)動(dòng)到B處時(shí)囱皿,物體B距離左側(cè)距離是offsetLeft瓢湃,速度就可以這么算浑厚,speed= offsetLeft / 8业簿,這樣就發(fā)現(xiàn)offsetLeft越大時(shí)赫悄,speed就越大仙畦,這樣物體物體就可做加速運(yùn)動(dòng)了撼唾,但是有個(gè)問(wèn)題廉邑,當(dāng)offsetLeft<4時(shí),物體時(shí)動(dòng)不了的倒谷,這是js的精準(zhǔn)度問(wèn)題蛛蒙,所以至少要是4開(kāi)始(我的代碼寫(xiě)了5)
window.onload = function () {
let start = $("start");
let box = $("box");
//總路程
const TOTAL_DISTANCE = 600;
start.onclick = function () {
//清除老的定時(shí)器
clearInterval(box.timer);
//開(kāi)啟新的定時(shí)器
box.timer = setInterval(function () {
//獲得當(dāng)前box的left值
let currentPosition = getStyle(box, "left");
//速度=物體距離左側(cè)的距離/8,8為8段渤愁,從0開(kāi)始不起效牵祟,直到4開(kāi)始有用
let speed = (currentPosition + 4) / 8;
box.style.left = box.offsetLeft + speed + "px";
if (box.offsetLeft >= TOTAL_DISTANCE) {
box.style.left = TOTAL_DISTANCE + "px";
clearInterval(box.timer);
}
}, 50);
}
}
今天就到這里,明天繼續(xù)抖格。
源碼已上傳至github, 需要的小伙伴可以去下載 https://github.com/17714574361/js-linear-motion_1