You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.5 KiB
JavaScript

4 years ago
(function() {
function createSvgEl(tag) {
return document.createElementNS("http://www.w3.org/2000/svg", tag);
}
function lerp(datax, datay, x) {
for (let i=0; i<datax.length; i++) {
const lo = datax[i];
const hi = datax[i + 1];
if (lo > x || hi < x)
continue;
const loy = datay[i];
const hiy = datay[i + 1];
return loy + (hiy-loy) * ((x - lo) / (hi - lo));
}
}
function robinson(lat, lon, radius, centerMeridian, adjX, adjY) {
const table = [
// lat a b
[0, 1.0000, 0.0000],
[5, 0.9986, 0.0314],
[10, 0.9954, 0.0629],
[15, 0.9900, 0.0943],
[20, 0.9822, 0.1258],
[25, 0.9730, 0.1572],
[30, 0.9600, 0.1887],
[35, 0.9427, 0.2201],
[40, 0.9216, 0.2515],
[45, 0.8962, 0.2826],
[50, 0.8679, 0.3132],
[55, 0.8350, 0.3433],
[60, 0.7986, 0.3726],
[65, 0.7597, 0.4008],
[70, 0.7186, 0.4278],
[75, 0.6732, 0.4532],
[80, 0.6213, 0.4765],
[85, 0.5722, 0.4951],
[90, 0.5322, 0.5072],
];
const a = lerp(table.map(r => r[0]), table.map(r => r[1]), Math.abs(lat));
const b = lerp(table.map(r => r[0]), table.map(r => r[2]), Math.abs(lat));
const x = 0.8487 * radius * a * ((lon * Math.PI/180) - centerMeridian) * adjX;
const y = (1.3523 * radius * b * adjY) * (lat < 0 ? -1 : 1);
return [x, y];
}
function hexbyte(n) {
return Math.round(n).toString(16).padStart(2, '0')
}
function ring(x, y, radius, strokeWid, trans) {
const circle = createSvgEl("circle");
circle.setAttribute("cx", x);
circle.setAttribute("cy", y);
circle.setAttribute("r", radius);
circle.setAttribute("stroke", "#1c619a" + hexbyte(80 + trans * 5));
circle.setAttribute("stroke-width", strokeWid);
circle.setAttribute("fill", "#1c619a" + hexbyte(trans));
return circle;
}
function drawServerLocation(e, data) {
if (!e || !data) return;
const svg = e.contentDocument.querySelector("svg");
const height = svg.height.baseVal.value;
const width = svg.width.baseVal.value;
const earthRadius = width / 2.666269758 / 2;
const center = 0;
const adjX = 1.02;
const adjY = 2;
const offX = -12;
const offY = 75;
for (point of data) {
const xy = robinson(point[0], point[1], earthRadius, center, adjX, adjY);
const realX = (width / 2) + xy[0] + offX;
const realY = (height / 2) - (xy[1]) + offY;
const dot = createSvgEl("circle");
dot.setAttribute("cx", realX);
dot.setAttribute("cy", realY);
dot.setAttribute("r", 5);
dot.setAttribute("fill", "#1c619a");
svg.appendChild(dot);
const rf = 5;
const rs = 15;
svg.appendChild(ring(realX, realY, rf + rs * 1, 2, 20));
svg.appendChild(ring(realX, realY, rf + rs * 2, 1, 15));
svg.appendChild(ring(realX, realY, rf + rs * 3, 0.5, 10));
}
}
window.addEventListener("load", function() {
drawServerLocation(
document.getElementById("map"),
JSON.parse(document.getElementById('locations-data').textContent)
);
});
})();