计算未在 data() 范围内定义的折线坐标
Calculations of polyline coordinates not defined in data() scope
我在计算 svg:poly
元素的 "d"
属性时遇到问题。我做的模型的情况:
演示版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(...);
});
但我正在寻找一些 "inline" 原生 d3
解决方案。在我的情况下,在绘图之前我应该 "prepare the data" 的解决方案不起作用。它只是一个复杂问题的模型。抱歉!
我想您可能对 d3.svg.line()
的使用方式有些误解。在这个例子中:
var lineGenerator = d3.svg.line()
lineGenerator
是一个函数,它接受一个点数组和 returns 一个字符串,该字符串是分配给属性 <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
错误是行生成器函数 d3.svg.line()
应该被内联调用为 (fn)()
:
path.attr("d", (d3.svg.line())(/* points */));
作为参数,提到为 points
,我们可以将函数与点数组 return 一起使用,例如:
path.attr("d", (d3.svg.line())(function(){
return([[1,2],[3,4],[5,6]]);
}));
方法 x()
和 y()
应该仅在坐标关联数组的情况下使用,并且在定义为对数组的点的情况下可以避免:
[1,2],[3,4],[5,6]
演示: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]
});
我在计算 svg:poly
元素的 "d"
属性时遇到问题。我做的模型的情况:
演示版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(...);
});
但我正在寻找一些 "inline" 原生 d3
解决方案。在我的情况下,在绘图之前我应该 "prepare the data" 的解决方案不起作用。它只是一个复杂问题的模型。抱歉!
我想您可能对 d3.svg.line()
的使用方式有些误解。在这个例子中:
var lineGenerator = d3.svg.line()
lineGenerator
是一个函数,它接受一个点数组和 returns 一个字符串,该字符串是分配给属性 <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
错误是行生成器函数 d3.svg.line()
应该被内联调用为 (fn)()
:
path.attr("d", (d3.svg.line())(/* points */));
作为参数,提到为 points
,我们可以将函数与点数组 return 一起使用,例如:
path.attr("d", (d3.svg.line())(function(){
return([[1,2],[3,4],[5,6]]);
}));
方法 x()
和 y()
应该仅在坐标关联数组的情况下使用,并且在定义为对数组的点的情况下可以避免:
[1,2],[3,4],[5,6]
演示: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]
});