在d3.geo MultiPoint中,如何为不同的点提供不同的形状? [英] in d3.geo MultiPoint how can I provide different shapes for different poins?

查看:51
本文介绍了在d3.geo MultiPoint中,如何为不同的点提供不同的形状?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have some geoJson data that I am charting using d3.geo.

当我写类似的东西

d3.select("svg")
   ... 
   .attr("d", function(d) {
                return path({
                    type:"MultiPoint",
                    coordinates: get_activity_coords_(d.activities)
                });
   })

我总是为每个坐标画一个圆.坐标表示旅程的各个停靠点的位置.我希望第一个和最后一个坐标的形状不同.

I always get a circle for each coordinate. The coordinates represent locations of various stopping points of a journey. What I would prefer is a different shape for the first and the last coordinate.

是否可以使用MultiPoint做到这一点,有没有我可以效仿的例子?我可以一一画出点,但是我记得阅读过MultiPoint的速度要快得多.另外,该代码更容易阅读.

Is it possible to do this using MultiPoint, is there an example that I can follow? I could draw the points one by one, but I recall reading that MultiPoint is far faster. Plus, the code would be much clearer to read.

非常感谢.

推荐答案

您不能使用 d3.geo.path 为MultiPoint geoJSON做不同的形状.您可以根据函数更改半径,但是看起来您只能按功能进行设置,而不能按 point 进行设置,因此您必须将一组点分解为多个功能,并且由于使用单个元素而失去任何性能优势

You can't do different shapes for MultiPoint geoJSON with d3.geo.path. You can change the radius based on a function, but it looks like you can only set it per feature and not per point, so you'd have to break your set of points into multiple features and lose any performance benefit from using the single element.

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

However, there are other ways to go about doing this.

正如您提到的,一个选项是为每个点创建一个具有单独< path> 元素的嵌套选择,并使用 d3.svg.symbol()函数.然后,您可以自定义符号函数以基于数据或索引.

One option, as you mentioned, is to create a nested selection with a separate <path> element for each point, and draw each path using a d3.svg.symbol() function. You can then customize the symbol function to be based on data or index.

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

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

Another option, which allows you to set custom shapes for the first and last point (but all intermediary points would be the same) is to connect the points as the vertices of a single, invisible <path> element and use line markers to draw the point symbols.

您的方法将是:

  1. 在SVG中创建一个< defs> 元素(硬编码或使用d3动态创建),并在其中定义起点,中间和终点标记点.(您可以使用 d3.svg.symbol()函数来绘制路径,也可以自己制作,也可以使用图像,由您自己决定.)

  1. Create a <defs> element within your SVG (either hard-coded or dynamically with d3), and define the start, middle and end marker points within them. (You can use d3.svg.symbol() functions to draw the paths, or make your own, or use images, it's up to you.)

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

Use a d3.svg.line() function to create the path's "d" attribute based on your array of point coordinates; the x and y accessor functions for the line should use the projection function that you're using for the map to get the x/y position from the coordinates of that point. To avoid calculating the projection twice, you can save the projected coordinates in the data object:

 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()函数将线绘制为地图功能,因为它将线分解为曲线以匹配经度和纬度的曲线地图投影中的直线;要使直线标记起作用,路径仅需是点之间的简单直线连接.)

(You can't use your d3.geo.path() function to draw the lines as a map feature, because it will break the line into curves to match the curves of longitude and latitude lines in your map projection; to get the line markers to work, the path needs to be just a simple straight-line connection between points.)

将该路径上的样式设置为无笔触和无填充,因此该行本身不会显示,然后设置 marker-start marker- marker-end 属性,以引用正确标记元素的id值.

Set the style on that path to be no stroke and no fill, so the line itself doesn't show up, but then set the marker-start, marker-mid and marker-end properties on the line to reference the id values of the correct marker element.

为使您入门,这是一个使用d3动态生成线标记的示例:
是否可以将d3.svg.symbol与svg.marker一起使用

To get you started, here's an example using d3 to dynamically-generate line markers:
Is it possible to use d3.svg.symbol along with svg.marker

这篇关于在d3.geo MultiPoint中,如何为不同的点提供不同的形状?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆