203 lines
6.7 KiB
HTML
203 lines
6.7 KiB
HTML
<!doctype html>
|
|
<html lang='en'>
|
|
|
|
<head>
|
|
<meta charset='UTF-8'>
|
|
<title>MapProjection</title>
|
|
|
|
|
|
<link rel='stylesheet' href='../../3rdparty/highlight/styles/default.css'>
|
|
<link rel='stylesheet' href='../../../css/doctest.css'>
|
|
|
|
<script src="../../../dist/iwmlib.3rdparty.js"></script>
|
|
<script src="../../../dist/iwmlib.js"></script>
|
|
<script src="../../../dist/iwmlib.pixi.js"></script>
|
|
|
|
<style>
|
|
.inline-showcase {
|
|
display: flex
|
|
}
|
|
|
|
.map-example {
|
|
display: inline-block;
|
|
width: 256px;
|
|
margin: 5px;
|
|
}
|
|
|
|
.map-container {
|
|
position: relative;
|
|
display: inline-flex;
|
|
}
|
|
|
|
.map-marker {
|
|
position: absolute;
|
|
transform: translate(-50%, -75%) scale(0.5);
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body onload='Doctest.run()'>
|
|
<h1>MapProjection</h1>
|
|
<p>The map projection calculates is responsible for transforming map coordinates to pixel coordinates and backwards.</p>
|
|
|
|
<h2>Static Squared World Map</h2>
|
|
<p>The most simple example is a squared world map, thats projected with mercator transformation. Ranging from
|
|
Longitude
|
|
-180 to 180 and Latitude from -90 to 90 (Exclusive, because mercator gets infinite at +/-90). </p>
|
|
<p>Coordinates:
|
|
<strong id="map_coords_0"></strong>
|
|
</p>
|
|
<div id="mapContainerGeneral" class="map-container">
|
|
<img src="../assets/maps/osm/0/0/0.png" id="map_image_0" alt="Image is missing." width="512">
|
|
</div>
|
|
<script>
|
|
|
|
let capitals = {
|
|
abidjan: { x: 5.349470, y: -4.006472 },
|
|
berlin: { x: 52.525430, y: 13.385291 },
|
|
canberra: { x: -35.282025, y: 149.128648 },
|
|
capetown: { x: -33.925448, y: 18.416962 },
|
|
moscow: { x: 55.750892, y: 37.622799 },
|
|
washington: { x: 38.895650, y: -77.031407 },
|
|
rio: { x: -22.871400, y: -43.280490 },
|
|
tokio: { x: 35.696278, y: 139.731366 }
|
|
}
|
|
|
|
const europeanCapitalCities = {
|
|
berlin: { x: 52.505949, y: 13.379400 },
|
|
london: { x: 51.5, y: -0.083333 },
|
|
rome: { x: 41.9, y: 12.483333 },
|
|
madrid: { x: 40.4, y: -3.683333 },
|
|
paris: { x: 48.833986, y: 2.346989 }
|
|
}
|
|
|
|
|
|
//Helper function to print the coordinates to a dom element.
|
|
function printCoordinates(element, mapProjection, out_dom) {
|
|
element.addEventListener("mousemove", (event) => {
|
|
let coords = mapProjection.toCoordinates({ x: event.offsetX / event.target.width, y: event.offsetY / event.target.height })
|
|
out_dom.innerHTML = "Lat: " + coords.x.toFixed(4) + " Lng: " + coords.y.toFixed(4)
|
|
})
|
|
}
|
|
|
|
|
|
function placeMarker(parent, position) {
|
|
const markerIconPath = "../../../assets/icons/room.png"
|
|
|
|
let marker = document.createElement("img")
|
|
marker.src = markerIconPath
|
|
marker.className = "map-marker"
|
|
|
|
Object.assign(marker.style, {
|
|
left: (position.x * 100) + "%",
|
|
top: (position.y * 100) + "%"
|
|
})
|
|
parent.appendChild(marker)
|
|
console.log(marker)
|
|
}
|
|
|
|
</script>
|
|
<script class="doctest">
|
|
|
|
// Instantiate our map projection.
|
|
let squared_world = new MapProjection(new Projection.Mercator());
|
|
|
|
// Define a position, we are interested in in {x: latitude, y: longitude}
|
|
let iceland = { x: 64.514979, y: -19.020796 }
|
|
|
|
// Gets the normalized positition of the coordinates
|
|
let pos_0 = squared_world.toPixel(iceland)
|
|
|
|
// Helper function to set the dom marker.
|
|
placeMarker(mapContainerGeneral, pos_0)
|
|
|
|
</script>
|
|
<script>
|
|
printCoordinates(map_image_0, squared_world, map_coords_0)
|
|
</script>
|
|
<h2 id="germany">Clipped Map</h2>
|
|
<p>Often we don't use the whole map, or our map is a subsection of the world. MapProjection can clip those cases, using
|
|
the a
|
|
bounding box of min and max coordinates.</p>
|
|
<p>Coordinates:
|
|
<strong id="map_coords_1"></strong>
|
|
</p>
|
|
<div class="map-container" id="mapContainerClipped">
|
|
<img src="../assets/maps/pixabay/europe.jpg" id="map_image_1" alt="Image is missing." width="512">
|
|
</div>
|
|
<script class="doctest">
|
|
|
|
//Same procedure as above, just add a clipping parameter to the MapProjection object.
|
|
let europe = new MapProjection(new Projection.Mercator(), {
|
|
clip: {
|
|
min: { x: 32.863294, y: -18.58 },
|
|
max: { x: 57.467973, y: 44.277158 }
|
|
}
|
|
})
|
|
|
|
//Same as above
|
|
for (let coordinates of Object.values(europeanCapitalCities)) {
|
|
let pixelPosition = europe.toPixel(coordinates)
|
|
placeMarker(mapContainerClipped, pixelPosition)
|
|
}
|
|
|
|
</script>
|
|
<script>
|
|
printCoordinates(map_image_1, germany, map_coords_1)
|
|
</script>
|
|
<h2>Translated Map</h2>
|
|
<p>Maps can be also translated, if the whole world is shown and clipping is not an option.</p>
|
|
<p>Coordinates:
|
|
<strong id="map_coords_2"></strong>
|
|
</p>
|
|
<div id="map_image_2" class="map-container"">
|
|
</div>
|
|
<script class=" doctest">
|
|
|
|
|
|
|
|
const size = 256
|
|
|
|
|
|
// Fake offset by using the old map projection.
|
|
let translation = squared_world.toPixel({ x: 90-10, y: -140 })
|
|
console.log(translation)
|
|
|
|
|
|
//This map is clipped at the bottom
|
|
// And also translated in hoizontal direction.
|
|
// The translate option corrects that.
|
|
let translated_world = new MapProjection(new Projection.Mercator(), {
|
|
translate: { x: -10, y: 40 },
|
|
|
|
})
|
|
|
|
|
|
console.log(translation)
|
|
|
|
Object.assign(map_image_2.style, {
|
|
width: size + "px",
|
|
height: size + "px",
|
|
backgroundImage: "url(../assets/maps/osm/0/0/0.png)",
|
|
backgroundColor: "red",
|
|
backgroundPosition: translation.x * size + "px " +translation.y * size + "px"
|
|
})
|
|
|
|
//Same as above
|
|
for (let coordinates of Object.values(capitals)) {
|
|
let position = translated_world.toPixel(coordinates)
|
|
placeMarker(map_image_2, position)
|
|
}
|
|
</script>
|
|
<script>
|
|
map_image_2.addEventListener("mousemove", (event) => {
|
|
let map = map_image_2
|
|
console.log(event.offsetX / map.width)
|
|
let coords = translated_world.toCoordinates({ x: event.offsetX / map.offsetWidth, y: event.offsetY / map.offsetHeight })
|
|
map_coords_2.innerHTML = "Lat: " + coords.x.toFixed(4) + " Lng: " + coords.y.toFixed(4)
|
|
})
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html> |