astronomy-js
Version:
A lightweight javascript library for astronomical calculations.
300 lines (266 loc) • 11.6 kB
HTML
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<title>AstronomyJS</title>
<style>
.card-image svg {
display: block;
margin: 0 auto;
}
.container {
max-width: 1024px ;
margin-left: auto;
margin-right: auto;
padding-left: 1rem;
padding-right: 1rem;
}
:root {
--pico-font-size: 100% ;
}
#timeLabel {
width: 5rem;
}
#map {
height: 400px;
width: 100%;
}
</style>
<link rel="stylesheet" href="pico.min.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
</head>
<body class="container">
<header>
<div style="display: flex; align-items: center; gap: 16px;">
<img src="../images/icon.png" alt="AstronomyJS Logo" width="144">
<div>
<h1>AstronomyJS</h1>
<p>Accurate and accessible JavaScript tools for astronomy calculations.</p>
</div>
</div>
</header>
<main>
<article>
<form>
<div class="grid">
<div>
<label for="datePicker">Date</label>
<input type="date" id="datePicker"/>
</div>
<div>
<label for="timeRange">Time</label>
<div role="group" style="display: flex; align-items: center; gap: 1rem;">
<input type="range" id="timeRange" min="0" max="1440" value="0" step="1"/>
<output id="timeLabel">00:00</output>
<button id="nowButton">Now</button>
</div>
</div>
</div>
</form>
<details>
<summary role="button" class="outline contrast">Location</summary>
<form>
<div class="grid">
<label>
Latitude:
<input type="number" step="0.00001" id="latitudeInput">
</label>
<label>
Longitude:
<input type="number" step="0.00001" id="longitudeInput">
</label>
</div>
</form>
<div id="map"></div>
</details>
</article>
<article>
<header>Sky Position</header>
<table id="solarSystemTable">
<thead>
<tr>
<th>Object</th>
<th>Altitude</th>
<th>Azimuth</th>
<th>Right Ascension</th>
<th>Declination</th>
</tr>
</thead>
</table>
</article>
<div class="grid">
<article>
<header>Ephemerides</header>
<table id="ephemeridesTable">
<thead>
<tr>
<th>Object</th>
<th>Rise</th>
<th>Set</th>
</tr>
</thead>
</table>
</article>
<article>
<header>Sun</header>
<table id="sunEphemeridesTable">
<thead>
<tr>
<th>Event</th>
<th>Time</th>
</tr>
</thead>
</table>
</article>
</div>
</main>
</body>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script type="module">
import {AstronomyJS} from "../dist/astronomy-js.es.js";
const solarSystemObjectsToDisplay = ["Sun", "Mercury", "Venus", "Mars",
"Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"];
const initialLatitude = 51.477335;
const initialLongitude = -0.000874;
let astronomyJS = AstronomyJS.initialize(initialLatitude, initialLongitude);
const latitudeInput = document.getElementById('latitudeInput');
const longitudeInput = document.getElementById('longitudeInput');
const solarSystemTable = document.getElementById('solarSystemTable');
const ephemeridesTable = document.getElementById('ephemeridesTable');
const sunEphemeridesTable = document.getElementById('sunEphemeridesTable');
latitudeInput.value = initialLatitude;
longitudeInput.value = initialLongitude;
latitudeInput.addEventListener('input', onLocationChange);
longitudeInput.addEventListener('input', onLocationChange);
function updateInputs(latitude, longitude) {
latitudeInput.value = latitude.toFixed(5);
longitudeInput.value = longitude.toFixed(5);
onLocationChange();
}
const map = L.map('map').setView([initialLatitude, initialLongitude], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
const marker = L.marker([initialLatitude, initialLongitude], {draggable: true}).addTo(map);
marker.on('dragend', function (_) {
const {lat, lng} = marker.getLatLng();
updateInputs(lat, lng);
});
map.on('click', function (e) {
const {lat, lng} = e.latlng;
marker.setLatLng([lat, lng]);
updateInputs(lat, lng);
});
function onLocationChange() {
const latitude = parseFloat(latitudeInput.value);
const longitude = parseFloat(longitudeInput.value);
if (!isNaN(latitude) && !isNaN(longitude)) {
marker.setLatLng([latitude, longitude]);
map.setView([latitude, longitude], map.getZoom());
astronomyJS.setLocation("Earth", latitude, longitude);
updateAllTilesWithTime(astronomyJS.getDate());
}
}
function updateAllTilesWithTime(referenceDate) {
astronomyJS.setDate(referenceDate);
updateAstronomicalData();
}
const now = new Date();
const datePicker = document.getElementById('datePicker');
datePicker.value = now.toISOString().slice(0, 10);
const timeRange = document.getElementById('timeRange');
const timeLabel = document.getElementById('timeLabel');
const nowButton = document.getElementById('nowButton');
function minutesToHHMM(minutes) {
const hour = Math.floor(minutes / 60);
const minute = minutes % 60;
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
}
function getMinutesSinceMidnight(referenceDate) {
return referenceDate.getHours() * 60 + referenceDate.getMinutes();
}
function updateTimeToNow() {
const now = new Date();
datePicker.value = now.toISOString().slice(0, 10);
const nowMinutes = getMinutesSinceMidnight(now);
timeRange.value = nowMinutes;
timeLabel.textContent = minutesToHHMM(nowMinutes);
updateAllTilesWithTime(now);
}
nowButton.addEventListener('click', (event) => {
event.preventDefault();
updateTimeToNow();
});
timeRange.addEventListener('input', () => {
timeLabel.value = minutesToHHMM(parseInt(timeRange.value, 10));
updateAllTilesWithTime(getReferenceDateFromForm());
});
datePicker.addEventListener('input', () => {
updateAllTilesWithTime(getReferenceDateFromForm());
});
function formatDateToHHMM(referenceDate) {
return referenceDate ? referenceDate.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
hour12: false,
}) : "-";
}
function getReferenceDateFromForm() {
const [year, month, day] = datePicker.value.split('-').map(Number);
const minutes = parseInt(timeRange.value, 10);
const hour = Math.floor(minutes / 60);
const minute = minutes % 60;
return new Date(year, month - 1, day, hour, minute);
}
function addValuesToTable(tableObject, rows) {
for (let i in rows) {
let row = document.createElement("tr");
let tableValues = rows[i];
for (let j in tableValues) {
const column = document.createElement("td");
column.appendChild(document.createTextNode(tableValues[j]));
row.appendChild(column);
}
tableObject.appendChild(row);
}
}
function updateAstronomicalData() {
while (solarSystemTable.rows.length > 1) {
solarSystemTable.deleteRow(1);
}
let solarSystemTableRows = [];
for (let i in solarSystemObjectsToDisplay) {
const objectName = solarSystemObjectsToDisplay[i];
let altAzCoordinates = astronomyJS.getAltAzCoordinatesForObject(objectName).toDegrees();
let raDecCoordinates = astronomyJS.getRADecCoordinatesForObject(objectName).toHours();
solarSystemTableRows.push([objectName, altAzCoordinates.latitude, altAzCoordinates.longitude, raDecCoordinates.longitude, raDecCoordinates.latitude]);
}
addValuesToTable(solarSystemTable, solarSystemTableRows);
while (ephemeridesTable.rows.length > 1) {
ephemeridesTable.deleteRow(1);
}
let ephemeridesTableRows = [];
for (let i in solarSystemObjectsToDisplay) {
const objectName = solarSystemObjectsToDisplay[i];
let rise = formatDateToHHMM(astronomyJS.getEphemerisDateForObject(objectName, astronomyJS.getDate(), "RISE"));
let set = formatDateToHHMM(astronomyJS.getEphemerisDateForObject(objectName, astronomyJS.getDate(), "SET"));
ephemeridesTableRows.push([objectName, rise, set]);
}
addValuesToTable(ephemeridesTable, ephemeridesTableRows);
while (sunEphemeridesTable.rows.length > 1) {
sunEphemeridesTable.deleteRow(1);
}
let sunEphemeridesTableRows = [];
sunEphemeridesTableRows.push(["Astronomical Twilight Start", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "ASTRONOMICAL_TWILIGHT_START"))]);
sunEphemeridesTableRows.push(["Nautical Twilight Start", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "NAUTICAL_TWILIGHT_START"))]);
sunEphemeridesTableRows.push(["Civil Twilight Start", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "CIVIL_TWILIGHT_START"))]);
sunEphemeridesTableRows.push(["Rise", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "RISE"))]);
sunEphemeridesTableRows.push(["Local Noon", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "TRANSIT"))]);
sunEphemeridesTableRows.push(["Set", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "SET"))]);
sunEphemeridesTableRows.push(["Civil Twilight End", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "CIVIL_TWILIGHT_END"))]);
sunEphemeridesTableRows.push(["Nautical Twilight End", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "NAUTICAL_TWILIGHT_END"))]);
sunEphemeridesTableRows.push(["Astronomical Twilight End", formatDateToHHMM(astronomyJS.getEphemerisDateForObject("Sun", astronomyJS.getDate(), "ASTRONOMICAL_TWILIGHT_END"))]);
addValuesToTable(sunEphemeridesTable, sunEphemeridesTableRows);
}
updateTimeToNow();
</script>
</html>