D3 TOPOJSON地图加载后如何运行功能

时间:2017-01-30 03:27:06

标签: javascript d3.js svg geojson topojson

我正在尝试运行一个功能,根据数据调整TOPOJSON D3地图的各个状态。

但是,该功能在状态加载/出现在SVG之前一直运行。构建映射的函数在文档就绪函数中调用。我已经尝试向状态添加一个事件监听器,一个.on属性调用应该遮蔽状态的函数并使用了window.load。但是,在状态出现在屏幕上之前,阴影状态的函数一直在运行,因此在尝试按ID查找每个状态时返回NULL值

.background {
  fill: none;
  pointer-events: all;
}

#states {
  fill: #aaa;
}

#states .active {
  fill: orange;
}

#state-borders {
  fill: none;
  stroke: #fff;
  stroke-width: 1.5px;
  stroke-linejoin: round;
  stroke-linecap: round;
  pointer-events: none;
}

</style>

<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
function buildmap(){
var width = 960,
    height = 500,
    centered;

var projection = d3.geo.albersUsa()
    .scale(1070)
    .translate([width / 2, height / 2]);

var path = d3.geo.path()
    .projection(projection);

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");

d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
  if (error) throw error;

  g.append("g")
      .attr("id", "states")
    .selectAll("path")
      .data(topojson.feature(us, us.objects.states).features)
    .enter().append("path")
      .attr("d", path);

  g.append("path")
      .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
      .attr("id", "state-borders")
      .attr("d", path);
});
};

function colorstates(){
   var mainstate = document.getElementById("texas")
   mainstate.style.fill="blue"
}



 $(document).ready(function((){
      buildmap()
      colorstates() //I have also used window.load and adding .on attribute to svg/d3

1 个答案:

答案 0 :(得分:3)

d3.json是异步的。这意味着它之后的所有代码都将立即运行 ,即代码不会等待 d3.json完成。

使用$(document).ready()window.load不会产生任何影响。只有在d3.json获取文件(btw,一个大文件)并绘制SVG后,路径才会出现在DOM中。因此,您必须等待d3.json完成,以便您可以选择这些路径。

解决方案:在d3.json

的底部调用您的函数
d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
    if (error) throw error;

    g.append("g")
        .attr("id", "states")
        .selectAll("path")
        .data(topojson.feature(us, us.objects.states).features)
        .enter().append("path")
        .attr("d", path);

    g.append("path")
        .datum(topojson.mesh(us, us.objects.states, function(a, b) {
            return a !== b;
        }))
        .attr("id", "state-borders")
        .attr("d", path);

    //calling colorstates inside d3.json
    colorstates() 

    function colorstates() {
        var mainstate = document.getElementById("texas")
        mainstate.style.fill = "blue"
    }

});

这样,当您调用colorstates函数时,元素就会出现。

编辑:要按ID选择状态(即路径),您必须设置路径&#39; ID首先(现在,他们没有ID):

g.append("path")
    .datum(topojson.mesh(us, us.objects.states, function(a, b) {
        return a !== b;
    }))
    .attr("id", d => "state" + d.id)
    .attr("d", path);

topoJSON中,d.id是数字,您无法通过数字开始ID(这就是我使用"state" + d.id的原因)。德州&#39; id是48。

以下是您的代码:https://bl.ocks.org/anonymous/b2114787193d018fc094763a92872333

PS:您不需要在D3代码中使用document.getElementById。您会发现使用D3选择器更容易,更通用。

PS2:你的州边界应该有&#34;州边界&#34;作为class而不是id不能具有相同的ID,用于不同的元素。 ID是唯一的。