Javascript 计算画布中的同心圆弧

Javascript 计算画布中的同心圆弧,javascript,canvas,bezier,quadratic,Javascript,Canvas,Bezier,Quadratic,我试图从给定的圆弧(二次贝塞尔曲线)计算出2个同心圆弧(三次贝塞尔曲线)。我想我可以计算出1/3和2/3的立方的控制点,但它并不完全匹配 var u = 1 / 3; // fraction of curve where Px1 and Py1 are var v = 2 / 3; // fraction of curve where Px2 and Py2 are //Calculate control points (Cx1, Cy1, Cx2, Cy2) var a =

我试图从给定的圆弧(二次贝塞尔曲线)计算出2个同心圆弧(三次贝塞尔曲线)。我想我可以计算出1/3和2/3的立方的控制点,但它并不完全匹配

  var u = 1 / 3; // fraction of curve where Px1 and Py1 are 
  var v = 2 / 3; // fraction of curve where Px2 and Py2 are 
  //Calculate control points (Cx1, Cy1, Cx2, Cy2)
  var a = 3 * (1 - u) * (1 - u) * u;
  var b = 3 * (1 - u) * u * u;
  var c = 3 * (1 - v) * (1 - v) * v;
  var d = 3 * (1 - v) * v * v;
  var det = a * d - b * c;
  var Qx1 = Px1 - ((1 - u) * (1 - u) * (1 - u) * Px0 + u * u * u * Px3);
  var Qy1 = Py1 - ((1 - u) * (1 - u) * (1 - u) * Py0 + u * u * u * Py3);
  var Qx2 = Px2 - ((1 - v) * (1 - v) * (1 - v) * Px0 + v * v * v * Px3);
  var Qy2 = Py2 - ((1 - v) * (1 - v) * (1 - v) * Py0 + v * v * v * Py3);
  var Cx1 = (d * Qx1 - b * Qx2) / det;
  var Cy1 = (d * Qy1 - b * Qy2) / det;
  var Cx2 = ((-c) * Qx1 + a * Qx2) / det;
  var Cy2 = ((-c) * Qy1 + a * Qy2) / det;
  ctx.beginPath();
  ctx.moveTo(Px0, Py0);
  ctx.bezierCurveTo(Cx1, Cy1, Cx2, Cy2, Px3, Py3);
  ctx.strokeStyle = "#0000FF";
  ctx.stroke();
控制点是否也取决于弧的半径或完全不同的东西?立方贝塞尔曲线是绘制同心圆弧的好选择吗?二次贝塞尔绝对不起作用,三次贝塞尔绝对让我更接近我所需要的

以下是链接:


使用“位置”滑块移动椭圆

目前的问题是关于需求有点不清楚。在任何情况下,这里都是一种不需要太多计算的方法,但它利用绘图操作来可视化代码笔中显示的内容

主要步骤是:

  • 在屏幕外画布上:
  • 定义线厚度,并将半径设置为绿色区域
  • 定义直线的圆顶
  • 用纯色绘制贝塞尔线
  • 使用相对于蓝线厚度的各种偏移将结果绘制到主画布中
  • 清除中心,您将获得蓝色轮廓
  • 实现手动Bezier,以便可以在该形状内的任意点绘制绿色圆弧/椭圆
半径/直径可以扩展。如果您需要可变半径,您可以使用贝塞尔公式来绘制一系列相互重叠的蓝色圆弧

概念证明 这将逐步显示该过程

第一步 在屏幕外的画布上(显示在屏幕上用于演示,我们将在下一步切换):

var c=document.querySelector(“画布”),
ctx=c.getContext(“2d”),
直径=90;//图形直径
ctx.strokeStyle=“蓝色”//颜色
ctx.lineWidth=直径;//线宽=直径
ctx.lineCap=“圆形”//圆帽
//绘制贝塞尔曲线(二次曲线,一个控制点)
ctx.moveTo(直径,直径);
ctx.方形曲线(300,230,c.宽度-直径,直径);
ctx.stroke()

您使用了两组不同的基本上不可调和的术语:“三次和二次贝塞尔曲线”与曲线路径相关,“圆弧和半径”与[半]圆形路径相关。这些类型的曲线不能表示圆形路径,反之亦然。请说明您正在尝试做什么。:-)为什么不直接用圆弧()来计算起点/终点角度呢?@K3N,我就是这么想的。你明白问题的意思吗?我不清楚-/@markE我不完全确定,我假设他希望蓝色和绿色的中心对齐(同心),蓝色覆盖/勾勒/嵌入(?)绿色椭圆,但我不知道是否需要Bezier。我确实认为圆弧(或者新的椭圆)更容易处理,也更精确。我用“圆弧”来描述曲线。很抱歉它不是一个实际的弧。二次贝塞尔曲线是给定的,这意味着我不能改变它。我试着用上面的曲线和下面的曲线来“匹配”它。显然,我不能在上面和下面画另一条二次曲线,因为上面或下面的曲线比给定的中间曲线小或大。哇!谢谢你的详细回答!我真的很喜欢它,可能会转向这个想法。如果轴相等,这将完全解决我的问题。在我的示例中,x轴和y轴略有不同,这一点并不完全清楚。在现实世界中,它们之间的差异甚至可以达到2倍。我可能会认为这个答案是正确的,因为它是解决问题的一个有用的方法,并且会帮助大多数有类似问题的人。我想让你看看我修改过的例子,看看我对不同轴的意思:我可以强制我的轴相等,然后我就可以充分利用你的答案来解决我的问题。@dreed75对其中一个轴的画布应用一个简单的比例,可能就不受影响了。还可以选择使用内置或自定义的ellipse(它是画布标准的一部分,但并非所有浏览器都支持它)。只需按照精细分辨率t值渲染轮廓即可。@dreed75在底部添加了一个示例(折叠),但更好的方法是绘制一个实际的椭圆,因为这样可以保持内弧正确)明白了。谢谢我也喜欢你的getQuadraticPoint()。我试图找到一种在画布上实现这一点的方法。这是我对二次贝塞尔曲线使用svg的唯一原因,因为它有一个内置函数,用于以一定的百分比获取点。