中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

JavaScript動畫 —— 彈動動畫

2018-07-20    來源:open-open

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

緩動和彈動都是那對象從已有位置移動到目標(biāo)位置的方法。但是緩動是指物體滑動到目標(biāo)點就停下來;而彈動是指物體來回反彈一段時間后,最終停在目標(biāo)點的運動。

彈動,大多數(shù)時候,物體的加速度與它到目標(biāo)點的距離是成比例的。

來看一個在現(xiàn)實中彈動的例子:在橡皮筋的一頭系上一個小球,另一頭固定起來。小球的目標(biāo)點就是它初始靜止懸空的那個位置點。將小球拉開一小段距離然后松開,剛松手那一瞬間,它的速度為0,但是橡皮筋給它施加了外力,把它拉向目標(biāo)點;如果小球盡可能地拉遠,橡皮筋對它施加的外力就會變得越大。松手后,小球會急速飛過目標(biāo)點。但是,當(dāng)它飛過目標(biāo)點以后,橡皮筋又把它往回拉,使其加速度減小,它飛得越遠,橡皮筋施加的力就越大;最終,它的速度降為0,又掉頭往回飛。由于受到摩擦力的影響,反復(fù)幾次后,小球的運動逐漸慢下來,停在目標(biāo)點上。

一. 一維坐標(biāo)上的彈動

1 . 首先需要一個變量存儲彈性比例系數(shù),取值為0~1,較大的彈性比例常熟會表現(xiàn)出較硬的彈簧效果。

var spring = 0.1,
    targetX = canvas.width / 2,
    vx = 0;

2 . 接下來,計算小球到目標(biāo)點的距離

var dx = targetX - ball.x;

3 . 計算加速度。在這個例子中,我們設(shè)置小球的加速度與距離成正比,即加速度 = 小球到目標(biāo)點的距離 × 彈性比例系數(shù)。

var ax = dx * spring;

4 . 把加速度累加到速度上,然后把速度累加到小球的當(dāng)前位置上:

vx += ax;
ball.x += vx;

在開始寫代碼前,先模擬一下整個過程,假設(shè)ball.x = 0,初速度vx = 0,目標(biāo)點的位置targetX = 100,彈性比例系數(shù)spring = 0.1。下面是執(zhí)行過程:

(1) 第一輪,加速度ax = (100 - 0) * 0.1 = 10,把ax加載vx上得速度vx = 10,把vx加在小球的當(dāng)前位置上得到ball.x = 10;

(2) 第二輪,加速度ax = (100 - ball.x) * 0.1 = 9,由此得到vx = 10 + 9 = 19,ball.x = 10 + 19 = 29;

(3) 第三輪,ax = 7.1, vx = 26.1,ball.x = 55.1;

(4) 第四輪, ax = 4.49,vx = 30.59,ball.x = 85.69;

(5) 第五輪, ax = 1.431,vx = 44.9,ball.x = 130.69:

(6) 第六輪,ax = -3.069,vx = 41.831,ball.x = 88.859;

... ...

隨著小球一幀一幀地靠近目標(biāo),加速度變得越來越小,但是速度一直在增加;

五輪過后,小球越過了目標(biāo)點后,加速度變成反向加速度,并且逐漸增加,導(dǎo)致速度逐漸減小,最終速度為0后,反向加速度達到極大值。此時速度將變成反向速度。

HTML代碼如下:

<canvas id="canvas" width="600" height="100"></canvas>

JavaScript代碼如下:

// requestAnimationFrame的兼容性寫法
window.requestAnimFrame = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            window.oRequestAnimationFrame      ||
            window.msRequestAnimationFrame     ||
            function( callback ){
                window.setTimeout(callback, 1000 / 60);
            };
})();

// cancelAnimationFrame的兼容性寫法
window.cancelAnimationFrame = (function () {
    return window.cancelAnimationFrame ||
            window.webkitCancelAnimationFrame ||
            window.mozCancelAnimationFrame ||
            window.oCancelAnimationFrame ||
            function (timer) {
                window.clearTimeout(timer);
            };
})();

// 創(chuàng)建畫球函數(shù)
function Ball() {
    this.x = 0;
    this.y = 0;
    this.radius = 10;
    this.fillStyle = "#f85455";
    this.draw = function(cxt) {
        cxt.fillStyle = this.fillStyle;
        cxt.beginPath();
        cxt.arc(this.x, this.y, this.radius,  0, 2 * Math.PI, true);
        cxt.closePath();
        cxt.fill();
    }
}

var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        ball = new Ball(),
        spring = 0.1,
        targetX = canvas.width / 2,
        vx = 0;
ball.x = 20;
ball.y = 20;

// 緩動動畫函數(shù)
var animRequest = null;
(function drawFrame() {
    animRequest = window.requestAnimationFrame(drawFrame, canvas);
    context.clearRect(0, 0, canvas.width, canvas.height);
    // 小球當(dāng)前位置與目標(biāo)點的距離
    var dx = targetX - ball.x;
    // 小球的加速度
    var ax = dx * spring;
    // 小球的速度
    vx += ax;
    // 計算出小球當(dāng)前的位置
    ball.x += vx;
    ball.draw(context);
})();

實現(xiàn)的效果如下:

See the Pen <a _>EVNWqL</a> by dengzhirong (<a _>@dengzhirong</a>) on <a _>CodePen</a>.

但是!但是,問題是小球永遠都不會停下來,因為小球的擺動幅度不變。而我們希望實現(xiàn)的例子中,小球的彈動會越來越慢,直到停止下來。在實際生活中,小球的彈動勢能大多是由于摩擦力的存在而轉(zhuǎn)化成內(nèi)能,最后使小球停下。所以,在這里,我們也模擬摩擦力,創(chuàng)建摩擦力系數(shù)friction,取值范圍為0~1。

var friction = 0.95;

然后把vx * friction,得到當(dāng)前的速度vx。

vx * = friction;

最終效果如下:

See the Pen <a _>GpNmRR</a> by dengzhirong (<a _>@dengzhirong</a>) on <a _>CodePen</a>.

【備注:請按F5刷新,或者點擊“Result”面板上懸浮的"Return"按鈕后查看效果】

二. 二維坐標(biāo)上的彈動

上面一個例子是讓小球在x軸上運動。如果我們想讓小球同時在x軸和y軸上運動,就需要引入二維坐標(biāo)上的彈動。事實上很簡單,只需要把目標(biāo)點、速度和加速度擴展到二維坐標(biāo)系上即可。

代碼與上面例子雷同不再重復(fù),直接上效果:

See the Pen <a _>ojYWgm</a> by dengzhirong (<a _>@dengzhirong</a>) on <a _>CodePen</a>.

【備注:請按F5刷新,或者點擊“Result”面板上懸浮的"Return"按鈕后查看效果】

與前一個例子唯一不同的是增加了一條y軸。但是現(xiàn)在小球看起來仍然像是一維運動,雖然小球同時在x軸和y軸上運動,但它仍然是一條直線。原因是它的初速度為0,也僅受一個把它拉向目標(biāo)點的外力,所以它沿著直線運動。為了動畫更豐富一點,可以嘗試修改vx、vy或者不同x、y軸的friction值。自己嘗試一下吧。

三. 目標(biāo)點移動的彈動

目標(biāo)點移動,我們很容易就想到把鼠標(biāo)當(dāng)成目標(biāo)點。在上一篇介紹緩動動畫時,有一個小球跟隨鼠標(biāo)的緩動動畫。讓小球跟隨鼠標(biāo)彈動同樣很簡單,只要把targetX和targetY替換為當(dāng)前坐標(biāo)即可。效果很炫酷,但是代碼基本沒變。只要在前面的例子中改動如下兩行:

var dx = targetX - ball.x;
var dy = targetY - ball.y;

修改為:

var dx = mouse.x - ball.x;
var dy = mouse.y - ball.y;

當(dāng)然,我們還需要寫一個獲得當(dāng)前鼠標(biāo)位置的函數(shù),可以參考我寫的博文《JavaScript動畫詳解(一) —— 循環(huán)與事件監(jiān)聽》

完整代碼如下:

HTML代碼:

<canvas id="canvas" width="400" height="400"></canvas>

JavaScript代碼:

// requestAnimationFrame的兼容性寫法
window.requestAnimFrame = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            window.oRequestAnimationFrame      ||
            window.msRequestAnimationFrame     ||
            function( callback ){
                window.setTimeout(callback, 1000 / 60);
            };
})();

// cancelAnimationFrame的兼容性寫法
window.cancelAnimationFrame = (function () {
    return window.cancelAnimationFrame ||
            window.webkitCancelAnimationFrame ||
            window.mozCancelAnimationFrame ||
            window.oCancelAnimationFrame ||
            function (timer) {
                window.clearTimeout(timer);
            };
})();

// 獲得當(dāng)前鼠標(biāo)位置
function getMouse(ev) {
    var mouse = {
        x: 0,
        y: 0
    };
    var event = ev || window.event;
    if(event.pageX || event.pageY) {
        x = event.x;
        y = event.y;
    }else {
        var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        x = event.clientX + scrollLeft;
        y = event.clientY + scrollTop;
    }
    mouse.x = x;
    mouse.y = y;

    return mouse;
}

// 創(chuàng)建畫球函數(shù)
function Ball() {
    this.x = 0;
    this.y = 0;
    this.radius = 10;
    this.fillStyle = "#f85455";
    this.draw = function(cxt) {
        cxt.fillStyle = this.fillStyle;
        cxt.beginPath();
        cxt.arc(this.x, this.y, this.radius,  0, 2 * Math.PI, true);
        cxt.closePath();
        cxt.fill();
    }
}

var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        ball = new Ball(),
        spring = 0.05,
        vx = 0,
        vy = 0,
        targetX = 0,
        targetY = 0,
        friction = 0.95;
ball.x = 20;
ball.y = 20;
var mouse = {x: 0, y: 0};

canvas.addEventListener("mousemove", function(ev) {
    mouse = getMouse(ev);
    targetX = mouse.x;
    targetY = mouse.y;
    console.log(targetX + " , " + targetY);
}, false);
// 緩動動畫函數(shù)
var animRequest = null;
(function drawFrame() {
    animRequest = window.requestAnimationFrame(drawFrame, canvas);
    context.clearRect(0, 0, canvas.width, canvas.height);
    // 小球當(dāng)前位置與目標(biāo)點的距離
    var dx = targetX - ball.x;
    var dy = targetY - ball.y;
    // 小球的加速度
    var ax = dx * spring;
    var ay = dy * spring;
    // 小球的速度
    vx += ax;
    vy += ay;
    vx *= friction;
    vy *= friction;
    // 計算出小球當(dāng)前的位置
    ball.x += vx;
    ball.y += vy;
    ball.draw(context);
})();

效果如下:

See the Pen <a _>LpbyGq</a> by dengzhirong (<a _>@dengzhirong</a>) on <a _>CodePen</a>.

【備注:把鼠標(biāo)移上去試試~】

好吧,上面這個例子不夠帶勁兒,希望使小球看起來像是栓在橡皮筋上,此時只要在上面的基礎(chǔ)上再小球圓心與當(dāng)前鼠標(biāo)位置畫線即可。

context.beginPath();
context.strokeStyle = "#71A4AD";
context.moveTo(ball.x, ball.y);
context.lineTo(mouse.x, mouse.y);
context.stroke();

效果如下:

See the Pen <a _>NGbjRd</a> by dengzhirong (<a _>@dengzhirong</a>) on <a _>CodePen</a>.

四. 總結(jié)

彈動和緩動非常類似,都是使用循環(huán)函數(shù)逐幀繪制從當(dāng)前位置到目標(biāo)位置的運動效果。不同的是緩動是指速度與距離成比例,而彈動是加速度與距離成比例關(guān)系。但是要模擬出更加真實的彈動,可能需要加入類似摩擦力系數(shù)的因子,把速度逐漸降下,直到停止運動。

相關(guān)文章:

1 . 《JavaScript動畫詳解(二) —— 緩動動畫》

2 . 《JavaScript動畫詳解(一) —— 循環(huán)與事件監(jiān)聽》

標(biāo)簽: 代碼

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇: java獲取jdk、系統(tǒng)、服務(wù)器等信息

下一篇:redis Java工具類