d3.js - 更新 dc.js 数据并重新应用原始过滤器

标签 d3.js dc.js crossfilter

我正在尝试构建一个关于如何 replace a crossfilter data restoring dimensions and groups 的问题的可重现示例- 即在数据更新之前重新应用用户创建的任何过滤器。这是我尝试实现 the accepted answer .这是一个 working jsfiddle .

脚本在 3 秒后刷新以从 data1 切换至 data2 .如果您在此之前应用过滤器(例如单击 Mr A ),当图表更新时,过滤器会被“记住”,因为正确的元素被突出显示(其他元素变灰)。但过滤器不适用于其他图表。您需要删除过滤器并重新应用它才能工作(例如删除 2013 饼图段)。

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

enter image description here

<!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/

有几个问题已得到纠正,但最重要的是,不要重建您的交叉过滤器、维度或组。那是不必要的。现有维度和组将使用新数据进行更新。

只需从 Crossfilter 中删除旧数据( ndx.remove() 没有过滤器),然后添加新数据( ndx.add(data2) ),然后告诉 dc.js 更新自身( dc.redrawAll() )。这就是您需要对 Crossfilter 执行的全部操作。

那么问题来了,在这个过程中,你如何移除所有过滤器并维护你的 dc.js 过滤器?关键是与 dc.js 图表交互,而不是直接与维度交互。对于序数选择图表,您可以执行以下操作:

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 测试版。

关于d3.js - 更新 dc.js 数据并重新应用原始过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32770830/

相关文章:

javascript - 替换 svg 元素

javascript - D3更新模式下select using merge和selectAll的区别

javascript - d3js v4 : How can I apply force to nodes onclick and make it look like a tween?

d3.js - dc.js - 监听图表组渲染

d3.js - dc.js 中的双 Y 轴折线图

d3.js - 如何使用 d3.js 和 crossfilter 数据创建直方图?

javascript - dc.js饼图图例溢出

javascript - 多线图,无法获取线数据

javascript - 无法从 dc.js 数据表中删除空箱

dc.js - 在 dc.js/crossfilter 中对数组使用维度