问题
I'm working with a variation of Bostock's Quantile Choropleth.
I've have successfully scaled the projection and integrated my own data. I am also currently filtering the json counties data to only include county ids starting with the state id of 48.
It all works perfectly, however, I still need to apply the .mesh function to combine the arcs between bordering counties. Otherwise, when I add a hover affect I get strangely uneven borders.
I tried replacing the data call with a datum(mesh) call instead (see the commented out line below) but it did not work.
Here is my working code:
function ready(error, us) {
if (error) throw error;
//define the feature of the states from the topojson file, then filter so only state 48 (texas) shows
var states = topojson.feature(us, us.objects.states),
state = states.features.filter(function(d) { return d.id === 48; })[0];
//define the features for the counties and filter based on number (starting with 48)
var counties = topojson.feature(us, us.objects.counties),
mycounties = counties.features.filter(function(d) { if(d.id >= 48000 && d.id <=49000) return d.id; });
//initiate the class for the state, and add an outline path
svg.append("path")
.datum(state)
.attr("class", "outline")
.attr("d", path);
//initiate the g object for the counties
svg.append("g")
.attr("class", "counties")
.selectAll("path")
//.datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b; }))
// ^I tried adding this to replace the following line, but it does not work
.data(mycounties)
.enter().append("path")
.attr("fill", function(d) { return color(d.establishments = centralTexas.get(d.id)); })
.attr("d", path)
.append("title")
.text(function(d) { var obj2 = jsonCounties[d.id]; if (typeof obj2 != "undefined") {return obj2.countyName + ": " + d.establishments + " Active Establishments";} });
}
How should I be going about this? Is it possible to do a more complicated filter query inside the .mesh function and totally eliminate the need for my
var counties = topojson.feature(us, us.objects.counties), mycounties = counties.features.filter(function(d) { if(d.id >= 48000 && d.id <=49000) return d.id; });
code?
Or do I need to run the mesh function on that variable with a different syntax?
回答1:
Assuming I understand your ultimate goal is to get even borders of a hovered feature:
Using datum.append(mesh) won't append areas - a mesh "Returns the GeoJSON MultiLineString geometry object representing the mesh for the specified object in the given topology." API documentation. Also, using .append().datum()
would append one feature - hover effects on individual counties would be lost - there are not data bound to features, just one datum bound to one feature. Lastly, the mesh can have odd fill patterns too (see this question). But, a mesh is unnecessary to get modified borders on hover that display as intended.
While the topojson removes identical arcs, every shared arc is represented at least twice in the geojson - but as they are identical they are overlain directly on top of each other. The layering is relative to the order in which the features are imported.
If a boundary is expanded on hover it may fall behind some (or all or none) of the neighboring features because of how the features are layered. This creates odd outline patterns by essentially clipping the feature's outline. This means that only some changes to a county/feature may be visible, depending on feature/element layering.
Try modifying the hover function with d3.select(this).raise()
(new in v4) or use
node.parentNode.appendChild(node);
(v3, where node is the DOM element, not the d3 selection), these will move a feature to the top of the svg (as though they were appended last) - which will allow you to show a feature with edge styling that is not partly covered by any other feature.
See this example using your referenced block (I've placed the state outlines in the same parent node so that raising the hovered county raises the edge above the state boundary too. On mouse out I lower the feature so that the state boundaries are unaffected.
来源:https://stackoverflow.com/questions/47316361/how-to-apply-a-filter-and-mesh-to-a-d3-choropleth