两个d3映射使用点击事件

时间:2017-02-24 23:14:56

标签: javascript d3.js

我正在使用d3创建一个交互式地图,使用json文件来创建边界但我停在我需要显示一个图层的位置将是首都城市,当点击它时将创建另一个图层 对于较小的城市, 由于所有数据都在一个json文件中,但是我们可以知道name_1 == name_2那么它是一个首都(第1层),否则只有在点击第1层时才会出现较小的城市(第2层)

这是我的代码同时显示第1层和第2层

//Width and height
var width = 600,
height = 600

var color = d3.scaleLinear()
.range(["rgb(254,224,210)","rgb(252,146,114)","rgb(222,45,38)"]);

//Define map projection //projection 
var projection = d3.geoMercator()
                   .translate([0, 0])
                   .scale(1);

//Define path generator
var path = d3.geoPath()
             .projection(projection);

//Create SVG element
var svg = d3.select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height);

svg.append("rect")
  .attr("class", "background")
  .attr("width", width)
  .attr("height", height)
  .on("click", clicked);

var g = svg.append("g");// <g> element is used to group SVG shapes together

//Load in GeoJSON data
d3.json("JOR_layer3.json", function(error,json) {//jordan.geo
if (error) throw error;

// Calculate bounding box transforms for entire collection
var b = path.bounds( json ),
s = 0.95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

console.log (json.features);

json.features.forEach(function (d) {
  console.log (d.properties.NAME_1);
})

// Update the projection    
projection
  .scale(s)
  .translate(t);

//Bind data and create one path per GeoJSON feature
g.append("g")
.attr("id", "city-polygon")
.selectAll("path")
   .data(json.features)
   .enter()
   .append("path")
   .attr("d", path)                   
   .style("fill", function (d, i) { //console.log (d);
    return color(i);})
   /*.style('stroke', 'white')
   .style('stroke-width', 0.7);*/
   .on("click", clicked);                   

g.selectAll(".city-name")
  .data(json.features)
  .enter()
  .append("text")
  .attr("class", "city")
  .attr("transform", function(d) {
    var centroid = path.centroid(d),
      x = centroid[0],
      y = centroid[1];
      return "translate(" + x + "," + y + ")";
        // + "scale(1)"
        // + "translate(" + -x + "," + -y + ")";
  })
  .attr('text-anchor', 'middle')
  .text (function (d) { return d.properties.NAME_2; });   
});

function clicked(d) {
  var x, y, k;

  if (d && centered !== d) {
    var centroid = path.centroid(d);
    x = centroid[0];
    y = centroid[1];
    k = 4;
    centered = d;
  } else {
    x = width / 2;
    y = height / 2;
    k = 1;
    centered = null;
  }

  g.selectAll("#path")
      .classed("active", centered && function(d) { return d === centered; });

  g.transition()
  .duration(750)
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
  .style("stroke-width", 1.5 / k + "px");
}

和json文件的样本

{"type":"FeatureCollection","bbox":[34.95763778686535,29.18587875366211,39.30208587646493,33.36817169189466],
"features":[{"type":"Feature","properties":{"ID_0":116,"ISO":"JOR","NAME_0":"Jordan","ID_1":1,"NAME_1":"Ajlun","ID_2":1,"NAME_2":"Ajlun",
"HASC_2":"JO.AJ.AJ","CCN_2":0,"CCA_2":null,"TYPE_2":"Nahia","ENGTYPE_2":"Sub-Province","NL_NAME_2":null,"VARNAME_2":"Ajlun"},
"geometry":{"type":"Polygon","coordinates":[[[35.709953308105526,32.38688278198248],[35.7218132019043,32.38408279418957],[35.737407684326115,32.38139343261719],
[35.740989685058594,32.380111694335994],[35.7465705871582,32.376800537109375],[35.706249237060604,32.372310638427734],[35.709953308105526,32.38688278198248]]]}},"type":"Feature","properties":{"ID_0":116,"ISO":"JOR","NAME_0":"Jordan","ID_1":1,"NAME_1":"Ajlun","ID_2":2,"NAME_2":"Kofranjah",
"HASC_2":"JO.AJ.KF","CCN_2":0,"CCA_2":null,"TYPE_2":"Nahia","ENGTYPE_2":"Sub-Province","NL_NAME_2":null,"VARNAME_2":null},
"geometry":{"type":"Polygon","coordinates":[[[35.74267196655279,32.16957473754883],[35.733383178710994,32.174312591552734],
[35.72740554809576,32.17792892456055],[35.72211837768566,32.181858062744254],[35.754566192626896,32.18144989013672],[35.74267196655279,32.16957473754883]]]}}]}

1 个答案:

答案 0 :(得分:1)

如果我理解正确,您的问题需要解决此声明:

  

我需要显示一个层......首都城市以及何时点击它   将为较小的城市创建另一个图层

上下文是:

  

所有数据都在一个json文件中

对于这个答案,我不打算在点击时放大每个区域,因为问题是关于根据点击显示数据。我也在使用d3 v4,它可以让您更轻松地fitExtent方法自动翻译和缩放地图 - 我建议你看看它。在这种情况下,我只是使用手动定义的投影,以便更简单,更清晰地演示。

对于这个问题,一种方法似乎最简单自然:立即绘制所有功能但隐藏一些数据,以便稍后切换:

因此,对于您的数据,这可能如下所示:

g.selectAll(".primary-city")
  .data(jordan.features)
  .enter()
  .filter(function(d) { return d.properties.name_1 == d.properties.name_2 })
  .append("text")
  .attr("class", "primary-city")
  .attr("transform", function(d) { return 'translate('+path.centroid(d)+')'; })
  .attr('y',-10)
  .attr('text-anchor', 'middle')
  .text (function (d) { console.log(d); return d.properties.name_2; });   

g.selectAll(".secondary-city")
  .data(jordan.features)
  .enter()
  .filter(function(d) { return d.properties.name_1 != d.properties.name_2 })
  .append("text")
  .attr("class", "secondary-city")
  .attr("transform", function(d) { return 'translate('+path.centroid(d)+')'; })
  .attr('y',-10)
  .attr('opacity',0)
  .attr('pointer-events','none')
  .attr('text-anchor', 'middle')
  .text (function (d) { console.log(d); return d.properties.name_2; }); 

上面的代码会将您的geojson分成两个不同的层[&#39;按类名分隔。二级城市&#39;绘制名称时将隐藏名称(不透明度= 0)。

现在你需要的是让click事件调用一个函数:

var clicked = false;

function click() {
    clicked = !clicked;
    if (clicked == true) {
        g.selectAll(".secondary-city")
            .transition()
            .attr('opacity',1)
            .duration(400); 
    }
    else {
        g.selectAll(".secondary-city")
            .transition()
            .attr('opacity',0)
            .duration(400); 
    }
}

这完全是什么样的?好吧,我已经整理了一个bl.ock,所以你可以看到here(我认为使用相同的数据源。此外,你必须点击乔丹的一个功能来触发它)。如果您希望将点击分配给特定的地理要素,则可以采用与过滤中的文本类似的路径方法,并使用类进行区分。