在 protovis 图表上绘制任意数量的线条
Draw an arbitrary number of lines on a protovis chart
我的目标
我正在尝试向 protovis 中的图表添加任意数量的垂直线。给定一个 x 截距值数组,我想遍历这个数组并为每个截距值画一条垂直线。现在,我可以绘制固定数量的线条,但无法概括。
我做了什么
我制作了一个 jsfiddle 展示了如何将固定数量的线添加到图表中,并且还在下面复制了该代码。在这里,我通过显式编码 x_value0
和 x_value1
添加了 2 行。在代码中,有两段相关的 protovis 代码,我将其标记为 Section A
和 Section B
。 Section A
是一个 protovis 函数,它定义了画线的位置,Section B
调用这些函数。
// X intercept values hard coded
var x_value0 = 30;
var x_value1 = 70;
new pvc.MetricDotChart({
canvas: "cccExample",
width: 500,
height: 400,
axisGrid: true,
axisZeroLine: false,
selectable: true,
extensionPoints: {
plot_add: function() {
var panel = new pv.Panel()
// Quadrant rules above grid, but below dots.
.zOrder(-1)
////
// Section A Begin
////
// Line 1
.def('l0', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_value0);
})
// Line 2
.def('l1', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_value1);
})
////
// Section A End
////
;
////
// Section B Begin
////
// Line 1
panel
.add(pv.Rule)
.top(0)
.left (function() { return this.parent.l0(); })
.height(function() { return this.parent.height(); })
.width(null)
;
// Line 2
panel
.add(pv.Rule)
.top(0)
.left (function() { return this.parent.l1(); })
.height(function() { return this.parent.height(); })
.width(null)
;
////
// Section B End
////
return panel;
}
}
})
.setData(testLDot2)
.render();
我想做的是将 xvalues
定义为一个数组,然后对其进行循环。我的尝试已经完成了一半。我做了一个 second jsfiddle ,我试图将 xvalues
移动到一个数组中。问题是我似乎无法成功地将相关部分包装在 for 循环中。来自那个 jsfiddle 的代码是:
// X intercept values in an array
var x_values = [30, 60];
new pvc.MetricDotChart({
canvas: "cccExample",
width: 500,
height: 400,
axisGrid: true,
axisZeroLine: false,
selectable: true,
extensionPoints: {
plot_add: function() {
var panel = new pv.Panel()
// Quadrant rules above grid, but below dots.
.zOrder(-1)
////
// Section A Begin - How can I put this inside of a loop?
////
// Line 1
.def('l0', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_values[0]);
})
// Line 2
.def('l1', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_values[1]);
})
////
// Section A End
////
;
////
// Section B Begin - I'm able to successfully loop this part
////
for (i = 0; i < x_values.length; i++) {
// The name of the .def function defined above
var fn_name = 'this.parent.l' + i + '()';
// Draw the lines
panel
.add(pv.Rule)
.top(0)
.left (function() { return eval(fn_name); })
.height(function() { return this.parent.height(); })
.width(null)
;
}
////
// Section B End
////
return panel;
}
}
})
.setData(testLDot2)
.render();
我可以将 Section B
包装在一个 for 循环中,我想为 Section A
:
做类似的事情
for (i = 0; i < x_values.length; i++) {
.def('l'+i, function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_values[i]);
})
}
或类似的东西。但问题是 protovis 似乎不允许我在这个 .def
块周围放置任何代码。
我还尝试为 x_values
数组中的每个项目生成一个字符串,其中包含 Section A
函数的定义,然后在 protovis 代码中使用 eval()
,但到目前为止还没有奏效。
如有任何帮助,我们将不胜感激!
编辑 - 更多进展
通过删除 Section A
并将该函数移到 Section B
中,我似乎更接近我想要的东西。有关该代码,请参阅 my latest jsfiddle。以前,在 Section B
中,.left
行调用了 Section A
中定义的函数之一。相反,我将该函数的定义移到了 .left
代码行中,如下所示:
////
// Section B Begin
////
for (var i = 0; i < x_values.length; i++) {
var x = x_values[i];
// Lines
panel
.add(pv.Rule)
.top(0)
.left (function() {
var ccc = this.parent.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x);
})
.height(function() { return this.parent.height(); })
.width(null)
;
}
现在是 运行,但仍然不太正确:它只绘制了 x_values
数组中的最后一行并覆盖了之前的所有行。有什么想法吗?
用以下代码替换你的循环
panel
.add(pv.Rule)
.data(x_values)
.top(0)
.left (
function(d) {
this.index * 20 + 15
var ccc = this.parent.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(d);
})
.height(function() { return this.parent.height(); })
.width(null)
;
我的目标
我正在尝试向 protovis 中的图表添加任意数量的垂直线。给定一个 x 截距值数组,我想遍历这个数组并为每个截距值画一条垂直线。现在,我可以绘制固定数量的线条,但无法概括。
我做了什么
我制作了一个 jsfiddle 展示了如何将固定数量的线添加到图表中,并且还在下面复制了该代码。在这里,我通过显式编码 x_value0
和 x_value1
添加了 2 行。在代码中,有两段相关的 protovis 代码,我将其标记为 Section A
和 Section B
。 Section A
是一个 protovis 函数,它定义了画线的位置,Section B
调用这些函数。
// X intercept values hard coded
var x_value0 = 30;
var x_value1 = 70;
new pvc.MetricDotChart({
canvas: "cccExample",
width: 500,
height: 400,
axisGrid: true,
axisZeroLine: false,
selectable: true,
extensionPoints: {
plot_add: function() {
var panel = new pv.Panel()
// Quadrant rules above grid, but below dots.
.zOrder(-1)
////
// Section A Begin
////
// Line 1
.def('l0', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_value0);
})
// Line 2
.def('l1', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_value1);
})
////
// Section A End
////
;
////
// Section B Begin
////
// Line 1
panel
.add(pv.Rule)
.top(0)
.left (function() { return this.parent.l0(); })
.height(function() { return this.parent.height(); })
.width(null)
;
// Line 2
panel
.add(pv.Rule)
.top(0)
.left (function() { return this.parent.l1(); })
.height(function() { return this.parent.height(); })
.width(null)
;
////
// Section B End
////
return panel;
}
}
})
.setData(testLDot2)
.render();
我想做的是将 xvalues
定义为一个数组,然后对其进行循环。我的尝试已经完成了一半。我做了一个 second jsfiddle ,我试图将 xvalues
移动到一个数组中。问题是我似乎无法成功地将相关部分包装在 for 循环中。来自那个 jsfiddle 的代码是:
// X intercept values in an array
var x_values = [30, 60];
new pvc.MetricDotChart({
canvas: "cccExample",
width: 500,
height: 400,
axisGrid: true,
axisZeroLine: false,
selectable: true,
extensionPoints: {
plot_add: function() {
var panel = new pv.Panel()
// Quadrant rules above grid, but below dots.
.zOrder(-1)
////
// Section A Begin - How can I put this inside of a loop?
////
// Line 1
.def('l0', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_values[0]);
})
// Line 2
.def('l1', function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_values[1]);
})
////
// Section A End
////
;
////
// Section B Begin - I'm able to successfully loop this part
////
for (i = 0; i < x_values.length; i++) {
// The name of the .def function defined above
var fn_name = 'this.parent.l' + i + '()';
// Draw the lines
panel
.add(pv.Rule)
.top(0)
.left (function() { return eval(fn_name); })
.height(function() { return this.parent.height(); })
.width(null)
;
}
////
// Section B End
////
return panel;
}
}
})
.setData(testLDot2)
.render();
我可以将 Section B
包装在一个 for 循环中,我想为 Section A
:
for (i = 0; i < x_values.length; i++) {
.def('l'+i, function() {
var ccc = this.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x_values[i]);
})
}
或类似的东西。但问题是 protovis 似乎不允许我在这个 .def
块周围放置任何代码。
我还尝试为 x_values
数组中的每个项目生成一个字符串,其中包含 Section A
函数的定义,然后在 protovis 代码中使用 eval()
,但到目前为止还没有奏效。
如有任何帮助,我们将不胜感激!
编辑 - 更多进展
通过删除 Section A
并将该函数移到 Section B
中,我似乎更接近我想要的东西。有关该代码,请参阅 my latest jsfiddle。以前,在 Section B
中,.left
行调用了 Section A
中定义的函数之一。相反,我将该函数的定义移到了 .left
代码行中,如下所示:
////
// Section B Begin
////
for (var i = 0; i < x_values.length; i++) {
var x = x_values[i];
// Lines
panel
.add(pv.Rule)
.top(0)
.left (function() {
var ccc = this.parent.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(x);
})
.height(function() { return this.parent.height(); })
.width(null)
;
}
现在是 运行,但仍然不太正确:它只绘制了 x_values
数组中的最后一行并覆盖了之前的所有行。有什么想法吗?
用以下代码替换你的循环
panel
.add(pv.Rule)
.data(x_values)
.top(0)
.left (
function(d) {
this.index * 20 + 15
var ccc = this.parent.getContext();
var scale = ccc.chart.axes.base.scale;
var li = ccc.panel._layoutInfo;
return li.paddings.left + scale(d);
})
.height(function() { return this.parent.height(); })
.width(null)
;