n次贝塞尔曲线

 n次贝塞尔曲线的递归公式:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.translate(10, 10); // 重新映射画布上的 (0,0) 位置,避免溢出

function drawCircle(x, y, color, r = 6) {
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.arc(x, y, r, 0, 2 * Math.PI);
  ctx.fill();
}

function drawPath(path) {
  ctx.beginPath();
  path.forEach((p, i) => {
    if (i) {
      ctx.lineTo(p.x, p.y);
    } else {
      ctx.moveTo(p.x, p.y);
    }
  });
  ctx.stroke();
}

function bezier(pointList, t) {
  if (pointList.length === 1) {
    return pointList[0];
  } else {
    // B(t)=(1-t)Bp0p1…pn-1(t) + tBp1p2…pn(t)
    var p1 = bezier(pointList.slice(0, -1), t);
    var p2 = bezier(pointList.slice(1), t);
    var p = {
      x: (1 - t) * p1.x + t * p2.x,
      y: (1 - t) * p1.y + t * p2.y,
    };
    return p;
  }
}

var startPoint = { x: 0, y: 0 };
var endPoint = { x: 900, y: 0 };
var pointList = [
  startPoint,
  // 中间为控制点
  { x: 300, y: 0 },
  { x: 400, y: 100 },
  { x: 600, y: 200 },
  { x: 700, y: 0 },
  endPoint,
];

// 绘制曲线
var path = [];
for (var i = 0; i <= 100; i++) {
  path.push(bezier(pointList, i / 100));
}
drawPath(path);

// 红色起始结束点
[startPoint, endPoint].forEach((p) => {
  drawCircle(p.x, p.y, "red");
});

// 蓝色控制点
pointList.slice(1, -1).forEach((p) => {
  drawCircle(p.x, p.y, "blue");
});

最终效果 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值