2015-06-01 3 views
1

Так что я пытаюсь нарисовать солнце по дуге (Pref круг), чтобы имитировать восход/закат, и я сталкиваюсь с проблемами.Путь дуги Солнца в Javascript

Холст шириной = 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) находится в верхнем левом углу экрана, поэтому все немного странно. Я попытался найти достойный сайт, который объяснил, как его найти, но все, что я нахожу, похоже, не работает так, как я этого хочу.

Я сделал это преобразование, основанное на том, что я знаю с математикой .... Soooo, если этот подход ушел, пожалуйста, дайте мне знать!

ответ

3

Ошибка связана с тем, что синус используется как для x, так и для y. Как холст ориентируют 0 ° направляется прямо должно быть:

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

Обратите внимание, что 400100 имеют радиус здесь так, чтобы определить центр вы также должны были бы центральную точку:

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, идущий дугой слева направо (или с востока на запад, если вы находитесь в южное полушарие, вы, вероятно, предпочтете противоположное).

Система координат холста будет иметь 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>

То, что осталось теперь найти линию горизонта и радиус для ширины и высоты в зависимости от широты. Зенит/азимут также являются факторами, которые следует учитывать, а также то, что центр солнечного пути, вероятно, не будет лежать на горизонте, поэтому диапазон углов для нормализации должен быть уменьшен или увеличен в зависимости от местоположения и времени года.

См. Также Yahoo's Weather channel API, который обеспечивает время засыпания/захода солнца, где вы находитесь. Также проверьте NOAA's page для подсказок и формул, чтобы правильно вычислить углы относительно точки обзора и т.д. (НАСА имеет некоторые хорошие ресурсы, а)

Вы также можете ограничить солнечный рисунок, когда он вне [0, 1] в зависимости от того, как будет проходить ваш окончательный рендеринг (в демонстрационной надписи холст будет закрепить его для нас).

+0

Я признаю, что это один из лучших ответов, которые я когда-либо получал. Так что большое спасибо за то, что нашли время, чтобы помочь мне! Это заставило его работать отлично :). – Justin

+0

@ user3585563 без проблем, рад, что я мог бы помочь! :) Удачи с вашим проектом. – K3N

Смежные вопросы