问题
I have a map, departments and municipalities. The departments are delimited by the red lines. I want when I mouse over the municipality, in addition to painting this municipality, also painted the department of another color.
var width = 900,
height = 900;
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("https://cdn.rawgit.com/finiterank/mapa-colombia-js/9ae3e4e6/colombia-municipios.json", function(error, co) {
var subunits = topojson.feature(co, co.objects.mpios);
var projection = d3.geo.mercator()
.scale(2000)
.translate([width / 2, height / 2])
.center([-61,43])
.rotate([2,3,2]);
var path = d3.geo.path()
.projection(projection);
svg.append("path")
.datum(subunits)
.attr("d", path);
//departments
svg.selectAll(".dpto")
.data(topojson.feature(co, co.objects.depts).features)
.enter().append("path")
.on('mouseover', mouseoverDep )
.on('mouseout',mouseoutDep)
.attr("class", function(d) { return "depts " + "_" + d.id; })
.attr("d", path)
svg.append("path")
.datum(topojson.mesh(co, co.objects.depts, function(a, b) { return true; }))
.attr("d", path)
.attr("class", "depto-borde");
//municipalities
svg.selectAll(".mpio")
.data(topojson.feature(co, co.objects.mpios).features)
.enter().append("path")
.on('mouseover', mouseoverMun )
.on('mouseout',mouseoutMun)
.attr("class", function(d) { return "mpio " + "_" + d.id; })
.attr("d", path)
svg.append("path")
.datum(topojson.mesh(co, co.objects.mpios, function(a, b) { return a !== b; }))
.attr("d", path)
.attr("class", "mpio-borde")
})
function mouseoverMun(d){
d3.select(this).style("fill","orange");
div.style("opacity", .9)
.html(d.properties.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
document.getElementById("department").innerHTML=d.properties.dpt
}
function mouseoutMun() {
d3.select(this).style("fill","#777");
div.style("opacity",0);
document.getElementById("department").innerHTML='';
}
function mouseoverDep(d){
d3.select(this).style("fill","blue");
div.style("opacity", .9)
.html(d.properties.dpt)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
document.getElementById("department").innerHTML=d.properties.dpt
}
function mouseoutDep(d){
d3.select(this).style("fill","#777");
div.style("opacity",0);
document.getElementById("department").innerHTML='';
}
http://jsfiddle.net/ctqhd851/
回答1:
You have set up two mouseover events for two different and entirely overlapping layers, but the mouseover (and mouseoff) events will only trigger for the topmost layer. So, you can instead achieve this effect with the mouseover only on the municipality layer.
As the municipality layer has a department property you want to:
- Color all municipalities that share a department a certain color
- Color the specific municipality that the mouse is over a second color
For number 1, you can achieve one easily if you give a class to each municipality that is its department's name (you could also apply a filter and update some of the features). I changed where you set the class of your municipality features to this:
.attr("class", function(d) { return "mpio " + "_" + d.id + " " + d.properties.dpt})
Then I added some code in the mouseover event for municipalities:
d3.selectAll("."+d.properties.dpt)
.style("fill","steelblue")
This will select every municipality in a given department, and set its color to blue.
For number 2:
In relation to the individual municipality that the mouse is hovering on, nothing changes from what you have really, you just want to apply that style after you set the department's municipalities to show one color (so you don't overwrite the change when coloring each municipality in the department).
The mouseout event just needs to remove the styles we've added by giving a fill of none to all the municipalities. As we only modified municipalities, we can select every municipality and set the fill to none.
Here's a snippet showing mouseover effects that highlight department and municipality.
Note that I took out the meshes that you were using, and instead applied the formatting of the edges to the polygons themselves
var width = 900,
height = 900;
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("https://cdn.rawgit.com/finiterank/mapa-colombia-js/9ae3e4e6/colombia-municipios.json", function(error, co) {
var subunits = topojson.feature(co, co.objects.mpios);
var projection = d3.geo.mercator()
.scale(2000)
.translate([width / 2, height / 2])
.center([-61,43])
.rotate([2,3,2]);
var path = d3.geo.path()
.projection(projection);
svg.append("path")
.datum(subunits)
.attr("d", path);
//departments
svg.selectAll(".dpto")
.data(topojson.feature(co, co.objects.depts).features)
.enter().append("path")
.attr("class", function(d) { return "depts " + "_" + d.id; })
.attr("d", path)
//municipalities
svg.selectAll(".mpio")
.data(topojson.feature(co, co.objects.mpios).features)
.enter().append("path")
.on('mouseover', mouseoverMun )
.on('mouseout',mouseoutMun)
.attr("class", function(d) { return "mpio " + "_" + d.id + " " + d.properties.dpt})
.attr("d", path)
})
function mouseoverMun(d){
// Turn the department blue
d3.selectAll("."+d.properties.dpt)
.style("fill","steelblue")
// Turn the municipality orange
d3.select(this).style("fill","orange");
// Show a tooltip
div.style("opacity", .9)
.html(d.properties.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
}
function mouseoutMun() {
d3.selectAll(".mpio").style("fill","none");
div.style("opacity",0);
}
path {
fill: #777;
}
.mpio {
fill: none;
stroke: #fff;
stroke-opacity: .25;
stroke-width: .5px;
pointer-events: all;
}
.depts {
fill: none;
stroke: #ff0000;
stroke-linejoin: round;
stroke-width: 1;
opacity: 1;
}
div.tooltip {
position: absolute;
text-align: center;
width: 100px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: white;
border-radius: 8px;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
来源:https://stackoverflow.com/questions/44640313/paint-the-apartment-and-the-town-of-different-colors-in-d3-js