Paint the apartment and the town of different colors in d3.js

一个人想着一个人 提交于 2020-01-05 03:35:15

问题


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:

  1. Color all municipalities that share a department a certain color
  2. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!