DC.js динамически обновляет диаграммы для использования обновленного набора данных - PullRequest
3 голосов
/ 05 октября 2019

У меня есть набор данных D3 с несколькими числовыми столбцами, которые я успешно использую для визуализации диаграмм DC.js. Диаграмма в настоящее время фиксируется для использования только одного из числовых столбцов.

Однако я хочу иметь возможность динамически переключаться между числовыми столбцами, чтобы поменять их местами в качестве значения в диаграммах DC.js.

Я планирую сделать это с помощью набора HTMLссылки вверху страницы с событием onclick для создания переменной для изменения столбца, выбранного в наборе данных D3. Это работает нормально.

Однако я застрял на том, как обновить диаграммы DC.js для использования обновленного набора данных.

Я видел другие подобные вопросы здесь и здесь но они мне не помогают.

Вот мой код:

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 Ответ

1 голос
/ 07 октября 2019

Да, вы правы, это вопросы программирования и JavaScript, на самом деле не так много общего с dc.js или d3.js.

обратные вызовы, которые зависят от обратных вызовов

Сначала мы посмотрелигде помещать обратные вызовы, такие как обработчики щелчков, которые управляют визуализацией и / или данными, которые устанавливаются другим обратным вызовом, таким как обработчик полученных данных.

Проблема в том, что данные и диаграмма могут быть недоступны в области верхнего уровня.

Самое простое решение - поместить обработчик щелчков внутри обработчика данных, чтобы он имел доступк диаграмме и данным.

повторное использование преобразований данных

Следующая проблема, с которой вы сталкиваетесь, - где поместить преобразование данных, чтобы оно вызывалось как до рисования диаграммы, так и послеa click.

В настоящее время ваш обработчик кликов ничего не делает, потому что он заменяет данные ... теми же данными. (грустный тромбонный звук)

Существует множество способов решить эту проблему, но самый простой способ изменить текущий код - перевести преобразования данных в повторно используемую функцию :

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

Примечание: с помощью постоянного тока. js вы определенно хотите визуализировать только в первый раз, а затем перерисовывать при изменении данных. Рендеринг начинается с нуля, в то время как перерисовка будет выполнять (обычно) приятные анимированные переходы.

...