2016-05-27 10 views
0

数日前、私はキャンバスに矢印を描く方法を尋ねる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>

答えて

0

私は私が望んでいたすべてを与え、この溶液に来ました。

基本的にdrawBezierSplit()では、2次ベジェ曲線のセクションを描画できます。

Patrick Galbraith

/** 
 
* 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(); 
 
    
 
\t if(0.0 == t0 && t1 == 1.0) { 
 
\t \t ctx.moveTo(x0, y0); 
 
\t \t ctx.quadraticCurveTo(x1, y1, x2, y2); 
 
\t } 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); 
 
\t } 
 
    
 
    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>

EDIT

そして、あなたはポリフィルが必要な場合、あなたはこのコードを使用することができます:

(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/

関連する問題