我在计算"d"
元素的svg:poly
属性时遇到问题。我制作了这种情况的模型:
DEMO http://jsfiddle.net/2efxadLy/1/
// array of points
var points = [{
name: "a",
coord: [22, 35]
}, {
name: "b",
coord: [2, 55]
}, {
name: "c",
coord: [42, 5]
}, {
name: "d",
coord: [5, 57]
}];
// array of connectors
var connectors = [
["a", "c"],
["b", "c"],
["d", "a"]
];
// styles
var styles = {
line: {
"stroke": "black",
"stroke-width": 1,
"fill": "none"
},
board: {
"width": 100,
"height": 100
}};
// svg element
var svg = d3.select("body").append("svg").attr(styles.board);
// three connectors between points
var path = svg.selectAll("path").data(connectors).enter().append("svg:path").attr(styles.line);
// attempt to fill the "d" attribute of the path
path.attr("d", function (d) {// d -- the array of connector pair ["a", "c"] etc.
var from = d[0],// "a"
to = d[1],// "c"
point_from = points.filter(function (item) {// [22,35]
return (item.name === from);
})[0],
point_to = points.filter(function (item) {// [42,5]
return (item.name === to);
})[0];
var coords = [point_from, point_to];
// ERROR!
// I can not place coords in line() function
// the line() function expects some "d3.data" type argument
// but there is no "d3.selection" to produce this data type
var l = d3.svg.line(/* missed content */).extrapolate("basis");
return(l);
});
结果,我有3个path
没有“d”属性:
我知道,我可以使用该模式,我将逐一添加连接器:
var line_function = d3.svg.line().x(function(d) {
return (d.x);
}).y(function(d) {
return d.y;
}).interpolate("basis");
connectors.forEach(function(pair){
var from = pair[0], to = pair[1];
var coordinate_array = [{x: ..., y; ...},{x: ..., y; ...}];
board.data(coordinate_array).enter().append("svg:path").attr("d", line_function(coordinate_array)).attr(...);
});
但我正在寻找一些“内联”原生d3
解决方案。在绘图之前我应该“准备数据”的解决方案在我的情况下不起作用。这只是一个复杂问题的典范。遗憾!
答案 0 :(得分:1)
我想也许你对d3.svg.line()
的使用方式有点误解。在这个例子中:
var lineGenerator = d3.svg.line()
lineGenerator
是一个函数,它接受一个点数组并返回一个String,它是分配给属性<path d="...">
的路径描述。
在所有这些中,不需要绑定到d3选择。
因此,您可以根据coords
数组为此创建所需路径描述的生成器:
// converts an array of 2 points (coords) or svg line path data
var lineGenerator = d3.svg.line()
.x(function(point) { return point.coord[0]; })
.y(function(point) { return point.coord[1]; })
.interpolate("basis")
稍后,在汇编path.attr("d", function (d) { ... })
后,在var coords = [point_from, point_to]
内,只需调用行生成器。
return lineGenerator(coords);
这是fiddle
答案 1 :(得分:0)
错误是行生成器函数d3.svg.line()
应该内联调用(fn)()
:
path.attr("d", (d3.svg.line())(/* points */));
作为参数,提到为points
,我们可以使用带点数组的函数返回如下:
path.attr("d", (d3.svg.line())(function(){
return([[1,2],[3,4],[5,6]]);
}));
方法x()
和y()
只应用于关联的坐标数组,并且在定义为对数组的情况下可以避免:
[1,2],[3,4],[5,6]
DEMO:http://jsfiddle.net/602fxj2e/
最后,我的示例代码应该以这种方式纠正:
// svg element
var p = d3.select("body").append("svg").attr(styles.board).selectAll("path").data(connectors).enter().append("svg:path").attr(styles.line)
.attr("d", function (d) {
var from = d[0], // "a"
to = d[1], // "c"
point_from = points.filter(function (item) { // [22,35]
return (item.name === from);
})[0].coord,
point_to = points.filter(function (item) { // [42,5]
return (item.name === to);
})[0].coord,
dots = [point_from, [point_from[0] + 100, point_from[1] + 50], // just to make it looks funny
[point_to[0] + 200, point_to[1] + 100], point_to];
return ((d3.svg.line().interpolate("basis"))(dots));
// simple return should be [point_from, point_to]
});