如何使用本地JavaScript代码绘制平滑曲线,而不使用ctx.bezierCurveTo?

5

我需要用原生JavaScript绘制和获取每个步骤的贝塞尔曲线坐标,而不使用ctx.bezierCurveTo方法。

我尝试了下面的方法,但它并没有正常工作。这里附上我的代码和输出曲线。

const accuracy = 0.01; let temp = 4;

 function draw(event) {
      if (!isDrawing) { return; }
      points.push({ x: event.clientX, y: event.clientY });    
      let count = 0;
      if(points.length === temp) {
      ctx.beginPath();
      ctx.moveTo(points[points.length - 4].x, points[points.length - 4].y)
      for (let i = 0; i <= 1; i += accuracy) {
        const p = bezier2(i, points[points.length - 4], points[points.length - 3] , 
        points[points.length - 2], points[points.length-1]);
        ctx.lineTo(p.x,p.y)
      }
     temp += 3
     ctx.stroke();
     ctx.closePath();
    }
  }

function bezier2(t, p0, p1, p2, p3){

    const aX = p0.x ;
    const bX = 3.0 * p1.x;
    const cX = 3.0 * p2.x;
    const dX = p3.x ;

    const aY = p0.y;
    const bY = 3.0 * p1.y ;    
    const cY = 3.0 * p2.y;    
    const dY = p3.y;

    const x = (p0.x * Math.pow((1 - t), 3)) + (3.0 * p1.x * Math.pow((1 - t), 2) * t) + (3.0 * p2.x * Math.pow((t), 2) * (1 - t)) + (p3.x * Math.pow(t, 3));
    const y = (p0.y * Math.pow((1 - t), 3)) + (3.0 * p1.y * Math.pow((1 - t), 2) * t) + (3.0 * p2.y * Math.pow((t), 2) * (1 - t)) + (p3.y * Math.pow(t, 3));
    return {x: x, y: y};
          
  }


不使用ctx.bezierCurveTo方法,我们可以知道原因吗? - blex
1
这回答解决了你的问题吗?如何使用JavaScript HTML5画布通过N个点绘制平滑曲线? - Anurag Srivastava
1
@blex 我想将这个用于使用纹理作为画笔的刷子工具。 - Randima Lahiru
@AnuragSrivastava 不行。我试过了,但输出结果一样。 - Randima Lahiru
1个回答

3
我发现了一些解决方法,并且它为我提供了预期的输出。我使用了一个控制点贝塞尔曲线算法进行测试。这是我的示例代码。
function draw(event) {
    if (!isDrawing) { return; }
    points.push({ x: event.clientX, y: event.clientY });
    let count = 0; pointArray = [];
    if (points.length > 1) {
      let begin; let control;
      const end = midPointBtw(points[points.length - 2] , points[points.length - 1] );
      if (points.length === 2) {
        begin = points[0];
        const middle  = midPointBtw(points[0] , points[1]);
        control =  midPointBtw(middle , points[1]);
      }  else {
        begin = midPointBtw(points[points.length - 3] , points[points.length - 2]);
        control =  points[points.length - 2];
      }
      for (let i = 0; i < 1; i += accuracy) {
        const p = bezier3(i,  begin , control, end);
        pointArray.push(p);
        count++;
      }
      if (count === 100) {
        ctx.beginPath();
        ctx.moveTo(begin.x, begin.y);
        for (let i = 0; i < pointArray.length - 1; i += 1) {
          ctx.lineTo(pointArray[i].x, pointArray[i].y);
        }
        ctx.stroke();
        ctx.closePath();
      }

    }
 }

function midPointBtw(p1, p2) {
    return {
      x: p1.x + (p2.x - p1.x) / 2,
      y: p1.y + (p2.y - p1.y) / 2
    };
  }
function bezier3(t, begin, control, end) {

    const cX = (end.x);
    const bX = 2 * (control.x);
    const aX = begin.x ;

    const cY = (end.y);
    const bY = 2 * (control.y) ;
    const aY = begin.y;

    const x = (aX * Math.pow((1 - t), 2)) + (bX * (1 - t) * t) + (cX * Math.pow(t, 2)) ;
    const y = (aY * Math.pow((1 - t), 2)) + (bY * (1 - t) * t) + (cY * Math.pow(t, 2));
    return {x: x, y: y};
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接