2024-03-31 20:21:11 -04:00
|
|
|
<!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>
|
2024-04-02 09:43:54 -04:00
|
|
|
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
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
2024-04-02 09:43:54 -04:00
|
|
|
index ^= 0x2aaaaaaa
|
|
|
|
for (let d = 1; d < 32; d *= 2) {
|
|
|
|
let t = index >>> d
|
|
|
|
if (!t) break
|
|
|
|
index ^= t
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
2024-04-02 09:43:54 -04:00
|
|
|
return index
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
|
|
|
|
2024-04-02 09:43:54 -04:00
|
|
|
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
|
2024-03-31 20:21:11 -04:00
|
|
|
while (bits) {
|
2024-04-02 09:43:54 -04:00
|
|
|
bits >>>= 1
|
|
|
|
++rotation
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
|
|
|
if (++rotation >= 2)
|
2024-04-02 09:43:54 -04:00
|
|
|
rotation -= 2
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
2024-04-02 09:43:54 -04:00
|
|
|
return coord
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
|
|
|
|
2024-04-02 09:43:54 -04:00
|
|
|
const dateDir = (date = new Date()) => `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`
|
|
|
|
|
2024-03-31 20:21:11 -04:00
|
|
|
const map = new maplibregl.Map({
|
|
|
|
container: "map",
|
|
|
|
attributionControl: false,
|
|
|
|
renderWorldCopies: false,
|
|
|
|
doubleClickZoom: false,
|
|
|
|
dragRotate: false,
|
|
|
|
style: {
|
2024-04-02 09:43:54 -04:00
|
|
|
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
|
2024-03-31 20:21:11 -04:00
|
|
|
],
|
2024-04-02 09:43:54 -04:00
|
|
|
minzoom: 0,
|
|
|
|
maxzoom: 8,
|
|
|
|
tileSize: 256
|
2024-03-31 20:21:11 -04:00
|
|
|
}
|
|
|
|
},
|
2024-04-02 09:43:54 -04:00
|
|
|
layers: [
|
2024-03-31 20:21:11 -04:00
|
|
|
{
|
2024-04-02 09:43:54 -04:00
|
|
|
id: "ipmap-tiles-layer",
|
|
|
|
type: "raster",
|
|
|
|
source: "ipmap-tiles",
|
|
|
|
paint: {
|
2024-03-31 20:21:11 -04:00
|
|
|
"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)
|
|
|
|
})
|
2024-04-02 09:43:54 -04:00
|
|
|
const setTileUrl = (date, variant, colormap) => map.getSource("ipmap-tiles").setTiles([`tiles/${dateDir(date)}/${variant}/${colormap}/{z}/{y}/{x}.png`])
|
2024-03-31 20:21:11 -04:00
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|