簡體   English   中英

在html5畫布中繪制動畫貝塞爾曲線時如何保持平滑線條

[英]How to keep smooth lines when drawing out animated bezier curves in html5 canvas

我終於找到了如何繪制bezier曲線的動畫。 我已經看到其他解決方案使用二次曲線來做到這一點,但我需要4點才能完成我的工作,並且b-spline太難找到隨機圖,而且它只是我想要的方式; 與Bezier Cuves。

我的問題是,如果沒有看到點或線,我找不到好的,快速的速度。 我一定會錯過一些東西。 有人可以指出我的錯誤或更有效的方式在任何時間/速度順利進行嗎? 我需要它穩定並且比下面的例子更快,但是如果我再做的話,差距越來越大......

小提琴代碼: https//jsfiddle.net/qzsy8aL7/

//B(t) = (1 - t)^3P0 + 3t(1 - t)^2 P1 + 3t^2(1 - t)P2 + t^3P3
function animatedBSpline(context, points, t) {
    // Draw curve segment
    context.beginPath();
    context.moveTo(
    Math.pow(1 - t, 3) * points[0].x +
    3 * t * Math.pow(1 - t, 2) * points[1].x +
    3 * Math.pow(t, 2) * (1 - t) * points[2].x +
    Math.pow(t, 3) * points[3].x,

    Math.pow(1 - t, 3) * points[0].y +
    3 * t * Math.pow(1 - t, 2) * points[1].y +
    3 * Math.pow(t, 2) * (1 - t) * points[2].y +
    Math.pow(t, 3) * points[3].y
  );

  // Draw spline segemnts
  context.lineTo(
    Math.pow((1 - t) + 0.001, 3) * points[0].x +
    3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].x +
    3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].x +
    Math.pow(t + 0.001, 3) * points[3].x,

    Math.pow((1 - t) + 0.001, 3) * points[0].y +
    3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].y +
    3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].y +
    Math.pow(t + 0.001, 3) * points[3].y
  );

  //33d4ff
  context.strokeStyle="#35bb23";
  context.lineJoin="round";
  context.lineWidth=2;
  context.fillStyle = "black";
  context.stroke();
  context.fill();

  // Keep going until t = 1
  if (t < 1) requestAnimationFrame(function() {
    animatedBSpline(context, points, t + 0.01);
  });
  else
    context.closePath();
}

如果需要更多信息,請告訴我。 我整天都在這里。

補充一點:如果我只是用這些情節直接繪制它,而不是為它做動畫,它看起來很好,顯然,但只是想指出這一點。 它與我動畫它的方式有關,我只是不知道。

這是帶有綠色貝塞爾曲線動畫的完整更新代碼:

 (function() { var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; $(function() { var canvas = $('#drawings')[0]; var context = canvas.getContext('2d'); var lineLength = 0; var lineLengthMax = 7; var timer; // Define points var points = [[{ x: 600, y: 200 }, { x: 550, y: 100 }, { x: 350, y: 100 }, { x: 300, y: 250 }], [{ x: 350, y: 250 }, { x: 75, y: 225 }, { x: 30, y: 400 }, { x: 120, y: 450 }], [{ x: 200, y: 450 }, { x: 5, y: 380 }, { x: 25, y: 750 }, { x: 175, y: 610 }], [{ x: 200, y: 520 }, { x: 150, y: 560 }, { x: 175, y: 750 }, { x: 325, y: 605 }], [{ x: 400, y: 395 }, { x: 275, y: 450 }, { x: 250, y: 750 }, { x: 565, y: 655 }], [{ x: 515, y: 540 }, { x: 500, y: 695 }, { x: 660, y: 675 }, { x: 675, y: 560 }], [{ x: 600, y: 400 }, { x: 790, y: 315 }, { x: 1005, y: 500 }, { x: 675, y: 585 }], [{ x: 500, y: 250 }, { x: 700, y: 100 }, { x: 775, y: 350 }, { x: 700, y: 380 }]]; //33d4ff context.strokeStyle="#35bb23"; context.lineJoin="round"; context.lineWidth=2; doLineDraw(); //animatedBSpline(context, points, 0); function doLineDraw() { if (lineLength <= lineLengthMax) { clearTimeout(timer); // Kick things off at t = 0 context.beginPath(); animatedBSpline(context, points[lineLength], 0); //animatedBSpline(context, eval('points'+(lineLength)), 0); lineLength++; if (lineLength <= lineLengthMax) timer = setTimeout(doLineDraw, 2000); } } //B(t) = (1 - t)^3P0 + 3t(1 - t)^2 P1 + 3t^2(1 - t)P2 + t^3P3 function animatedBSpline(context, points, t) { // Draw curve segment if (t == 0) context.moveTo( Math.pow(1 - t, 3) * points[0].x + 3 * t * Math.pow(1 - t, 2) * points[1].x + 3 * Math.pow(t, 2) * (1 - t) * points[2].x + Math.pow(t, 3) * points[3].x, Math.pow(1 - t, 3) * points[0].y + 3 * t * Math.pow(1 - t, 2) * points[1].y + 3 * Math.pow(t, 2) * (1 - t) * points[2].y + Math.pow(t, 3) * points[3].y ); // Draw spline segemnts context.lineTo( Math.pow((1 - t) + 0.001, 3) * points[0].x + 3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].x + 3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].x + Math.pow(t + 0.001, 3) * points[3].x, Math.pow((1 - t) + 0.001, 3) * points[0].y + 3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].y + 3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].y + Math.pow(t + 0.001, 3) * points[3].y ); //context.fillStyle = "black"; context.stroke(); //context.fill(); // Keep going until t = 1 if (t < 1) requestAnimationFrame(function() { animatedBSpline(context, points, t + 0.01); }); } }); }()); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section> <article> <canvas id="drawings" width="1000" height="1000" /> </article> </section> 

一些關鍵點,其中一些與問題相關。

  • 避免使用eval來引用具有后固定數字的變量名稱。 只需使用數組即可。
  • 您繪制點而不是線的原因是因為您在每個新頂點之前調用了context.beginPath()context.moveTo() ,這導致context.stroke()context.fill() “忘記”前面的指令。

我將context.beginPath()移動到animatedBSpline() context.beginPath()之外,並指定context.moveTo()在該函數中的t==0運行,這樣就沒有脫節點。 我希望有所幫助。

暫無
暫無

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

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