startAngle在HTML5画布椭圆中是什么意思? [英] What does startAngle mean in an HTML5 canvas ellipse?

查看:184
本文介绍了startAngle在HTML5画布椭圆中是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

绘制画布时椭圆,我很惊讶地发现 startAngle实际上并没有指定椭圆起点的角度。如下面的代码片段所示,两个具有相同 startAngle但半径值不同的椭圆在非常不同的位置开始其弧。

When drawing a canvas ellipse, I was surprised to discover that 'startAngle' doesn't actually seem to specify the angle from the ellipse's origin. As seen in the code snippet below, two ellipses with the same 'startAngle' but different radius values begin their arcs in very different places.

高椭圆形似乎始于从原点开始测量的角度为50或60度,而宽椭圆形的角度则为15或20度。

The tall ellipse seems to begin on an angle of 50 or 60 degrees, as measured from the origin, while the wide ellipse's angle looks like 15 or 20 degrees.

那么 startAngle到底是什么?

So what is 'startAngle' exactly?

https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/ellipse

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var startAngle = 0.5;
var endAngle = Math.PI * 2;

ctx.beginPath();
ctx.ellipse(70, 150, 50, 140, 0, startAngle, endAngle);
ctx.stroke();

ctx.beginPath();
ctx.ellipse(300, 150, 140, 50, 0, startAngle, endAngle);
ctx.stroke();

<html>
<body>

<canvas id="canvas" width="500" height="300">

</body>
</html>

推荐答案

就像您第一次开始绘图一样

It's like you first start drawing a circular arc and than stretch and squish that to match the dimensions of the elliptical arc.

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var startAngle = Math.PI * 2 / 360 * 45;
var endAngle = Math.PI * 2 / 360 * 315;

ctx.fillStyle = "rgba(255, 255, 255, 0.125)";

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 50, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 60, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 70, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 80, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 90, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 100, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 110, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 120, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 130, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(70, 150);
ctx.ellipse(70, 150, 50, 140, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 50, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 60, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 70, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 80, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 90, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 100, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 110, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 120, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 130, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

ctx.beginPath();
ctx.moveTo(300, 150);
ctx.ellipse(300, 150, 140, 50, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();

<html>
<body>

<canvas id="canvas" width="500" height="300">

</body>
</html>

这已按照OP的要求运行。
该公式来自此博客文章:
找到椭圆周围的角度

This is working as intended by the OP
The formula comes from this blog post: Finding the angle around an ellipse

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var startAngle = Math.PI * 2 / 360 * 75;
var endAngle = Math.PI * 2 / 360 * 345;


ctx.fillStyle = "rgba(255, 255, 255, 0.125)";

function correctEllipse(ctx, cx, cy, w, h, r, sa, ea) {
  sa = Math.atan(w/h * Math.tan(sa))
  ea = Math.atan(w/h * Math.tan(ea))
  ctx.ellipse(cx, cy, w, h, r, sa, ea);
}


w = 50
h = 50

ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 60
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 70
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 80
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 90
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 100
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 110
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 120
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 130
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 140
ctx.beginPath();
ctx.moveTo(70, 150);
correctEllipse(ctx, 70, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.fill();

h = 50
w = 50
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();


w = 60
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 70
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 80
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 90
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 100
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 110
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 120
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 130
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();
ctx.fill();

w = 140
ctx.beginPath();
ctx.moveTo(300, 150);
correctEllipse(ctx, 300, 150, w, h, 0, startAngle, endAngle);
ctx.lineTo(300, 150);
ctx.stroke();

<html>
<body>

<canvas id="canvas" width="500" height="300">

</body>
</html>

您需要一个更正阶段,因为tan的atan仅在时间间隔内是正确的

[-Math.PI / 2; Math.PI / 2]。超出此间隔后,该值会定期移位k *Math.PI。 在数学上查看此质量检查

You need a correction phase, because atan of tan is only correct in the interval
[-Math.PI/2;Math.PI/2]. Beyond this interval the value is shifted by k * Math.PI periodically. See this QA on Mathematics

// "use strict";

window.requestAnimFrame = (function(callback) {
  return (
    window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function(callback) {
      window.setTimeout(callback, 1000 / 60);
    }
  );
})();

var step = 0;

function animate() {
  requestAnimationFrame(animate);
  step++;

  if (step % 1 === 0) {
    ctx.clearRect(0, 0, 500, 300);
    step = 0;
    startAngle += 1;
    endAngle += 1;

    //   startAngle = ((startAngle + 180) % 360) - 180;
    //   endAngle = ((endAngle + 180) % 360) - 180;

    // endAngle += 1;

    // startAngle = startAngle % 360;
    // endAngle = endAngle % 360

    // if (endAngle < startAngle) {
    //   temp = endAngle
    //   endAngle = startAngle
    //   startAngle = temp
    // }

    // console.log(startAngle, endAngle)

    //startAngle = ((startAngle + 180) % 360) - 180;
    //endAngle = ((endAngle + 180) % 360) - 180;

    h = 50;
    w = 50;
    cx = 70;
    cy = 150;

    deltaW = 1;
    deltaH = 5;
    deltaCx = 3;
    deltaCy = 1;

    for (var i = 0; i < 15; i++) {
      currentW = w + deltaW * i;
      currentH = h + deltaH * i;
      currentCx = cx + deltaCx * i;
      currentCy = cy + deltaCy * i;
      angleEllipse(
        ctx,
        currentCx,
        currentCy,
        currentW,
        currentH,
        0,
        startAngle * Math.PI / 180,
        endAngle * Math.PI / 180
      );
    }

    h = 50;
    w = 50;
    cx = 300;
    cy = 150;

    deltaW = 5;
    deltaH = 1;
    deltaCx = 1;
    deltaCy = 3;
    for (var i = 0; i < 15; i++) {
      currentW = w + deltaW * i;
      currentH = h + deltaH * i;
      currentCx = cx + deltaCx * i;
      currentCy = cy + deltaCy * i;
      angleEllipse(
        ctx,
        currentCx,
        currentCy,
        currentW,
        currentH,
        0,
        startAngle * Math.PI / 180,
        endAngle * Math.PI / 180
      );
    }
  }
}

document.addEventListener("DOMContentLoaded", function() {
  animate();
});

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var startAngle = 75;
var endAngle = 320;

ctx.fillStyle = "rgba(255, 255, 255, 0.125)";

function atantan(angle, w, h) {
  angle = (angle + Math.PI) % (2 * Math.PI) - Math.PI;
  var tempAngle = angle;
  angle = Math.atan(w / h * Math.tan(angle));
  if (tempAngle < -Math.PI / 2) {
    angle -= Math.PI;
  } else if (tempAngle > Math.PI / 2) {
    angle += Math.PI;
  }
  return angle;
}

function correctEllipse(ctx, cx, cy, w, h, r, sa, ea) {
  // sa should stay between negative Math.PI and positive Math.PI
  sa = atantan(sa, w, h);
  ea = atantan(ea, w, h);
  ctx.ellipse(cx, cy, w, h, r, sa, ea);
}

function angleEllipse(ctx, cx, cy, w, h, r, sa, ea) {
  ctx.beginPath();
  ctx.moveTo(cx, cy);
  correctEllipse(ctx, cx, cy, w, h, r, sa, ea);
  // ctx.ellipse(cx, cy, w, h, r, sa, ea);
  ctx.lineTo(cx, cy);
  ctx.stroke();
  ctx.fill();
}

<canvas id="canvas" width="500" height="300" />

这篇关于startAngle在HTML5画布椭圆中是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆