簡體   English   中英

在畫布中繪制動畫曲線

[英]Drawing animated curves in canvas

幾天前我來到stackoverflow詢問如何在畫布上緩慢繪制箭頭。 沒有人能夠給我正確的答案......所以我希望這對某人有所幫助。

基本上,我想在地圖上動畫從一個國家到另一個國家的入侵過程。 要做到這一點,我應該使用畫布並繪制一個從 A 國移動到 B 國的箭頭,但不是一個固定的箭頭......一個逐漸增長的箭頭。

下面的代碼繪制了一個箭頭,但不是漸進式的。 因此,我需要像具有 5 秒過渡的 CSS 動畫一樣繪制這條曲線。

 function drawCurve (ctx, x0, y0, x1, y1, x2, y2){ ctx.beginPath(); ctx.moveTo( x0, y0 ); ctx.quadraticCurveTo( x1, y1, x2, y2 ); ctx.stroke(); ctx.closePath(); } var docCanvas = document.getElementById('canvas'); var ctx = docCanvas.getContext('2d'); drawCurve(ctx, 0, 100, 150, -50, 300, 100);
 <canvas id="canvas" width="480" height="320"></canvas>

經過一番挖掘,我找到了這個解決方案,它提供了我想要的一切。

基本上drawBezierSplit()允許您繪制二次貝塞爾曲線的一部分。

所有功勞都歸功於帕特里克·加爾布雷思

 /** * Animates bezier-curve * * @param ctx The canvas context to draw to * @param x0 The x-coord of the start point * @param y0 The y-coord of the start point * @param x1 The x-coord of the control point * @param y1 The y-coord of the control point * @param x2 The x-coord of the end point * @param y2 The y-coord of the end point * @param duration The duration in milliseconds */ function animatePathDrawing(ctx, x0, y0, x1, y1, x2, y2, duration) { var start = null; var step = function animatePathDrawingStep(timestamp) { if (start === null) start = timestamp; var delta = timestamp - start, progress = Math.min(delta / duration, 1); // Clear canvas ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // Draw curve drawBezierSplit(ctx, x0, y0, x1, y1, x2, y2, 0, progress); if (progress < 1) { window.requestAnimationFrame(step); } }; window.requestAnimationFrame(step); } /** * Draws a splitted bezier-curve * * @param ctx The canvas context to draw to * @param x0 The x-coord of the start point * @param y0 The y-coord of the start point * @param x1 The x-coord of the control point * @param y1 The y-coord of the control point * @param x2 The x-coord of the end point * @param y2 The y-coord of the end point * @param t0 The start ratio of the splitted bezier from 0.0 to 1.0 * @param t1 The start ratio of the splitted bezier from 0.0 to 1.0 */ function drawBezierSplit(ctx, x0, y0, x1, y1, x2, y2, t0, t1) { ctx.beginPath(); if( 0.0 == t0 && t1 == 1.0 ) { ctx.moveTo( x0, y0 ); ctx.quadraticCurveTo( x1, y1, x2, y2 ); } else if( t0 != t1 ) { var t00 = t0 * t0, t01 = 1.0 - t0, t02 = t01 * t01, t03 = 2.0 * t0 * t01; var nx0 = t02 * x0 + t03 * x1 + t00 * x2, ny0 = t02 * y0 + t03 * y1 + t00 * y2; t00 = t1 * t1; t01 = 1.0 - t1; t02 = t01 * t01; t03 = 2.0 * t1 * t01; var nx2 = t02 * x0 + t03 * x1 + t00 * x2, ny2 = t02 * y0 + t03 * y1 + t00 * y2; var nx1 = lerp ( lerp ( x0 , x1 , t0 ) , lerp ( x1 , x2 , t0 ) , t1 ), ny1 = lerp ( lerp ( y0 , y1 , t0 ) , lerp ( y1 , y2 , t0 ) , t1 ); ctx.moveTo( nx0, ny0 ); ctx.quadraticCurveTo( nx1, ny1, nx2, ny2 ); } ctx.stroke(); ctx.closePath(); } /** * Linearly interpolates between two numbers */ function lerp(v0, v1, t) { return ( 1.0 - t ) * v0 + t * v1; } var docCanvas = document.getElementById('canvas'); var ctx = docCanvas.getContext('2d'); animatePathDrawing(ctx, 0, 100, 150, -50, 300, 100, 5000);
 <canvas id="canvas" width="480" height="320"></canvas>

編輯

如果你需要一個 polyfill,你可以使用以下代碼:

(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

鏈接http : //www.pjgalbraith.com/drawing-animated-curves-javascript/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM