js運(yùn)動(dòng)之一(勻速枫攀,折返括饶,緩沖,加速)

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ì)算出速度,而且這里的速度還不一樣,我們可以看圖桃漾。

buffer1.png

當(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)相反

buffer2.png

從圖中可以發(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诺苹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雹拄,更是在濱河造成了極大的恐慌收奔,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滓玖,死亡現(xiàn)場(chǎng)離奇詭異筹淫,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)损姜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)饰剥,“玉大人,你說(shuō)我怎么就攤上這事摧阅√兀” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵棒卷,是天一觀的道長(zhǎng)顾孽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)比规,這世上最難降的妖魔是什么若厚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蜒什,結(jié)果婚禮上测秸,老公的妹妹穿的比我還像新娘。我一直安慰自己灾常,他們只是感情好霎冯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著钞瀑,像睡著了一般沈撞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雕什,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天缠俺,我揣著相機(jī)與錄音,去河邊找鬼贷岸。 笑死壹士,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凰盔。 我是一名探鬼主播墓卦,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼户敬!你這毒婦竟也來(lái)了落剪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤尿庐,失蹤者是張志新(化名)和其女友劉穎忠怖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體抄瑟,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凡泣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞋拟。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骂维,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贺纲,到底是詐尸還是另有隱情航闺,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布猴誊,位于F島的核電站潦刃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏懈叹。R本人自食惡果不足惜乖杠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澄成。 院中可真熱鬧胧洒,春花似錦、人聲如沸环揽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)歉胶。三九已至,卻和暖如春巴粪,著一層夾襖步出監(jiān)牢的瞬間通今,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工肛根, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辫塌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓派哲,卻偏偏與公主長(zhǎng)得像臼氨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子芭届,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容