当我可以创建一条线如下:
var lineData = [{ "x": 50, "y": 50 }, {"x": 100,"y": 100}, {"x": 150,"y": 150}, {"x": 200, "y": 200}];
var lineFunction = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.interpolate("basis");
var myLine = lineEnter.append("path")
.attr("d", lineFunction(lineData))
现在我想给lineArray的第二个点添加一个文本:
lineEnter.append("text").text("Yaprak").attr("y", function(d){
console.log(d); // This is null
console.log("MyLine");
console.log(myLine.attr("d")) // This is the string given below, unfortunately as a String
// return lineData[1].x
return 10;
);
线路console.log(myLine.attr("d"))
的输出:M50,50L58.33333333333332,58.33333333333332C66.66666666666666,66.66666666666666,83.33333333333331,83.33333333333331,99.99999999999999,99.99999999999999C116.66666666666666,116.66666666666666,133.33333333333331,133.33333333333331,150,150C166.66666666666666,166.66666666666666,183.33333333333331,183.33333333333331,191.66666666666663,191.66666666666663L200,200
我可以得到字符串格式的路径数据。我可以把这个数据转换回lineData数组吗?或者,当追加文本时,有没有其他简单的方法来重新生成或得到lineData?
请参考this JSFiddle。
7条答案
按热度按时间8e2ybdfx1#
SVGPathElement
API有内置的方法来获取这些信息,你不需要自己解析数据字符串。由于您将行的选择存储为变量,因此可以使用
myLine.node()
引用path
元素本身来轻松访问path元素的api。例如:
然后,您可以通过访问
pathSegList
属性来访问用于构造路径的命令列表:使用该对象的
length
属性,可以轻松地循环访问该对象,以获取与每个路径段关联的坐标:检查控制台输出,您会发现每个路径段都有
x
和y
属性,表示该段的端点,对于贝塞尔曲线、圆弧等,控制点也根据需要指定为x1
、y1
、x2
和y2
。在您的情况下,无论您是使用此方法还是选择自己解析字符串,都将遇到困难,因为您使用
interpolate('basis')
进行线插值。(在你的具体情况下)而不是4,并且它们的端点并不总是对应于数据中的原始点。如果使用interpolate('linear')
,则可以重建原始数据集,因为线性内插与路径数据输出具有一一对应关系。假设您使用线性插值,则可按如下方式重建原始数据集:
至于在添加文本时使用原始数据......我假设您希望在点上添加标签,那么就不需要再经历重建数据的所有麻烦。事实上,真正的问题是您在制作线图时从未使用过数据绑定。尝试使用
.datum()
方法为路径绑定数据。并对标签使用.data()
方法。此外,您可能希望重命名lineEnter
,因为您没有使用回车选择,它只是代表一个组。例如:os8fio9y2#
通过将字符串拆分为
L
、M
和C
字符,可以将该行拆分为单个命令:这给出了用于呈现路径的命令序列,每个命令都是一个字符串,由一个字符(L、M或C)后跟一串用逗号分隔的数字组成,它们看起来像这样:
它描述了一条通过三个点[66,66]、[83,83]和[99,99]的曲线。你可以用另一个
split
命令和一个循环将这些点处理成点对数组,包含在一个map中:这将返回一个包含每个命令的数组,该数组是一个长度为2的数组,每个数组都是路径相应部分中的一个点的(x,y)坐标对。
您还可以修改
map
中的函数,以返回包含命令类型和数组中的点的对象。EDIT:如果希望能够访问
lineData
,可以将其作为数据添加到组中,然后将路径附加到组中,并将文本附加到组中。这将是一种比反向工程路径更像d3的数据访问方式,也可能更容易理解。
More info on SVG path elements
afdcj2ne3#
有点笨拙,但是你可以使用animateMotion沿着路径动画一个对象(例如矩形或圆形),然后采样对象的x/y位置。你将不得不做出一系列选择(例如多快地动画对象,多快地采样x/y位置,等等)。你也可以多次运行这个过程,然后取某种平均值或中值。
完整代码(请参见实际操作:http://jsfiddle.net/mqmkc7xz/)
l0oc07j24#
pathSegList
在旧版Chrome中受支持,但自Chrome 48起已被删除。但Chrome尚未实现新的API。
使用path seg polyfill处理旧API。
**使用path data polyfill来处理新的API。**建议使用。
0h4hbjxa5#
我在Google上找到了这个问题,我需要的只是SVG
path
对象的pathSegList
属性:每一点看起来都像
见
h79rfbju6#
我已经成功地使用它来渲染一个x,y点的列表:
https://shinao.github.io/PathToPoints/
代码比我在这个文本框中所能容纳的要多,但这里可能是一个好的开始:https://github.com/Shinao/PathToPoints/blob/master/js/pathtopoints.js#L209
eqfvzcg87#
展开@翠西萍回答:
getPathData()
还包括一个标准化选项:getPathData({normalize:true})
,它将转换相对和速记命令以仅使用M
、L
、C
和z
。因此,您不必担心高度优化/缩小的
d
字符串(包含相对命令、速记等)。