Skip to content

Instantly share code, notes, and snippets.

@IagoLast
Last active November 8, 2023 13:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IagoLast/d6575a79fa279f450947244bba81f098 to your computer and use it in GitHub Desktop.
Save IagoLast/d6575a79fa279f450947244bba81f098 to your computer and use it in GitHub Desktop.
Webmercator, geojson and 2D canvas
license: gpl-3.0
height: 600
scrolling: no
border: no
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Mercator projection example</title>
<style>
body {
margin: 0;
padding: 0;
}
canvas {
display: block;
margin: auto;
}
;
</style>
</head>
<body>
<script>
// Used to generate colors
let i = 0;
// Adjust the map size to the window size
const MAP_SIZE = Math.min(window.parent.window.innerHeight, window.parent.window.innerWidth);
// Set the projection Radius, force the diameter to be equal to map size.
const R = MAP_SIZE / (2 * Math.PI);
// Diameter of the globe
const D = R * 2 * Math.PI;
// Create a canvas element
const canvas = document.createElement('canvas');
// Set canvas size
canvas.width = MAP_SIZE;
canvas.height = MAP_SIZE * 0.7;
// Add the canvas to the DOM
document.body.appendChild(canvas);
// Save a drawing context into the map variable
const map = canvas.getContext('2d');
// Get the data from a json and draw it
fetch('world.json')
.then(response => response.json())
.then(drawGeoJson);
/**
* Draw a geoJson object, it only supports polygons and MultiPolygons
*/
function drawGeoJson(geoJsonData) {
geoJsonData.features.forEach(feature => {
if (feature.geometry.type === 'Polygon') {
drawPolygon(map, feature.geometry.coordinates[0]);
}
if (feature.geometry.type === 'MultiPolygon') {
feature.geometry.coordinates.forEach(coords => drawPolygon(map, coords[0]));
}
});
}
/**
* Given a list of coordinates, draw into a rendering context a polygon.
*/
function drawPolygon(ctx, coords) {
ctx.fillStyle = getColor();
ctx.beginPath();
const initialPoint = project(coords.shift());
ctx.moveTo(initialPoint.x, initialPoint.y);
coords.map(project).forEach(point => ctx.lineTo(point.x, point.y));
ctx.closePath();
ctx.fill();
}
/**
* Webmercator projection.
* Since D === MAP_SIZE this function already returns pixel coordinates in the canvas.
*/
function project([lon, lat]) {
const sinlat = Math.sin(lat * Math.PI / 180.0);
const x = D * lon / 360.0;
const y = R / 2 * Math.log((1 + sinlat) / (1 - sinlat));
return { x: (D / 2 + x), y: (D - (D / 2 + y)) }
}
/**
* Generate a color
*/
function getColor() {
return `rgb(${i++ % 255}, ${180}, ${255})`;
}
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment