d3.js:处理多个画笔
d3.js: Handling multiple brushes
我正在尝试构建一个平行坐标图,如 Mike 的示例所示 here. So far so good,但我在处理画笔事件时遇到了一些问题。
Mike 的示例使用 v3,我正在使用 v4。 v4 更新删除了 brush.empty()
,留下 d3.brushSelection(node)
来完成这个角色。
这是我第一次使用该库,所以我不完全了解如何在某些情况下迭代选择。似乎 API 想要 selection.node()
作为参数,但我的选择不是 1,而是一组画笔。
有没有一种方法可以在 v4 中使用简单的 JS 构造(类似于 Mike 的)来实现它?
下面是 Mike 在 v3 中实现的刷机事件处理程序
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
这里又是一个事件处理程序,由互联网的一位好心人实施,他实施了 parallel coordinates in v4。奖金(理论上)指向任何可以解释此代码如何工作的人。
function brush_parallel_chart() {
for (var i = 0; i < dimensions.length; ++i) {
if (d3.event.target == y[dimensions[i]].brush) {
extents[i] = d3.event.selection.map(y[dimensions[i]].invert, y[dimensions[i]]);
}
}
foreground.style("display", function(d) {
return dimensions.every(function(p, i) {
if (extents[i][0] == 0 && extents[i][0] == 0) {
return true;
}
return extents[i][1] <= d[p] && d[p] <= extents[i][0];
}) ? null : "none";
});
}
我能够通过引用 v4 示例中的上述片段来解决这个问题。
我最初的方法是遍历画笔,并使用每个画笔的属性来确定当前点是否包含在它的范围内。从概念上讲这是正确的..
但是d3.event没有提到画笔,而是包含了我需要的所有信息。
const [upperBound, lowerBound] = d3.event.selection.map(scale.invert, scale);
// Or
const bounds = [scale(d3.event.selection), scale.invert(d3.event.selection)];
换句话说...
来自d3.event.selection
的数据是一个数字对,需要应用于画笔所在维度(轴)的scale
。
一旦有了画笔的边界,就很容易弄清楚问题点是否包含在边界内。
return val >= lowerBound && val <= upperBound
我正在尝试构建一个平行坐标图,如 Mike 的示例所示 here. So far so good,但我在处理画笔事件时遇到了一些问题。
Mike 的示例使用 v3,我正在使用 v4。 v4 更新删除了 brush.empty()
,留下 d3.brushSelection(node)
来完成这个角色。
这是我第一次使用该库,所以我不完全了解如何在某些情况下迭代选择。似乎 API 想要 selection.node()
作为参数,但我的选择不是 1,而是一组画笔。
有没有一种方法可以在 v4 中使用简单的 JS 构造(类似于 Mike 的)来实现它?
下面是 Mike 在 v3 中实现的刷机事件处理程序
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
这里又是一个事件处理程序,由互联网的一位好心人实施,他实施了 parallel coordinates in v4。奖金(理论上)指向任何可以解释此代码如何工作的人。
function brush_parallel_chart() {
for (var i = 0; i < dimensions.length; ++i) {
if (d3.event.target == y[dimensions[i]].brush) {
extents[i] = d3.event.selection.map(y[dimensions[i]].invert, y[dimensions[i]]);
}
}
foreground.style("display", function(d) {
return dimensions.every(function(p, i) {
if (extents[i][0] == 0 && extents[i][0] == 0) {
return true;
}
return extents[i][1] <= d[p] && d[p] <= extents[i][0];
}) ? null : "none";
});
}
我能够通过引用 v4 示例中的上述片段来解决这个问题。
我最初的方法是遍历画笔,并使用每个画笔的属性来确定当前点是否包含在它的范围内。从概念上讲这是正确的..
但是d3.event没有提到画笔,而是包含了我需要的所有信息。
const [upperBound, lowerBound] = d3.event.selection.map(scale.invert, scale);
// Or
const bounds = [scale(d3.event.selection), scale.invert(d3.event.selection)];
换句话说...
来自d3.event.selection
的数据是一个数字对,需要应用于画笔所在维度(轴)的scale
。
一旦有了画笔的边界,就很容易弄清楚问题点是否包含在边界内。
return val >= lowerBound && val <= upperBound