gpt4 book ai didi

javascript - startAngle 在 HTML5 canvas 椭圆中意味着什么?

转载 作者:行者123 更新时间:2023-11-27 23:01:27 27 4
gpt4 key购买 nike

绘制时a canvas ellipse ,我惊讶地发现“startAngle”实际上似乎并没有指定与椭圆原点的 Angular 。正如下面的代码片段所示,两个具有相同“startAngle”但不同半径值的椭圆在截然不同的位置开始它们的圆弧。

从原点测量,高椭圆似乎以 50 或 60 度的 Angular 开始,而宽椭圆的 Angular 看起来像 15 或 20 度。

那么“startAngle”到底是什么?

https://developer.mozilla.org/en-US/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>

最佳答案

这就像您首先开始绘制圆弧,然后拉伸(stretch)和挤压它以匹配椭圆弧的尺寸。

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 的预期工作的
公式来自这篇博文: 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>

编辑2

你需要一个修正阶段,因为atan of tan只在区间内是正确的
[-Math.PI/2;Math.PI/2]。超出此时间间隔,该值会定期移动 k * Math.PI。 See this QA关于数学

// "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" />

关于javascript - startAngle 在 HTML5 canvas 椭圆中意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52149077/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com