Javascript d3.path仅绘制特征集合的第一个特征

Javascript d3.path仅绘制特征集合的第一个特征,javascript,d3.js,Javascript,D3.js,我正试图绘制一张英国地图,并在上面绘制一些选定的点。 我将学习本教程的第一部分 以下是我所做的 var svg = d3.select('body').append('svg') .attr('height', height) .attr('width', width) .call(zoom); d3.json("/data/uk.json", function(error, uk) { if (error) return console.error(error); var su

我正试图绘制一张英国地图,并在上面绘制一些选定的点。 我将学习本教程的第一部分

以下是我所做的

var svg = d3.select('body').append('svg')
.attr('height', height)
.attr('width', width)
.call(zoom);

d3.json("/data/uk.json", function(error, uk) {

   if (error) return console.error(error);

  var subunits = topojson.feature(uk, uk.objects.subunits);
  var projection = d3.geo.albers()
                 .center([0, 55.4])
                 .rotate([4.4, 0])
                 .parallels([50, 60])
                 .scale(6000)
                 .translate([width / 2, height / 2]);

var path = d3.geo.path()
          .projection(projection);
svg.append('path')
         .datum(subunits)
         .attr('d', path);

svg.selectAll('.subunit')
    .data(topojson.feature(uk, uk.objects.subunits).features)
    .enter().append('path')
    .attr('d', path);
这里是我试图绘制点的部分

d3.json('/data/places.json',  function (error , result) {

    if(error)
      console.error(error);

    svg.append('path')
              .data(result.features)
              .style('stroke', 'green')
              .attr('d' , d3.geo.path().projection(projection))
  });

上面的代码只在地图上绘制了一个点,即JSON文件中的第一个点

svg.append('path')
   .data(result.features)
   .style('stroke', 'green')
   .attr('d' , d3.geo.path().projection(projection))
这将附加一个路径,将
result.features的第一个元素绑定到此路径,并相应地设置样式和属性

要按照您想要的方式工作,您需要利用D3的机制

svg.selectAll('path.features')
   .data(result.features)
  .enter().append('path')
    .attr('class', 'feature')
    .style('stroke', 'green')
    .attr('d' , d3.geo.path().projection(projection))
这将为
result.features
中的功能计算a,将新元素放入enter选择中,可通过调用seletion来访问该选择。使用此输入选择,您现在可以为所有要素附加路径


另一个与您的问题没有直接关系的旁注: 根据要附加到地图的要素数量,可能会经常调用
.attr(“d”)
setter。您可以通过重用路径生成器的一个实例来提高性能:

var geoPath = d3.geo.path().projection(projection);  // You need just one instance

svg.selectAll('path.features')
   .data(result.features)
  .enter().append('path')
    .attr('class', 'feature')
    .style('stroke', 'green')
    .attr('d' , geoPath)                             // Re-use the path generator

这被认为是最佳实践,应该普遍采用。

使用时未正确绑定功能数据

svg.append('path')
   .data(result.features)
   .style('stroke', 'green')
   .attr('d' , d3.geo.path().projection(projection))
这将附加一个路径,将
result.features的第一个元素绑定到此路径,并相应地设置样式和属性

要按照您想要的方式工作,您需要利用D3的机制

svg.selectAll('path.features')
   .data(result.features)
  .enter().append('path')
    .attr('class', 'feature')
    .style('stroke', 'green')
    .attr('d' , d3.geo.path().projection(projection))
这将为
result.features
中的功能计算a,将新元素放入enter选择中,可通过调用seletion来访问该选择。使用此输入选择,您现在可以为所有要素附加路径


另一个与您的问题没有直接关系的旁注: 根据要附加到地图的要素数量,可能会经常调用
.attr(“d”)
setter。您可以通过重用路径生成器的一个实例来提高性能:

var geoPath = d3.geo.path().projection(projection);  // You need just one instance

svg.selectAll('path.features')
   .data(result.features)
  .enter().append('path')
    .attr('class', 'feature')
    .style('stroke', 'green')
    .attr('d' , geoPath)                             // Re-use the path generator

这被认为是最佳实践,应该普遍采用。

它奏效了,谢谢。你能告诉我这里发生了什么事吗?我认为必须向d3.geo.path()传递它必须为其创建路径的数据元素。为什么我们要明确提到投影呢?调用
d3.geo.path()
将生成一个路径生成器,它根据GeoJSON geomety特性计算SVG元素的屏幕坐标。为了实现这一点,您显然必须同时传入投影和包含GeoJSON特性的数据。前者是通过在路径生成器上调用“.projection()”来完成的,后者则由D3数据绑定的内部魔法来完成。要理解数据绑定是如何工作的,请开始阅读我的答案中包含的链接。@ AITITAARAMANI另一个提示:考虑重用路径生成器,这将提高性能。我已经更新了我的答案,以涵盖这一点。它的工作,谢谢。你能告诉我这里发生了什么事吗?我认为必须向d3.geo.path()传递它必须为其创建路径的数据元素。为什么我们要明确提到投影呢?调用
d3.geo.path()
将生成一个路径生成器,它根据GeoJSON geomety特性计算SVG元素的屏幕坐标。为了实现这一点,您显然必须同时传入投影和包含GeoJSON特性的数据。前者是通过在路径生成器上调用“.projection()”来完成的,后者则由D3数据绑定的内部魔法来完成。要理解数据绑定是如何工作的,请开始阅读我的答案中包含的链接。@ AITITAARAMANI另一个提示:考虑重用路径生成器,这将提高性能。我已经更新了我的答案以涵盖这一点。