parent
6de2fcac99
commit
5f177eda51
3 changed files with 145 additions and 50 deletions
|
@ -16,6 +16,5 @@
|
|||
</div>
|
||||
</div>
|
||||
<div id="map"></div>
|
||||
<p id="footnote">I hate blur... but here we are</p>
|
||||
</body>
|
||||
</html>
|
126
html/map/map.js
126
html/map/map.js
|
@ -8,40 +8,124 @@ L.tileLayer('https://{s}.tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png?apike
|
|||
apikey: 'db5ae1f5778a448ca662554581f283c5',
|
||||
}).addTo(map);
|
||||
|
||||
var pl1 = [52.1904441909767, 20.922122237417636];
|
||||
var de1a = [49.44951340282083, 11.014075123186862];
|
||||
var de1 = [50.085448739143715, 8.461733038044116];
|
||||
var nl1 = [52.36679746122722, 4.891598348592709];
|
||||
var it1 = [41.66806722233489, 12.503981281868477];
|
||||
var de1t = [50.085448739143715, 8.461733038044116];
|
||||
|
||||
// title, popup, location
|
||||
var nodes = [
|
||||
["Warsaw, Poland", "pl1 at equinix wa3", pl1],
|
||||
["Nuremberg, Germany", "de1 at hetzner nbg<br>Tunneled to Frankfurt. If you have a node here at hetzner nuremberg, it will go nbg -> fra -> nbg.", de1a],
|
||||
["Amsterdam, Netherlands", "nl1 at scaleway<br>I don't know where exactly", nl1],
|
||||
["Rome, Italy", "it1 at c1vhosting<br>I also don't know where exactly, but there's no evidence of the existence of the data center", it1]
|
||||
]
|
||||
// title, hostname, popup, location
|
||||
var nodes = {
|
||||
pl1: {
|
||||
location: [52.1904441909767, 20.922122237417636],
|
||||
city: "Warsaw, Poland",
|
||||
hostname: "pl1.420129.xyz",
|
||||
datacenter: "equinix wa3",
|
||||
description: "",
|
||||
publicKey: "v854+5m4Diqh8oGo6/sGVS7LELsreIjMujkWqwc6bWo=",
|
||||
linkLocal: "fe80::129:3"
|
||||
},
|
||||
de1: {
|
||||
location: [49.44951340282083, 11.014075123186862],
|
||||
city: "Nuremberg, Germany",
|
||||
hostname: "de1.420129.xyz",
|
||||
datacenter: "hetzner nbg",
|
||||
description: "Tunneled to Frankfurt. If you have a node here at hetzner nuremberg, it will go nbg -> fra -> nbg.",
|
||||
publicKey: "N9rGceoiFcc/obnHrqMAmVlrb/E2Br55+doekTKwNF8=",
|
||||
linkLocal: "fe80::129:2"
|
||||
},
|
||||
nl1: {
|
||||
location: [52.36679746122722, 4.891598348592709],
|
||||
city: "Amsterdam, Netherlands",
|
||||
hostname: "nl1.420129.xyz",
|
||||
datacenter: "scaleway AMS-1",
|
||||
description: "I don't know where exactly",
|
||||
publicKey: "iZfLBtF6BiQvdKXx4Yl02u+OL6ls35gSpWCRmB9q4lU=",
|
||||
linkLocal: "fe80::129:1"
|
||||
},
|
||||
it1: {
|
||||
location: [41.66806722233489, 12.503981281868477],
|
||||
city: "Rome, Italy",
|
||||
hostname: "it1.420129.xyz",
|
||||
datacenter: "c1vhosting?",
|
||||
description: "Location also approximate, there's no evidence of the existence of the data center",
|
||||
publicKey: "",
|
||||
linkLocal: "fe80::129:4"
|
||||
}
|
||||
}
|
||||
|
||||
function line(from, to, popup) {
|
||||
L.polyline([from, to], {opacity: 0.5}).addTo(map).bindPopup(popup);
|
||||
}
|
||||
|
||||
|
||||
var opened = null;
|
||||
|
||||
const sidebarContent = document.getElementById("sidebarContent");
|
||||
const nodesElement = document.getElementById("nodes");
|
||||
for (let node of nodes) {
|
||||
let marker = L.marker(node[2]).addTo(map).bindPopup(node[1]);
|
||||
|
||||
sidebarContent.onclick = (ev) => {
|
||||
if (opened == null) return;
|
||||
const popup = opened[0];
|
||||
|
||||
const rect = opened[1].getBoundingClientRect();
|
||||
|
||||
console.log('a')
|
||||
//sidebarContent.removeChild(opened);
|
||||
popup.style.height = rect.height - 20 + 'px';
|
||||
popup.style.transform = 'none';
|
||||
nodesElement.style.opacity = 1;
|
||||
|
||||
opened = null;
|
||||
map.closePopup();
|
||||
|
||||
setTimeout(() => {
|
||||
sidebarContent.removeChild(popup);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
function onNodeClick(ev, node, elem) {
|
||||
console.log('b')
|
||||
if (opened != null) return;
|
||||
const rect = elem.getBoundingClientRect();
|
||||
|
||||
nodesElement.style.opacity = 0;
|
||||
|
||||
ele = elem.cloneNode(true);
|
||||
ele.innerHTML += `<br><br>Datacenter: <span class="code">${node.datacenter}</span><br>${node.description.split('\n').slice(1).join('\n')}`;
|
||||
ele.onclick = (ev) => {ev.stopPropagation()};
|
||||
|
||||
ele.classList.add('selectedNode');
|
||||
sidebarContent.appendChild(ele);
|
||||
|
||||
ele.style.width = rect.width - 40 + 'px'; // padding or margin
|
||||
ele.style.height = rect.height - 20 + 'px';
|
||||
ele.style.top = rect.top - 10 + 'px';
|
||||
//ele.style.left = rect.left - 10 + 'px';
|
||||
|
||||
ele.offsetHeight;
|
||||
|
||||
const destY = 72 - rect.top; // window.innerHeight / 4
|
||||
ele.style.transform = `translateY(${destY}px)`;
|
||||
ele.style.height = window.innerHeight / 3 + 'px';
|
||||
|
||||
opened = [ele, elem];
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
for (let node of Object.values(nodes)) {
|
||||
let marker = L.marker(node.location).addTo(map).bindPopup(`<strong>${node.city}</strong><br>DC: ${node.datacenter}`);
|
||||
|
||||
let ele = document.createElement("div");
|
||||
ele.innerText = node[0];
|
||||
ele.onclick = () => {
|
||||
ele.innerHTML = `<strong>${node.city}</strong>`;
|
||||
if (node.description != '') ele.innerHTML += `<br><small>${node.description.split('\n')[0]}</small>`;
|
||||
ele.onclick = (ev) => {
|
||||
marker.openPopup();
|
||||
map.panTo(node[2], {
|
||||
map.panTo(node.location, {
|
||||
padding: [1000, 1000]
|
||||
});
|
||||
onNodeClick(ev, node, ele);
|
||||
};
|
||||
nodesElement.appendChild(ele);
|
||||
}
|
||||
|
||||
line(de1, de1a, "4ms");
|
||||
line(de1, pl1, "24ms");
|
||||
line(de1, nl1, "10ms");
|
||||
line(nl1, it1, "25ms");
|
||||
line(nodes.de1.location, de1t, "Tunnel (already included in other labels)<br><strong>4ms</strong>");
|
||||
line(de1t, nodes.pl1.location, "de1 - pl1<br><strong>24ms</strong>");
|
||||
line(de1t, nodes.nl1.location, "de1 - nl1<br><strong>10ms</strong>");
|
||||
line(nodes.nl1.location, nodes.it1.location, "it1 - nl1<br><strong>25ms</strong>");
|
|
@ -4,6 +4,30 @@ html, body {
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
#map {
|
||||
background: black;
|
||||
}
|
||||
|
||||
.code {
|
||||
cursor: pointer;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.selectedNode {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transition: transform .3s ease, height .3s ease;
|
||||
|
||||
text-align: left;
|
||||
background: #222;
|
||||
padding: 10px 20px;
|
||||
margin: 10px;
|
||||
width: calc(100% - 60px);
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
width: 320px;
|
||||
height: 100%;
|
||||
|
@ -26,9 +50,9 @@ html, body {
|
|||
|
||||
#nodes {
|
||||
width: 100%;
|
||||
}
|
||||
transition: opacity .3s ease;
|
||||
|
||||
#nodes > div {
|
||||
div {
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
background: #222;
|
||||
|
@ -39,16 +63,8 @@ html, body {
|
|||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#footnote {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
text-align: center;
|
||||
color: transparent;
|
||||
z-index: 9999;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#blurThing {
|
||||
|
@ -107,22 +123,18 @@ html, body {
|
|||
@media screen and (max-width: 600px) {
|
||||
#sidebar {
|
||||
width: 100%;
|
||||
height: 220px;
|
||||
height: 320px;
|
||||
|
||||
mask-image: linear-gradient(180deg, black 200px, transparent 220px);
|
||||
mask-image: linear-gradient(180deg, black 300px, transparent 320px);
|
||||
|
||||
#sidebarContent {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-left {
|
||||
margin-left: none;
|
||||
margin-top: 220px;
|
||||
}
|
||||
|
||||
#footnote {
|
||||
display: none;
|
||||
margin-top: 320px;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue