更新dc.js数据并重新应用原始过滤器 [英] Updating dc.js data and reapplying original filters

查看:72
本文介绍了更新dc.js数据并重新应用原始过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试建立此问题的可重现示例,该示例关于如何替换交叉过滤器数据恢复维度和组-即在数据更新之前重新应用用户创建的所有过滤器.这是我实现接受的答案的过程.这是工作jsfiddle .

I'm trying to build a reproducible example of this question about how to replace a crossfilter data restoring dimensions and groups - i.e. reapplying any filters created by the user before data is updated. Here's my stab at implementing the accepted answer. Here's a working jsfiddle.

脚本会在3秒后刷新,以从data1切换到data2.如果您在此之前应用了过滤器(例如,单击Mr A),则当图表更新时,该过滤器将被记住",因为右边的元素被突出显示(其他显示为灰色).但是,过滤器不会应用于其他图形.您需要删除过滤器,然后重新应用才能使其正常工作(例如,删除2013饼图段).

The script refreshes after 3 seconds to switch from data1 to data2. If you apply a filter before then (e.g. click Mr A), the filter is 'remembered' when the graphs update as the right element is highlighted (others greyed out). But the filter isn't applied across to other graphs. You need to remove the filter and reapply for it to work (e.g. remove 2013 pie segment).

我的实现或解决方案本身有问题吗?

Is there something wrong with my implementation, or the solution itself?

<!DOCTYPE html>
<html lang="en">
<head>
    <title>dc.js - Example</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="http://dc-js.github.io/dc.js/css/dc.css"/>
    <script type="text/javascript" src="http://dc-js.github.io/dc.js/js/d3.js"></script>
    <script type="text/javascript" src="http://dc-js.github.io/dc.js/js/crossfilter.js"></script>
    <script type="text/javascript" src="http://dc-js.github.io/dc.js/js/dc.js"></script>
</head>
<body>
    <div id="chart-ring-year"></div>
    <div id="chart-row-spenders"></div>

    <script type="text/javascript">

var yearRingChart   = dc.pieChart("#chart-ring-year"),
    spenderRowChart = dc.rowChart("#chart-row-spenders");

var data1 = [
    {Name: 'Mr A', Spent: 40, Year: 2011},
    {Name: 'Mr B', Spent: 10, Year: 2011},
    {Name: 'Mr C', Spent: 40, Year: 2011},
    {Name: 'Mr A', Spent: 70, Year: 2012},
    {Name: 'Mr B', Spent: 20, Year: 2012},
    {Name: 'Mr B', Spent: 50, Year: 2013},
    {Name: 'Mr C', Spent: 30, Year: 2013}
];

var data2 = [
    {Name: 'Mr A', Spent: 10, Year: 2011},
    {Name: 'Mr B', Spent: 20, Year: 2011},
    {Name: 'Mr C', Spent: 50, Year: 2011},
    {Name: 'Mr A', Spent: 20, Year: 2012},
    {Name: 'Mr B', Spent: 40, Year: 2012},
    {Name: 'Mr B', Spent: 50, Year: 2013},
    {Name: 'Mr C', Spent: 50, Year: 2013}
];

// data reset function (adapted)
function resetData(ndx, dimensions) {
    dimensions.forEach(function(dim){dim.filter(null);});
    ndx.remove();
}

// set crossfilter with first dataset
var ndx = crossfilter(data1),
    yearDim  = ndx.dimension(function(d) {return +d.Year;}),
    spendDim = ndx.dimension(function(d) {return Math.floor(d.Spent/10);}),
    nameDim  = ndx.dimension(function(d) {return d.Name;}),
    spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
    spendPerName = nameDim.group().reduceSum(function(d) {return +d.Spent;}),
    spendHist    = spendDim.group().reduceCount();

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();
}

render_plots();

// REFRESH DATA AFTER 3 SECONDS
setTimeout(function() { 
    console.log("data reset");
    resetData(ndx, [yearDim, spendDim, nameDim]); 

    ndx = crossfilter(data2),
        yearDim  = ndx.dimension(function(d) {return +d.Year;}),
        spendDim = ndx.dimension(function(d) {return Math.floor(d.Spent/10);}),
        nameDim  = ndx.dimension(function(d) {return d.Name;}),
        spendPerYear = yearDim.group().reduceSum(function(d) {return +d.Spent;}),
        spendPerName = nameDim.group().reduceSum(function(d) {return +d.Spent;}),
        x = spendPerName,
        spendHist    = spendDim.group().reduceCount();

    render_plots();
}, 3000);

    </script>
</body>
</html>

推荐答案

以下是您的示例工作: http://jsfiddle.net/pm12xf3z/

Here is your example working: http://jsfiddle.net/pm12xf3z/

有些问题已得到纠正,但最重要的是,不要重建Crossfilter,尺寸或组.那是没有必要的.现有的维度和组将使用新数据进行更新.

There were several problems that are corrected, but most importantly, don't rebuild your Crossfilter, your dimensions, or your groups. That is unnecessary. The existing dimensions and groups will be updated with the new data.

只需从交叉过滤器(ndx.remove()中没有过滤器的位置)中删除旧数据,然后添加新数据(ndx.add(data2)),然后告诉dc.js进行自我更新(dc.redrawAll()).这就是您对Crossfilter所做的一切.

Just remove the old data from your Crossfilter (ndx.remove() with no filters in place), then add your new data (ndx.add(data2)), then tell dc.js to update itself (dc.redrawAll()). That's all you need to do to your Crossfilter.

然后,问题是如何在此过程中删除所有过滤器并维护dc.js过滤器?关键是要与dc.js图表​​进行交互,而不是直接与尺寸进行交互.对于您的顺序选择图,您可以执行以下操作:

Then the question is how you remove all filters and maintain your dc.js filters in the process? The key is to interact with your dc.js charts, not your dimensions directly. For your ordinal selection charts, you can do the following:

function resetData(ndx, dimensions) {
    var yearChartFilters = yearRingChart.filters();
    var spenderChartFilters = spenderRowChart.filters();
    yearRingChart.filter(null);
    spenderRowChart.filter(null);
    ndx.remove();
    yearRingChart.filter([yearChartFilters]);
    spenderRowChart.filter([spenderChartFilters]);
}

也就是说,从图表中获取过滤器,将图表上的过滤器设置为null,移除Crossfilter数据,然后将过滤器添加回图表中.确切的过滤器格式有点麻烦,而且您必须将.filters()的输出放在数组中才能与.filter()一起使用的事实有点奇怪,但是在dc.js中,情况变得越来越好2.0测试版.

That is, grab the filters from the charts, set the filters on the charts to null, do your Crossfilter data removal, then add the filters back to the charts. The exact filter format is kind of screwy, and the fact that you have to put the output of .filters() in an array to make it work with .filter() is a bit strange, but things are getting better in dc.js 2.0 betas.

这篇关于更新dc.js数据并重新应用原始过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆