Javascript 中的太阳弧路径

Jus*_*tin 1 javascript math canvas

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

画布宽度 = 800;画布高度 = 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));
Run Code Online (Sandbox Code Playgroud)

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

关于 HTML 画布的奇怪之处在于 (0,0) 位于屏幕的左上角,所以事情有点奇怪。我试图找到一个像样的网站,解释了如何找到它,但我找到的所有东西似乎都不像我想要的那样工作。

我根据我对数学的了解做了这个转换......如果这种方法不可行,请告诉我!

小智 8

错误是由于 x 和 y 都使用了正弦。由于画布的方向为 0° 航向,因此它应该是:

sun.x = 400 * Math.cos(angle * (Math.PI/180));  // cos for x
sun.y = 100 * Math.sin(angle * (Math.PI/180));
Run Code Online (Sandbox Code Playgroud)

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

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

只需考虑几点 -

什么被解释为现实的日出/日落将在很大程度上取决于您在世界上的位置(与纬度有关,或?)。

例如,如果您住在厄瓜多尔,或者?= 0,太阳基本上会直上直下。如果您位于北极圈(或就此而言是南极圈)上方,您的角度将非常陡峭。此外,在这些纬度地区,太阳永远不会在夏季(午夜太阳落下,也永远不会在冬季(极夜)升起。

但是,如果您只是在近似之后,您可以在角度 0 处定义基线(日出),在角度 180 处定义日落,从左到右(或从东到西,如果您在南半球,则为弧形) d 可能更喜欢相反的情况)。

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

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

折断

sun.x = 400 * Math.cos(angle * (Math.PI/180));  // cos for x
sun.y = 100 * Math.sin(angle * (Math.PI/180));
Run Code Online (Sandbox Code Playgroud)
sun.x = centerX + radiusX * Math.cos(angle * (Math.PI/180));
sun.y = centerY + radiusY * Math.sin(angle * (Math.PI/180));
Run Code Online (Sandbox Code Playgroud)

下一步是对输入和输出值进行归一化,这样我们就可以将归一化的值插入太阳渲染器中。

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

通用公式(不考虑极端情况作为 f.ex.(蚂蚁)北极圈):

var normTime = (currentTime - sunriseTime) / (sunsetTime - sunrisetime);
Run Code Online (Sandbox Code Playgroud)

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

var currentAngle = Math.PI + (Math.PI * 2 - Math.PI) * normTime;
Run Code Online (Sandbox Code Playgroud)

或简化为:

var currentAngle = Math.PI + Math.PI * normTime;
Run Code Online (Sandbox Code Playgroud)

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

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

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
}
Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)
var normTime = (currentTime - sunriseTime) / (sunsetTime - sunrisetime);
Run Code Online (Sandbox Code Playgroud)

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

另请参阅雅虎的天气频道 API,它提供您所在位置的日出/日落时间。还可以查看NOAA 的页面以获取正确计算与视点等相关的角度的提示和公式(NASA 也有一些很好的资源)

您还可以根据最终渲染的方式限制太阳绘图,当它在 [0, 1] 范围之外时(在上面的演示中,画布将为我们剪辑它)。