所以我试图在弧形路径中画一个太阳(Pref a circle path)来模拟日出/日落,我遇到了问题。
画布宽度= 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));
这是我试图使其正确旋转的代码,它似乎给了我错误的弧形类型。
关于HTML画布的奇怪之处在于(0,0)位于屏幕的左上角,所以事情有点奇怪。我试图找到一个体面的网站,解释如何找到它,但我找到的一切似乎并没有按照我想要的方式工作。
我根据我对数学的了解进行了这次转换....如果这种方法有所了解,请告诉我!
答案 0 :(得分:4)
错误是由于x和y都使用了正弦。由于画布朝向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,太阳基本上会直线上升并且直线下降。如果你在北极圈(或南极圈)之上,你会有一个相当陡峭的角度。此外,太阳永远不会在夏季时间(midnight sun)设置,并且在冬季(polar night)永远不会在这些纬度上升。
如果您刚刚接近近似值,则可以在角度0处定义基线(日出),在角度180处定义日落,从左到右(或从东到西,如果您在南部)以弧形定义半球你可能更喜欢相反的方式。)
Canvas'坐标系将指向右0°,90°将指向下方,因此我们将知道180°360°将是一个具有天顶(最高点)的圆弧,为270°。
这将使用虚拟太阳和任意步骤绘制这样的弧:
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>
现在剩下的就是根据纬度找到宽度和高度的水平线和半径。天顶/方位角也是需要考虑的因素,太阳路径的中心可能不会在地平线上,所以必须根据一年中的位置和时间减少或增加标准化的角度范围。
另请参阅 Yahoo's Weather channel API ,其中提供了您所在位置的时间/日落时间。还可以查看 NOAA's page ,了解正确计算与观点等相关的角度的提示和公式。(NASA也有一些很好的资源)
当它在[0,1]范围之外时,您也可以限制太阳绘图,具体取决于最终渲染的方式(在上面的演示中,画布将为我们剪辑)。