const hub = [103.99, 1.36]
const distanceKm = ([lon1, lat1], [lon2, lat2]) => {
const R = 6371.0088
const rad = Math.PI / 180
const dLat = (lat2 - lat1) * rad
const dLon = (lon2 - lon1) * rad
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(lat1 * rad) * Math.cos(lat2 * rad) * Math.sin(dLon / 2) ** 2
return Math.round(2 * R * Math.asin(Math.sqrt(a)))
}
const routes = [
{ name: 'Singapore to London Heathrow', to: [-0.45, 51.47] },
{ name: 'Singapore to New York JFK', to: [-73.78, 40.64] },
{ name: 'Singapore to Los Angeles', to: [-118.41, 33.94] },
{ name: 'Singapore to Tokyo Narita', to: [140.39, 35.77] },
{ name: 'Singapore to Sydney', to: [151.18, -33.95] },
{ name: 'Singapore to Johannesburg', to: [28.24, -26.13] },
{ name: 'Singapore to São Paulo', to: [-46.47, -23.43] },
{ name: 'Singapore to Frankfurt', to: [8.57, 50.04] },
{ name: 'Singapore to Dubai', to: [55.36, 25.25] },
{ name: 'Singapore to Auckland', to: [174.79, -37.01] },
].map((d) => ({ name: d.name, from: hub, to: d.to, value: distanceKm(hub, d.to) }))
const night = ['#22d3ee', '#38bdf8', '#818cf8', '#c084fc', '#fbbf24']
const map = new ApexMaps(document.getElementById('map'), {
chart: { height: 540 },
theme: { mode: 'dark' },
geo: {
map: 'world/land@110m',
fill: '#1d2735',
view: { fit: [-180, -58, 180, 84], padding: 16 },
sphere: { show: true, fill: '#0d121b', stroke: 'rgba(255,255,255,0.08)' },
graticule: { show: true, step: 20, color: 'rgba(255,255,255,0.055)', width: 0.6 },
},
series: [
{
type: 'arc',
name: 'Great-circle distance',
data: routes,
geodesic: true,
curvature: 0,
width: { range: [0.6, 3.4] },
colorScale: { palette: night, classes: 5 },
opacity: 0.9,
endpoints: { show: true, radius: 2, color: '#e8f4ff' },
flow: true,
},
],
legend: {
title: 'Great-circle distance, km',
align: 'start',
formatter: (item) => `${Math.round(item.from)} to ${Math.round(item.to)}`,
},
tooltip: {
formatter: ({ name, value }) =>
`<div style="font-weight:640">${name}</div>` +
`<div style="font-weight:600">${value.toLocaleString()} km</div>`,
},
})
map.render()