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
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)
|
||
|
);
|
||
|
});
|
||
|
})();
|