When creating many geographic circles (e.g. for visualizing graduating radii on a map), calling d3.geo.circle multiple times will create overlapping great circles, which may not be desired.
Here we simply subtract out the smaller great circles from the bigger ones, adding them as holes to the GeoJSON Polygon object. Note: The holes must be in reverse order to the great circle.
Compare with Overlapping Geographic Circles.
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
background: #fcfcfa;
}
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill {
fill: #fff;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: #222;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script>
var width = 960,
height = 500;
var projection = d3.geo.naturalEarth()
.scale(167)
.translate([width / 2, height / 2])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path);
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
var circleWithAngle = (function() {
var circle = d3.geo.circle();
return function (angle) {
return circle.angle(angle)();
};
})();
var createNonOverlappingCircles = function(angles) {
var circles = [];
circles.push(circleWithAngle(angles[0]));
for (var i = 1; i < angles.length; i++) {
var circleGeo = circleWithAngle(angles[i]), // Generate a circle with the given angle
holeCircleGeo = circleWithAngle(angles[i - 1]); // And a circle with a previous angle
// Holes in GeoJSON Polygons are specified in the coordinates array in the 1 to nth index in reverse winding order
circleGeo.coordinates.push(holeCircleGeo.coordinates[0].reverse());
circles.push(circleGeo);
}
console.log(circles, "YUP");
return circles;
};
var circleAngles = [30, 50, 80, 120];
var circles = createNonOverlappingCircles(circleAngles);
var category = d3.scale.category10();
d3.json("/../../data/world-50m.json", function(error, world) {
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
svg.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "boundary")
.attr("d", path);
svg.selectAll("path.circle")
.data(circles)
.enter().append("path")
.attr("class", "circle")
.attr("d", path)
.style("fill", function(d, i) { return category(i); })
.style("opacity", 0.3);
});
d3.select(self.frameElement).style("height", height + "px");
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://d3js.org/d3.geo.projection.v0.min.js to a secure url
Modified http://d3js.org/topojson.v1.min.js to a secure url
Changed /mbostock/raw/4090846/world-50m.json to a local referenece
https://d3js.org/d3.v3.min.js
https://d3js.org/d3.geo.projection.v0.min.js
https://d3js.org/topojson.v1.min.js