Uses geoVoronoi.find()
to highlight the nearest site to the selected (spherical) point.
See also a planar voronoi.find()
.
xxxxxxxxxx
<meta charset="utf-8">
<style>
.polygons {
fill: #f4f4f4;
stroke: #000;
}
.polygons.found {
fill: #f00;
}
.sites {
fill: #000;
stroke: #fff;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="d3-geo-voronoi.min.js"></script>
<script>
var svg = d3.select("svg").on("touchmove mousemove", moved),
width = +svg.attr("width"),
height = +svg.attr("height");
var sites = d3.range(500)
.map(function(d) { return [Math.random() * 360, Math.random() * 90 - Math.random() * 90 ]; });
var projection = d3.geoOrthographic();
var path = d3.geoPath()
.projection(projection);
var diagram = d3.geoVoronoi()(sites);
var polygon = svg.append("g")
.attr("class", "polygons")
.selectAll("path")
.data(diagram.polygons().features)
.enter().append("path")
.attr("d", path);
// this is a variant of diagram.find()
// that colors the intermediate steps
diagram.xfind = function(x, y, radius) {
var features = diagram.polygons().features;
// optimization: start from most recent result
var i, next = diagram.find.found || 0;
var cell = features[next] || features[next=0];
var dist = d3.geoLength({
type: 'LineString',
coordinates: [[x,y], cell.properties.sitecoordinates]
});
do {
cell = features[i=next];
next = null;
polygon._groups[0][i].setAttribute('fill', '#f5a61d');
cell.properties.neighbours.forEach(function(e) {
if (polygon._groups[0][e].getAttribute('fill') != '#f5a61d')
polygon._groups[0][e].setAttribute('fill', '#fbe8ab');
var ndist = d3.geoLength({
type: 'LineString',
coordinates: [[x,y], features[e].properties.sitecoordinates]
});
if (ndist < dist){
dist = ndist;
next = e;
return;
}
});
} while (next !== null);
diagram.find.found = i;
if (!radius || dist < radius * radius) return cell.properties.site;
}
findcell(projection.invert([width/2, height/2]));
function moved() {
findcell(projection.invert(d3.mouse(this)));
}
if (this.remove_if_you_dont_mind_being_seasick)
d3.interval(function(el){
projection.rotate([el/200, 10 * Math.sin(el/1000)]);
redraw()
},60);
function findcell(m) {
polygon.attr('fill', '');
var found = diagram.xfind(m[0],m[1], 50);
if (found)
polygon._groups[0][found.index].setAttribute('fill', 'red');
}
function redraw() {
polygon = polygon.data(diagram.polygons()).attr("d", path);
}
</script>
https://d3js.org/d3.v4.js