DC.js动态刷新图表以使用更新的数据集

时间:2019-10-05 19:05:35

标签: javascript d3.js dc.js

我拥有包含多个数字列的D3数据集,我已成功使用它们来呈现DC.js图表​​。图表目前固定为仅使用数字列之一。

但是,我希望能够在数字列之间动态切换,以将它们交换为DC.js图表​​中的值。

我计划通过使用页面顶部的一组html链接和一个onclick事件来实现此目的,以创建变量来更改D3数据集中选择的列。一切正常。

但是,我坚持如何刷新DC.js图表​​以使用更新的数据集。

我看到了其他类似的问题herehere,但它们并没有帮助我。

这是我的代码:

bucket.getObject({
    Bucket: 's3-google-analytics', 
    Key: 'merged.csv'
    }, 
    function awsDataFile(error, data) {

        if (error) {
            return console.log(error);
        }

        mergedcsv = d3.csv.parse(data.Body.toString()); 
        var parseDate = d3.time.format("%Y%m%d").parse;
        var counter = 0;

        var varMetric = 'sessions'; 
        // Note, i can successfully manually change varMetric variable  
        //to change numeric column is used in chart. 

        mergedcsv.forEach(function(d) {
            d.date = parseDate(d.date);
            d.dateString = formatDateYYYYMMDD(d.date);
            if (varMetric == 'sessions') {
                d.metric = +d.sessions;
            } else if (varMetric == 'users') {
                d.metric = +d.users;
            } else if (varMetric == 'bounceRate') {
                d.metric = +d.bounceRate;
            } else if (varMetric == 'newUsers') {
                d.metric = +d.newUsers;
            } else if (varMetric == 'sessionDuration') {
                d.metric = +d.sessionDuration;
            } else if (varMetric == 'sessionsPerUser') {
                d.metric = +d.sessionsPerUser;
            } else if (varMetric == 'twitterSessions') {
                d.metric = +d.twitterSessions;
            }
            countLoop = counter++;
        });

        var ndx  = crossfilter(mergedcsv);

        // where to put this?
        $('#metric a').click(function(e) {
            var varMetric = $(e.target).text();
            console.log(varMetric);
            ndx.remove();
        // which to use .. add or crossfilter?
            //ndx.add(mergedcsv);
            //ndx  = crossfilter(mergedcsv);
        // which to use .. redrawAll or renderAll?
            //dc.redrawAll();
            //dc.renderAll();
        });

        var yyyymmDim = ndx.dimension(function(d) { return d["yyyymm"]; });
        var PPCCByYYYYMM = yyyymmDim.group().reduceSum( function(d) {  return +d.metric; });
        BarChartAlltimeByMonth = dc.barChart("#barchart-alltime-by-month");

        BarChartAlltimeByMonth
        .height(100)
        .width(1000)
        .margins({top: 0, right: 10, bottom: 50, left: 35})
        .dimension(yyyymmDim)
        .group(PPCCByYYYYMM)

        dc.renderAll(); 

        //on click put here but doesn't work
        $('#metric a').click(function(e) {
            var varMetric = $(e.target).text();
            console.log('onclick ' + varMetric);
            ndx.remove();
            ndx.add(mergedcsv);
            //dc.redrawAll();
            dc.renderAll();
        });


});

我将onclick处理程序放在脚本的底部。

在上述其他SO问题中,似乎可以做到这一点:1)删除旧数据,2)添加新数据,3)重绘所有图表。

ndx.remove()确实删除了数据,但是ndx.add(mergedcsv)没有添加数据。

dc.redrawAll()不会执行任何操作,但是尽管dc.renderAll()确实会导致图表再次呈现,但是数据没有变化。

这可能是DC.js和一般的Javascript问题,因为我都不熟练。

1 个答案:

答案 0 :(得分:1)

是的,是的,这是编程和JavaScript问题,与dc.js或d3.js无关。

取决于回调的回调

首先,我们研究了将回调(如单击处理程序)放置在何处,该回调程序可处理由另一个回调(如接收数据处理程序)设置的可视化效果和/或数据。

问题在于数据和图表可能在顶级范围内不可用。

最简单的解决方案是将点击处理程序放入数据处理程序中,以便可以访问图表和数据。

重复使用数据转换

您要处理的下一个问题是在哪里放置数据转换,以便在绘制图表之前和单击之后都将调用它。

当前,您的点击处理程序不执行任何操作,因为它会将数据替换为...相同的数据。 (长号悲伤的声音)

有很多方法可以解决此问题,但是更改当前代码的最简单方法是将数据转换移动到可重用的函数

function transform_data(data, varMetric) {
    data.forEach(function(d) {
        d.date = parseDate(d.date);
        d.dateString = formatDateYYYYMMDD(d.date);
        if (varMetric == 'sessions') {
            d.metric = +d.sessions;
        } else if (varMetric == 'users') {
            d.metric = +d.users;
        } else if (varMetric == 'bounceRate') {
            d.metric = +d.bounceRate;
        } else if (varMetric == 'newUsers') {
            d.metric = +d.newUsers;
        } else if (varMetric == 'sessionDuration') {
            d.metric = +d.sessionDuration;
        } else if (varMetric == 'sessionsPerUser') {
            d.metric = +d.sessionsPerUser;
        } else if (varMetric == 'twitterSessions') {
            d.metric = +d.twitterSessions;
        }
        countLoop = counter++;
    });
}

现在这可以在绘制图表之前发生:

function awsDataFile(error, data) {

    if (error) {
        return console.log(error);
    }

    mergedcsv = d3.csv.parse(data.Body.toString()); 
    var parseDate = d3.time.format("%Y%m%d").parse;
    var counter = 0;

    var varMetric = 'sessions'; 
    transform_data(mergedcsv, varMetric);
    var ndx  = crossfilter(mergedcsv);
    // ...

我们可以单击一下来重复数据转换:

    $('#metric a').click(function(e) {
        var varMetric = $(e.target).text();
        console.log('onclick ' + varMetric);
        transform_data(mergedcsv, varMetric);
        ndx.remove();
        ndx.add(mergedcsv);
        dc.redrawAll();
    });

注意:对于dc.js,您肯定只想第一次渲染,然后在数据更改时重新绘制。渲染从头开始,而重绘将执行(通常)漂亮的动画过渡。