this example shows how d3.js can help you with GeoJSON antimeridian cutting and use it in leaflet or other mapping service
Last active
October 30, 2018 19:01
-
-
Save strangerintheq/c28bfb385d9b6e5db7aa428815113099 to your computer and use it in GitHub Desktop.
d3 // antimeridian cuttted GeoJSON // leaflet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 | |
height: 500 | |
scrolling: no | |
border: yes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="https://d3js.org/d3.v5.min.js"></script> | |
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> | |
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"/> | |
</head> | |
<body style="margin: 0"> | |
<svg style="display: inline-block"></svg> | |
<div id="map" style="display: inline-block; width: 550px; height: 450px"></div> | |
<script> | |
var tileLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png'); | |
var map = L.map('map').setView([0,0], 0).addLayer(tileLayer); | |
var bounds = [400, 450]; | |
var colorGenerator = d3.scaleOrdinal(d3.schemeCategory10); | |
var projection = d3.geoMercator().translate([bounds[0] / 2, bounds[1] / 2]).scale(70); | |
var geoPath = d3.geoPath().projection(projection); | |
var geoCircle = d3.geoCircle(); | |
var svg = d3.select('svg') | |
.attr("width", bounds[0]) | |
.attr("height", bounds[1]) | |
.attr("viewbox", "0 0 " + bounds[0] + " " + bounds[1]) | |
.append('g'); | |
svg.append("g") | |
.append("path") | |
.datum(d3.geoGraticule()) | |
.attr("stroke", "gray") | |
.attr('d', geoPath); | |
function addCircle(center, radius, color) { | |
var g = svg.append("g"); | |
var drag = d3.drag().on("drag", dragged); | |
var xy = projection(center); | |
var path = g.append("path") | |
.datum({ | |
type: "Polygon", | |
coordinates: [[]], | |
x: xy[0], | |
y: xy[1] | |
}) | |
.classed("zone", "true") | |
.attr("fill", color) | |
.attr("stroke", color) | |
.attr("fill-opacity", 0.3) | |
.call(drag); | |
update(path.datum()); | |
function dragged(d) { | |
g.raise(); | |
d.x = d3.event.x; | |
d.y = d3.event.y; | |
update(d) | |
} | |
function update(d) { | |
center = projection.invert([d.x, d.y]); | |
var poly = geoCircle.center(center).radius(radius)(); | |
d.coordinates[0] = poly.coordinates[0]; | |
path.attr('d', geoPath); | |
d.geojson && d.geojson.remove(); | |
d.geojson = L.geoJSON(unproject(path.attr('d')), { | |
color: color, | |
}).addTo(map); | |
} | |
function unproject(d) { | |
var features = d.toLowerCase().split('z').join('').split('m'); | |
features.shift(); | |
var coords = features.map(function (feature) { | |
return feature.split('l').map(function (pt) { | |
var xy = pt.split(','); | |
return projection.invert([+xy[0], +xy[1]]); | |
}); | |
}); | |
return { | |
type: 'MultiPolygon', | |
coordinates: [coords] | |
} | |
} | |
} | |
d3.range(0, 4).forEach(function (i) { | |
addCircle([-120 + i * 60, 0], i * 10 + 10, colorGenerator(i)); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment