如何绘制用三次贝塞尔曲线绘制的椭圆的部分?

时间:2013-04-09 12:13:13

标签: javascript canvas bezier ellipse

我正在使用此函数(How to draw an oval in html5 canvas?)在HTML5 Canvas中绘制一个椭圆:

function drawEllipse(ctx, x, y, w, h) {
  var kappa = .5522848,
      ox = (w / 2) * kappa, // control point offset horizontal
      oy = (h / 2) * kappa, // control point offset vertical
      xe = x + w,           // x-end
      ye = y + h,           // y-end
      xm = x + w / 2,       // x-middle
      ym = y + h / 2;       // y-middle

  ctx.beginPath();
  ctx.moveTo(x, ym);
  ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  ctx.closePath();
  ctx.stroke();
}

然后,我将获取所有这些值并将其发送到我的Android应用。在那里,我使用Path类的cubicTo方法绘制相同的椭圆。为此,我只使用上面函数的相同参数,它就像一个魅力。

但是现在,我必须只绘制这个椭圆的一部分,而我在谷歌上找不到任何可以帮助我解决问题的方法。我想做的是,拥有第一个椭圆:

enter image description here

我希望能够绘制这些图像:

enter image description here

enter image description here

enter image description here

我该怎么办?

4 个答案:

答案 0 :(得分:1)

看看http://pomax.github.io/bezierinfo/#circles_cubic - 它讨论了圆弧的这个问题(控制点值以圆弧角度表示在截面的底部),但这些和椭圆之间的唯一区别是旋转+缩放其中一个维度。如果你理解圆形近似,你也可以得到椭圆近似。

答案 1 :(得分:0)

除了所有数学内容之外,你可以简单地使用剪辑:

canvas.save();
canvas.clipRect(mYourTargetRect);
// draw your arc/circle/object/oval/whatever here
canvas.restore();

答案 2 :(得分:0)

我有一个最简单的方法。我只是在我的Web应用程序中使用Bezier cuvers绘制椭圆。然后,我得到椭圆的centerX,centerY,宽度和高度,并将它们传递给我的android应用程序。

在我的Android应用中,我可以使用drawOval方法绘制在Web中绘制的椭圆。有了这个,我可以使用drawArcs方法绘制椭圆的弧,它接收一个Oval作为参数。

答案 3 :(得分:0)

Chrome支持CanvasRenderingContext2D.prototype.ellipse方法绘制椭圆或椭圆弧。但是其他浏览器不支持椭圆方法。

您可以使用canvas-5-polyfill来提供椭圆方法。

或者只是写一些js代码:

if (CanvasRenderingContext2D.prototype.ellipse == undefined) {
  CanvasRenderingContext2D.prototype.ellipse = function(x, y, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise) {
    this.save();
    this.translate(x, y);
    this.rotate(rotation);
    this.scale(radiusX, radiusY);
    this.arc(0, 0, 1, startAngle, endAngle, antiClockwise);
    this.restore();
  }
}