在d3.geo MultiPoint中如何为不同的点提供不同的形状?

时间:2014-03-20 09:48:40

标签: d3.js geo

我有一些使用d3.geo绘制的geoJson数据。

当我写

之类的东西时
d3.select("svg")
   ... 
   .attr("d", function(d) {
                return path({
                    type:"MultiPoint",
                    coordinates: get_activity_coords_(d.activities)
                });
   })

我总是为每个坐标得到一个圆圈。坐标表示旅程的各个停靠点的位置。我更喜欢的是第一个和最后一个坐标的不同形状。

是否可以使用MultiPoint执行此操作,是否有可以遵循的示例?我可以逐一绘制点,但我记得读到MultiPoint要快得多。此外,代码将更清晰易读。

非常感谢。

1 个答案:

答案 0 :(得分:3)

对于d3.geo.path的MultiPoint geoJSON,您不能使用不同的形状。您可以change the radius based on a function,但看起来您只能按功能而不是进行设置,因此您必须打破自己的设置指向多个功能并使用单个元素失去任何性能优势。

但是,还有其他方法可以做到这一点。

正如您所提到的,一个选项是为每个点创建一个单独的<path>元素的嵌套选择,并使用d3.svg.symbol()函数绘制每个路径。然后,您可以根据数据或索引自定义符号功能。

var trips = d3.select("svg").selectAll("g.trips")
               .data(/*The data you were currently using for each path,
                       now gets to a group of paths */)
               .attr("class", "trips"); 
               //also set any other properties for the each trip as a whole

var pointSymbol = d3.svg.symbol().type(function(d,i){
                    if (i === 0) 
                        //this is the first point within its groups
                        return "cross";
                    if ( this === this.parentNode.querySelector("path:last-of-type") )
                        //this is the last point within its group
                        return "square";
                    //else:
                    return "circle";
               });


var points = trips.selectAll("path")
               .data(function(d) {
                   return get_activity_coords_(d.activities);
                   //return the array of point objects
                })
               .attr("transform", function(d){ 
                         /* calculate the position of the point using 
                            your projection function directly */
                })
               .attr("d", pointSymbol);

另一个选项允许您为第一个和最后一个点设置自定义形状(但所有中间点都相同)是将这些点连接为单个不可见<path>的顶点元素并使用line markers绘制点符号

你的方法是:

  1. 在SVG中创建<defs>元素(硬编码或动态d3),并在其中定义开始,中间和结束标记点。 (您可以使用d3.svg.symbol()功能绘制路径,或制作自己的路径,或使用图像,它取决于您。)

  2. 使用d3.svg.line()功能创建路径&#34; d&#34;属性基于您的点坐标数组;线的x和y存取器函数应使用您用于地图的投影函数从该点的坐标获取x / y位置。为避免计算两次投影,可以将投影坐标保存在数据对象中:

     var multipointLine = d3.svg.line()
                          .x(function(d,i) {
                              d.projectedCoords = projection(d);
                              return d.projectedCoords[0];
                            })
                          .y(function(d){ return d.projectedCoords[1];});
    

    (您无法使用d3.geo.path()函数将线条绘制为地图要素,因为它会将线条划分为曲线以匹配地图投影中经度和纬度线条的曲线;让线标记起作用,路径只需要点之间的简单直线连接。)

  3. 将该路径上的样式设置为无笔画和无填充,因此该行本身不会显示,但随后设置marker-startmarker-mid和{{行上的1}}属性,用于引用正确标记元素的id值。

  4. 为了帮助您入门,以下是使用d3动态生成线标记的示例:
    Is it possible to use d3.svg.symbol along with svg.marker