gpt4 book ai didi

javascript - Javascript 中的太阳弧路径

转载 作者:行者123 更新时间:2023-11-30 10:03:03 25 4
gpt4 key购买 nike

所以我试图在弧形路径(首选圆形路径)中绘制太阳以模拟日出/日落,但我遇到了问题。

Canvas 宽度 = 800; Canvas 高度 = 100;

if(getTime() - sunTime > 100){
angle++;
sunTime = getTime();
}

sun.x = 400 * Math.sin(angle * (Math.PI/180));//Convert to degrees
sun.y = 100 * Math.sin(angle * (Math.PI/180));

这是我试图使其正确弧形的代码,它似乎给了我错误的弧形类型。

HTML canvas 的奇怪之处在于 (0,0) 位于屏幕的左上角,所以有点奇怪。我试着找到一个像样的网站,解释了如何找到它,但我发现的一切似乎都没有按照我想要的方式工作。

我根据我对数学的了解进行了这种转换……如果这种方法不合适,请告诉我!

最佳答案

错误是由于正弦同时用于 x 和 y。由于 Canvas 的方向为 0° 向右,因此它应该是:

sun.x = 400 * Math.cos(angle * (Math.PI/180));  // cos for x
sun.y = 100 * Math.sin(angle * (Math.PI/180));

请注意,此处 400,100 是半径,因此要定义中心,您还需要一个中心点:

sun.x = centerX + radiusX * Math.cos(angle * (Math.PI/180));
sun.y = centerY + radiusY * Math.sin(angle * (Math.PI/180));

只需考虑几点 -

什么被解释为真实的日出/日落在很大程度上取决于您在世界上的位置(相对于纬度或 φ)。

例如,如果你住在厄瓜多尔,或者 φ = 0,太阳基本上会直线上升和直线下降。如果你在北极圈(或南极圈)上方,你将有一个非常陡峭的 Angular 。此外,在这些纬度,太阳永远不会在夏令时 (midnight sun) 落下,也不会在冬令时 (polar night) 升起。

但是,如果您只是在近似之后,您可以定义 Angular 为 0 的基线(日出)和 Angular 为 180 的日落,从左到右(或从东到西,如果您在南部)您可能更喜欢相反的半球)。

Canvas 的坐标系将 0° 指向右侧,90° 将指向下方,因此我们将知道 180 - 360° 将是一个圆弧,顶点(最高点)在 270°。

这将使用虚拟太阳和任意步骤绘制这样的弧:

snap

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

var angle = Math.PI, // we'll use radians here, 0 to Math.PI (=180)
centerX = ctx.canvas.width * 0.5, // center of arc
bottomY = ctx.canvas.height,
radiusX = ctx.canvas.width * 0.8, // radius, 80% of width in this example
radiusY = ctx.canvas.height * 0.9; // radius, 90% of height in this example

// goes 180 to 360°, in radians PI to 2xPI
for(; angle < Math.PI*2; angle += 0.1) {
var x = centerX + radiusX * Math.cos(angle);
var y = bottomY + radiusY * Math.sin(angle);
ctx.fillRect(x - 2, y - 2, 4, 4); // dummy sun for now
}
<canvas></canvas>

下一步是规范化输入和输出值,这样我们就可以将规范化的时间值插入到太阳渲染器中。

要标准化时间,您可以定义日出和日落时间。然后在该范围内划分当前时间。如果该值在 [0, 1] 范围内,我们就有太阳并且可以将该值插入“渲染器”。

通用公式(不考虑极端情况,如 f.ex.( Ant )北极圈):

var normTime = (currentTime - sunriseTime) / (sunsetTime - sunrisetime);

渲染器将采用归一化值并使用简单插值将其应用于 [180, 360] 范围:

var currentAngle = Math.PI + (Math.PI * 2 - Math.PI) * normTime;

或简化为:

var currentAngle = Math.PI + Math.PI * normTime;

您甚至可以将归一化时间值插入到渐变值中,也可以绘制代表天空颜色的背景。

为简单起见,让我们模拟一个运行速度非常快的 24 小时时钟:

var ctx = document.querySelector("canvas").getContext("2d"),
gr = ctx.createLinearGradient(0, 0, 0, ctx.canvas.height),
sky = new Image();

sky.onload = go;
sky.src = "http://i.stack.imgur.com/qhQhQ.jpg";

function go() {

// some style setup
ctx.font = "bold 16px sans-serif";
gr.addColorStop(0, "#ffc");
gr.addColorStop(0.75, "gold");
gr.addColorStop(1, "orange");

ctx.shadowColor = "#ffa";

var centerX = ctx.canvas.width * 0.5, // center of arc
bottomY = ctx.canvas.height + 16, // let center be a bit below horizon
radiusX = ctx.canvas.width * 0.52, // radius, 80% of width in this example
radiusY = ctx.canvas.height * 0.8; // radius, 90% of height in this example

// define sunrise and sunset times (in 24-hour clock, can be fractional)
var time = 7, sunrise = 7, sunset = 19;

(function loop() {
var normTime = getTime(); // get normalized time
var angle = getAngle(normTime); // get angle in radians
var x = centerX + radiusX * Math.cos(angle); // calcuate point
var y = bottomY + radiusY * Math.sin(angle);
drawSky(normTime); // draw sky gradient
drawSun(x, y); // draw sun at point
drawTime(); // render time
requestAnimationFrame(loop) // loop
})();

function getTime() {
// produces a normalized pseduo-time
time += 0.033;
if (time > 23) time = 0;
return (time - sunrise) / (sunset - sunrise);
}

function getAngle(normTime) {
return Math.PI + Math.PI * normTime
}

function drawSun(x, y) {
ctx.beginPath();
ctx.moveTo(x + 16, y);
ctx.arc(x, y, 16, 0, 6.28);
ctx.fillStyle = gr;
ctx.shadowBlur = 20;
ctx.fill();
}

function drawTime() {
ctx.fillStyle = "#fff";
ctx.shadowBlur = 0;
ctx.fillText("Time: " + time.toFixed(1) + "h", 10, 20);
}

function drawSky(t) {
t = Math.max(0, Math.min(1, t));
var iw = sky.width,
w = ctx.canvas.width,
x = 60 + (iw - 120) * t;
ctx.drawImage(sky, x, 0, 1, sky.height, 0, 0, w, ctx.canvas.height);
}
}
canvas {background:#acf}
<canvas width=400 height=180></canvas>

现在剩下的就是根据纬度找到地平线和宽度和高度的半径。天顶 Angular/方位 Angular 也是要考虑的因素,而且太阳路径的中心可能不会位于地平线上,因此必须根据一年中的位置和时间减少或增加要归一化的 Angular 范围。

另见 Yahoo's Weather channel API 提供您所在位置的升起/日落时间。另请查看 NOAA's page 用于正确计算与视点相关的 Angular 等的提示和公式(NASA 也有一些很好的资源)

您还可以在太阳绘图超出 [0, 1] 范围时限制它,具体取决于最终渲染的方式(在上面的演示中 Canvas 将为我们剪裁)。

关于javascript - Javascript 中的太阳弧路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30577457/

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