ipmap/index.html

144 lines
4.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="dark light">
<title>IP Map</title>
<script src="https://unpkg.com/maplibre-gl@4.1.2/dist/maplibre-gl.js"></script>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.1.2/dist/maplibre-gl.css" />
<style>
body {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
}
#map {
width: 100vh;
height: 100%;
margin: 0 auto;
}
.maplibregl-canvas {
cursor: pointer;
}
.maplibregl-popup-content {
background-color: #222;
font-size: 1rem;
padding: 0.8rem 1.2rem;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const hilbert_c2i = ({ x, y }) => {
let rotation = 0
let reflection = 0
let index = 0
for (let b = 15; b >= 0; b--) {
let bits = reflection
reflection = (y >>> b) & 1
reflection |= ((x >>> b) & 1) << 1
bits = bits ^ reflection
bits = ((bits >>> rotation) | (bits << (2 - rotation))) & 3
index |= bits << (b << 1)
reflection ^= (1 << rotation)
bits = bits & (-bits) & 1
while (bits) {
++rotation
bits >>>= 1
}
if (++rotation >= 2)
rotation -= 2
}
index ^= 0x2aaaaaaa
for (let d = 1; d < 32; d *= 2) {
let t = index >>> d
if (!t) break
index ^= t
}
return index
}
const hilbert_i2c = index => {
let rotation = 0
let reflection = 0
let coord = { x: 0, y: 0 }
index ^= (index >>> 1) ^ 0x2aaaaaaa
for (let b = 15; b >= 0; b--) {
var bits = index >>> (2 * b) & 3
reflection ^= ((bits >>> (2 - rotation)) | (bits << rotation)) & 3
coord.x |= (reflection & 1) << b
coord.y |= ((reflection >>> 1) & 1) << b
reflection ^= (1 << rotation)
bits &= (-bits) & 1
while (bits) {
bits >>>= 1
++rotation
}
if (++rotation >= 2)
rotation -= 2
}
return coord
}
const dateDir = (date = new Date()) => `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`
const map = new maplibregl.Map({
container: "map",
attributionControl: false,
renderWorldCopies: false,
doubleClickZoom: false,
dragRotate: false,
style: {
version: 8,
sources: {
"ipmap-tiles": {
type: "raster",
tiles: [
"tiles/2024-03-30/density/jet/{z}/{y}/{x}.png" // change to using remote json with list of tilemaps
],
minzoom: 0,
maxzoom: 8,
tileSize: 256
}
},
layers: [
{
id: "ipmap-tiles-layer",
type: "raster",
source: "ipmap-tiles",
paint: {
"raster-resampling": "nearest"
}
}
]
},
center: [0, 0],
minZoom: -1,
maxZoom: 12,
zoom: 0
})
map.painter.context.extTextureFilterAnisotropic = undefined
map.addControl(new maplibregl.NavigationControl({ showCompass: false }), "top-left")
const toIp = v => `${v >> 24 & 0xFF}.${v >> 16 & 0xFF}.${v >> 8 & 0xFF}.${v >> 0 & 0xFF}`
map.on("click", (e) => {
const { x, y } = maplibregl.MercatorCoordinate.fromLngLat(e.lngLat, 0)
const rawIp = hilbert_c2i({ x: Math.floor(0x10000 * x), y: Math.floor(0x10000 * y) })
const subnet = Math.min(32, Math.round(map.getZoom()) * 2 + 18)
const text = subnet < 32 ?
`Range: ${toIp((rawIp >> (32 - subnet)) << (32 - subnet))}/${subnet}` :
`IP: ${toIp(rawIp)}`
new maplibregl.Popup()
.setHTML(text)
.setLngLat(e.lngLat)
.addTo(map)
})
const setTileUrl = (date, variant, colormap) => map.getSource("ipmap-tiles").setTiles([`tiles/${dateDir(date)}/${variant}/${colormap}/{z}/{y}/{x}.png`])
</script>
</body>
</html>