D3 V6 and JavaScript - GeoJSON fill is "spilling" outside of path

Viewed 458

Creating a map using D3 V6, showing educational attainment by county. I have a counties.topojson and csvData.csv which are loaded:

var promises = [];
promises.push(d3.csv("data/csvData.csv")); //load attributes from csv
promises.push(d3.json("data/counties.topojson")); //load background spatial data

Promise.all(promises).then(callback);

and in a callback function assigned to variables csvData and counties. The counties are then translated using:

miCounties = topojson.feature(counties, counties.objects.collection).features;

The csvData is joined to the county data, and the join is confirmed in console.log(joinedCounties), within the callback function setEnumerationUnits() is called (where colorScale is quantile scale based on an array created from the csvData and map is the SVG element:

function setEnumerationUnits(joinedCounties,map,path,colorScale){
var counties = map.selectAll(".counties")
    .data(joinedCounties)
    .enter()
    .append("path")
    .attr("class", function(d){
        return "counties " + d.properties.NAME;
    })
    .attr("d", path)
    .style("fill", function(d) {
        return choropleth(d.properties, colorScale);
     })

I should also mention adding "fill" to the .counties class in CSS also creates the "spilling". I have checked the topojson in QGIS and Pro, which both appear normal. I have also tried a second source of data with the same results. Here is the result:

image of faulted map

Here is what is looks like without styling, no fill, just stroke defined in CSS:

counties without styling or fill

I receive no errors in the console. I appreciate any help anyone can give! Thanks!

Thank you! The turf.rewind worked!!

here's what I added to make it work (after installing turf library):

        miCounties.forEach(function(feature){
        feature.geometry = turf.rewind(feature.geometry, {reverse:true});
1 Answers

One or more of your GeoJSON entries are the wrong way around. The values are correct, but they are in the wrong order. d3-geo generally expects GeoJSON features to be clockwise:

Spherical polygons also require a winding order convention to determine which side of the polygon is the inside: the exterior ring for polygons smaller than a hemisphere must be clockwise, while the exterior ring for polygons larger than a hemisphere must be anticlockwise.

You can fix the winding of your data using a plugin or tool like turf, which you can use to "rewind" your shapes - though you should use the reverse: true option.

Related