通过 fiddle 示例更好地理解 dc.js 图表交互性
understanding dc.js charts interactivity better with fiddle example
这是我的样本 fiddle
这是一张 2 基本图表 dc.js 图表。我想了解的是图表如何相互作用。例如:
如果我 select Aziz
在行图(右图)上,则此图表中的其他值显示为灰色,而在环形图(左图)中 2012
填满整个环图。然后如果我 select Aziz
再次重置两个图表。
如果我 select 2012
在环形图(左图)上,则此图表中的其他值显示为灰色,而在条形图(右图)中 Aziz
是行图(右图)中显示的唯一值。然后如果我 select 2012
再次重置两个图表。
基本上这种互动是如何运作的?
传递给这些图表的四个变量是 yearDim
spendDim
spendPerYear
spendPerName
但这里唯一的共同点是 xfilter
也许就是这样,但这并不能为我完全解释。谁能建议帮助我更好地理解这一点?
var xfilter = crossfilter(data1),
yearDim = xfilter.dimension(function(d) {return +d.Year;}),
spendDim = xfilter.dimension(function(d) {return Math.floor(d.Spent/10);}),
nameDim = xfilter.dimension(function(d) {return d.Name;}),
spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
spendPerName = nameDim.group().reduceSum(function(d) {return +d.Spent;});
function render_plots(){
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spenderRowChart
.width(250).height(200)
.dimension(nameDim)
.group(spendPerName)
.elasticX(true);
dc.renderAll();
}
注意
here and here 可能相关,它在图表交互性上或未被链接。
答案中很好的图表示例here
编辑1
看到这个fiddle
对于第二张图,如果我将此行 .group(spendPerName)
更改为此 .group(spendPerYear)
,我现在将在两个图表上按相同的分组进行分组。这改变了图表的交互性。
现在我可以 select 2012 在行图上,它会突出显示。我可以将其从突出显示切换为未突出显示。但是当它被突出显示并且我在行图中又 select 一年时,它们都崩溃了(消失)。环形图上一直没有发生任何事情。
有了环图我可以 select 一年,它会被高亮显示,切换它会高亮显示年份,然后是整个环。但是再次在行图表上没有发生任何事情。
所以它实际上已经失去了交互性。这可能是一个愚蠢的例子,但它可能会帮助我更好地理解它。 为什么它失去了交互性?或者换句话说,我怎样才能在图表中以相同的方式呈现数据而不失去交互性?因此,如果我 select 2012 在柱状图上,这将在环状图上突出显示(或显示为整个环)?也许这与我的数据集有关。
我将只回答 edit1,因为你原来的问题似乎很宽泛。
这里有两个重要的事实:
- 数据来自群组,通过维度应用过滤器。您可能会将组视为视图,将维度视为控制器,将交叉过滤器视为模型。 Crossfilter 并不完全符合该模式,但这个概念确实适用于始终写入一种类型的对象,并从反映更改的另一个对象中读取。
- 一个群体不会观察到自己维度的变化。这支持常见用例,其中每个图表都有自己的维度并从该维度的组中读取数据。您通常不希望图表自行过滤。
因此,您的群组应该几乎总是与您的尺寸相匹配。为显示年份的图表命名维度从表面上看没有任何意义,将会发生的是它将尝试按不在维度中的值进行过滤。
我不知道为什么它在第一次点击时有效,但在第二次点击时它会注册一个过滤功能,该功能会从名称维度中排除除 2012 年和 2014 年以外的所有内容 - 因此没有任何匹配项。
此外,由于第 2 点,折线图的组正在观察折线图的维度,导致它消失。您通常不希望图表观察自己的过滤器。
两个图表相互过滤
如果您希望两个图表相互过滤,请复制维度和分组,以便它们相互观察:
yearDim = xfilter.dimension(function(d) {return +d.Year;}),
yearDim2 = xfilter.dimension(function(d) {return +d.Year;}),
spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
spendPerYear2 = yearDim2.group().reduceSum(function(d) {return +d.Spent;}),
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spenderRowChart
.width(250).height(200)
.dimension(yearDim2)
.group(spendPerYear2)
.elasticX(true);
https://jsfiddle.net/gordonwoodhull/yodzpnsL/1/
两个图表 "linked brushing"
如果你想让两个图表应用到同一个维度,而不是互相过滤,而是让它们的亮点同步,那是 dc.js 不直接支持的事情。 dc.js 无法知道哪些图表正在共享一个维度,以及可以在何处共享亮点。
我用 "filter groups" 做了一些实验来明确设置多个图表使用相同的过滤器。您仍然需要告诉 dc.js 要 link 哪些图表。增强要求是https://github.com/dc-js/dc.js/issues/681
这还没有准备好,但您现在可以模拟它。这是一个构建事件侦听器的函数,该事件侦听器将过滤器状态反映到其他指定图表:
function reflect_filters(targets) {
var recursionGuard = false; // don't recurse forever
if(!Array.isArray(targets))
targets = [targets];
return function(chart) {
if(recursionGuard)
return;
recursionGuard = true;
targets.forEach(function(target) {
target.replaceFilter(chart.filters() ? [chart.filters()] : null);
});
recursionGuard = false;
}
}
为此,我们希望图表共享相同的维度和组:
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spenderRowChart
.width(250).height(200)
.dimension(yearDim)
.group(spendPerYear)
.elasticX(true);
像这样应用reflect_filters
:
yearRingChart.on('filtered', reflect_filters(spenderRowChart));
spenderRowChart.on('filtered', reflect_filters(yearRingChart));
(如果您想要 link 编辑两个以上的图表,请传递一组图表。)
另一个分支:https://jsfiddle.net/gordonwoodhull/yodzpnsL/10/
汪。所以这个狭义问题有两个答案。问题很笼统,可以写一本书了!
这是我的样本 fiddle
这是一张 2 基本图表 dc.js 图表。我想了解的是图表如何相互作用。例如:
如果我 select Aziz
在行图(右图)上,则此图表中的其他值显示为灰色,而在环形图(左图)中 2012
填满整个环图。然后如果我 select Aziz
再次重置两个图表。
如果我 select 2012
在环形图(左图)上,则此图表中的其他值显示为灰色,而在条形图(右图)中 Aziz
是行图(右图)中显示的唯一值。然后如果我 select 2012
再次重置两个图表。
基本上这种互动是如何运作的?
传递给这些图表的四个变量是 yearDim
spendDim
spendPerYear
spendPerName
但这里唯一的共同点是 xfilter
也许就是这样,但这并不能为我完全解释。谁能建议帮助我更好地理解这一点?
var xfilter = crossfilter(data1),
yearDim = xfilter.dimension(function(d) {return +d.Year;}),
spendDim = xfilter.dimension(function(d) {return Math.floor(d.Spent/10);}),
nameDim = xfilter.dimension(function(d) {return d.Name;}),
spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
spendPerName = nameDim.group().reduceSum(function(d) {return +d.Spent;});
function render_plots(){
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spenderRowChart
.width(250).height(200)
.dimension(nameDim)
.group(spendPerName)
.elasticX(true);
dc.renderAll();
}
注意
here and here 可能相关,它在图表交互性上或未被链接。
答案中很好的图表示例here
编辑1
看到这个fiddle
对于第二张图,如果我将此行 .group(spendPerName)
更改为此 .group(spendPerYear)
,我现在将在两个图表上按相同的分组进行分组。这改变了图表的交互性。
现在我可以 select 2012 在行图上,它会突出显示。我可以将其从突出显示切换为未突出显示。但是当它被突出显示并且我在行图中又 select 一年时,它们都崩溃了(消失)。环形图上一直没有发生任何事情。
有了环图我可以 select 一年,它会被高亮显示,切换它会高亮显示年份,然后是整个环。但是再次在行图表上没有发生任何事情。
所以它实际上已经失去了交互性。这可能是一个愚蠢的例子,但它可能会帮助我更好地理解它。 为什么它失去了交互性?或者换句话说,我怎样才能在图表中以相同的方式呈现数据而不失去交互性?因此,如果我 select 2012 在柱状图上,这将在环状图上突出显示(或显示为整个环)?也许这与我的数据集有关。
我将只回答 edit1,因为你原来的问题似乎很宽泛。
这里有两个重要的事实:
- 数据来自群组,通过维度应用过滤器。您可能会将组视为视图,将维度视为控制器,将交叉过滤器视为模型。 Crossfilter 并不完全符合该模式,但这个概念确实适用于始终写入一种类型的对象,并从反映更改的另一个对象中读取。
- 一个群体不会观察到自己维度的变化。这支持常见用例,其中每个图表都有自己的维度并从该维度的组中读取数据。您通常不希望图表自行过滤。
因此,您的群组应该几乎总是与您的尺寸相匹配。为显示年份的图表命名维度从表面上看没有任何意义,将会发生的是它将尝试按不在维度中的值进行过滤。
我不知道为什么它在第一次点击时有效,但在第二次点击时它会注册一个过滤功能,该功能会从名称维度中排除除 2012 年和 2014 年以外的所有内容 - 因此没有任何匹配项。
此外,由于第 2 点,折线图的组正在观察折线图的维度,导致它消失。您通常不希望图表观察自己的过滤器。
两个图表相互过滤
如果您希望两个图表相互过滤,请复制维度和分组,以便它们相互观察:
yearDim = xfilter.dimension(function(d) {return +d.Year;}),
yearDim2 = xfilter.dimension(function(d) {return +d.Year;}),
spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
spendPerYear2 = yearDim2.group().reduceSum(function(d) {return +d.Spent;}),
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spenderRowChart
.width(250).height(200)
.dimension(yearDim2)
.group(spendPerYear2)
.elasticX(true);
https://jsfiddle.net/gordonwoodhull/yodzpnsL/1/
两个图表 "linked brushing"
如果你想让两个图表应用到同一个维度,而不是互相过滤,而是让它们的亮点同步,那是 dc.js 不直接支持的事情。 dc.js 无法知道哪些图表正在共享一个维度,以及可以在何处共享亮点。
我用 "filter groups" 做了一些实验来明确设置多个图表使用相同的过滤器。您仍然需要告诉 dc.js 要 link 哪些图表。增强要求是https://github.com/dc-js/dc.js/issues/681
这还没有准备好,但您现在可以模拟它。这是一个构建事件侦听器的函数,该事件侦听器将过滤器状态反映到其他指定图表:
function reflect_filters(targets) {
var recursionGuard = false; // don't recurse forever
if(!Array.isArray(targets))
targets = [targets];
return function(chart) {
if(recursionGuard)
return;
recursionGuard = true;
targets.forEach(function(target) {
target.replaceFilter(chart.filters() ? [chart.filters()] : null);
});
recursionGuard = false;
}
}
为此,我们希望图表共享相同的维度和组:
yearRingChart
.width(200).height(200)
.dimension(yearDim)
.group(spendPerYear)
.innerRadius(50);
spenderRowChart
.width(250).height(200)
.dimension(yearDim)
.group(spendPerYear)
.elasticX(true);
像这样应用reflect_filters
:
yearRingChart.on('filtered', reflect_filters(spenderRowChart));
spenderRowChart.on('filtered', reflect_filters(yearRingChart));
(如果您想要 link 编辑两个以上的图表,请传递一组图表。)
另一个分支:https://jsfiddle.net/gordonwoodhull/yodzpnsL/10/
汪。所以这个狭义问题有两个答案。问题很笼统,可以写一本书了!