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

标签 javascript d3.js dc.js

我有一个包含多个数字列的 D3 数据集,我成功地使用它来呈现 DC.js 图表。该图表目前固定为仅使用其中一个数字列。

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

我计划通过在页面顶部使用一组带有 onclick 事件的 html 链接来创建变量来更改 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 问题,因为我两者都不流利。

最佳答案

是的,你是对的,这些是编程和 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,您绝对希望只在第一次渲染,然后在数据发生变化时重新绘制。渲染从头开始,而重绘将执行(通常)漂亮的动画过渡。

关于javascript - DC.js 动态刷新图表以使用更新的数据集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58251470/

相关文章:

javascript - 如何从url中提取字符串

javascript - 流停止后网络摄像头灯保持亮起

javascript - d3 折线图和剪辑路径

d3.js - nvd3.jsstackedAreaChart 图表转换。就像在 nvd3.org 上一样

javascript - DC.js折线图配置

javascript - 浏览器缓存下载的 JavaScript

Javascript:替换 element.src 属性中的字符串

d3.js 在 Y 轴上附加数据集中的两个标签

javascript - dc.js - 从单选按钮中选择减少功能

javascript - dc.js Vue 渲染图表不正确