繁体   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