БлогNot. Простая модель "Солнце, Земля и Луна" на Javascript

Простая модель "Солнце, Земля и Луна" на Javascript

Простая - значит, буквально на 3 картинках и одной канве. Правда, Луна, как видно "прячется" в тени Земли от Солнца, это единственное усложнение, чтобы показать принципы дальнейшей модификации примера.

Извините, Ваш браузер не поддерживает тег canvas

Подход к позиционированию картинок использован "самый современный", то есть, мы не пересчитываем "вручную" полярные координаты в декартовы, а используем возможности яваскрипта по переносу, сдвигу и повороту плоской системы координат. С учётом всего этого, сделать скрипт с вращающимися вокруг Солнца Землёй и Луной не сложнее, чем идущие часики со стрелками.

Размер канвы в теге <canvas> предполагается квадратным, хотя и не обязательно, картинки также лучше использовать квадратные. Исходник, который можно сохранить в формате файла .html, предполагает, что картинки с именами sun.png, earth.png и moon.png находятся в той же папке, что и сам скрипт. Если нужно, это легко изменить.

Числовые константы в скрипте тоже можно менять, но я был бы с этим поосторожнее, ведь мы пересчитываем всё в целые пиксельные координаты и, например, при неудачном сочетании скоростей Земли и Луны последняя может где-то "запрыгать".

Все действия по рисованию Земли подробно закомментированы, остальное, думаю, будет ясно по аналогии :)

<div align="center">
 <canvas id="sunSystemCanvas" width="500" height="500" style="background-color: black;">
  <font color="#808080">Извините, Ваш браузер не поддерживает тег canvas</font>
 </canvas>
</div>
<script type="text/javascript">
 var sunImg = new Image();
 var moonImg = new Image();
 var earthImg = new Image();

 function init() {
  sunImg.src = 'sun.png'; //получить рисунки
  moonImg.src = 'moon.png';
  earthImg.src = 'earth.png';
  window.requestAnimationFrame (draw); //запланировать перерисовку и вызвать функцию draw
 }

 function draw() { //основной метод
  var canvas = document.getElementById('sunSystemCanvas');
  var ctx = canvas.getContext('2d');
  ctx.globalCompositeOperation = 'destination-over'; //новые фигуры рисуются под уже нарисованными
  var width = canvas.width;
  var height = canvas.height; //размеры канвы
  var cx = Math.floor(width/2);
  var cy = Math.floor(height/2); //центр канвы
  var earthDelta = Math.floor(0.35*Math.min(width,height)); //смещение орбиты Земли в долях единицы
  var moonDelta = Math.floor(0.095*Math.min(width,height)); //смещение орбиты  Луны, в долях единицы

  ctx.clearRect(0, 0, width, height); //очистить канву
  var time = new Date(); //Текущее время

  ctx.save();
  ctx.translate(cx, cy); //Начало координат смещаем в центр канвы

  //Земля:
  var P2 = 2 * Math.PI; //круг = 2 пи :)
  var earthSpeed = 60; //секунд на оборот
  ctx.rotate((P2/earthSpeed)*time.getSeconds() + (P2/(earthSpeed*1000))*time.getMilliseconds());
   //повернуть систему координат на нужную долю круга
  ctx.translate(earthDelta, 0); //и сдвинуть по оси X на заданную величину орбиты
  var halfOfEarth = -1*Math.floor(earthImg.width/2); //пол-Земли, предполагаем, что ширина картинки = высоте
  ctx.fillStyle = 'rgba(0, 0, 0, 0.4)'; //стиль заполнения
  ctx.fillRect (0, halfOfEarth, moonDelta + moonImg.width, earthImg.width); //тень от Земли на Луну
  ctx.drawImage(earthImg, halfOfEarth, halfOfEarth); //рисуем Землю
   //Луна:
   ctx.save();
   var moonSpeed = earthSpeed/12; //на самом деле - 13.37 оборотов Луны вокруг Земли за год
   ctx.rotate((P2/moonSpeed)*time.getSeconds() + (P2/(moonSpeed*1000))*time.getMilliseconds());
   ctx.translate(0, moonDelta);
   var halfOfMoon = -1*Math.floor(moonImg.width/2); //пол-Луны, предполагаем, что ширина картинки = высоте
   ctx.drawImage(moonImg, halfOfMoon, halfOfMoon);
   ctx.restore();
  ctx.restore();
  //Земная орбита:
  ctx.strokeStyle = 'rgba(0, 204, 255, 0.45)';  
  ctx.setLineDash([2, 4]);
  ctx.beginPath();
  ctx.arc(cx, cy, earthDelta, 0, Math.PI * 2, false); 
  ctx.stroke();

  //Солнце:
  ctx.save();
  ctx.translate(cx, cy); //Солнце - в центре канвы
  var halfOfSun = -1*Math.floor(sunImg.width/2); //пол-Солнца, предполагаем, что ширина картинки = высоте
  ctx.drawImage(sunImg, halfOfSun, halfOfSun); 
  ctx.restore();

  window.requestAnimationFrame(draw);
 }

 window.onload = init; //запустить функцию init по загрузке содержимого окна
</script>
<noscript>
 <div align="center">
  Извините, нужен Javascript для работы приложения
 </div>
</noscript>
sun.png
sun.png
earth.png
earth.png
moon.png
moon.png

Помните также, что модель с неподвижным Солнцем в середине имеет к реальности не очень много отношения, а на самом деле наша Солнечная система движется примерно вот так:

движение Солнца и планет в космосе
движение Солнца и планет в космосе

Какими будут расстояния от Земли до Солнца и ближайшей звезды, если мы решим соблюдать масштабы для объектов и расстояний между ними?

Подсчитать это несложно. Представим, что Землю мы изобразили крошечной пылинкой или маковым зёрнышком с диаметром 0,5 мм (реальный диаметр Земли, напомним, ~12742 км).

Тогда Солнце, имеющее диаметр примерно 1390600 км, будет размером примерно с шар бильярда-американки (диаметр такого шара 57 мм, а диаметр Солнца в этом масштабе станет порядка 54,5 мм). Положить этот бильярдный шар нужно будет почти на 6 метров от пылинки (150000000 км от Земли до Солнца или примерно 5,88 м в нашем масштабе).

Где будет находиться ближайшая к нам звезда Альфа Центавра, имеющая схожий с Солнцем размер и отстоящая от него на ~39900000000000 км? Увы, даже не на соседней улице. Расстояние до неё в нашем масштабе составит около 1565 км и будет соответствовать расстоянию от Новосибирска до Челябинска.

2022. Мир состоит из пустоты. "Вояджеры" обнаружили странности с пространством вскоре после ухода из Солнечной системы
2022. Мир состоит из пустоты. "Вояджеры" обнаружили странности с пространством вскоре после ухода из Солнечной системы

08.02.2018, 13:25 [6398 просмотров]


теги: javascript графика числа вселенная

показать комментарии (1)