我有一个包含多个数字列的 D3 数据集,我成功地使用它来呈现 DC.js 图表。该图表目前固定为仅使用其中一个数字列。
但是,我希望能够在数字列之间动态切换以将它们交换为 DC.js 图表中的值。
我计划通过在页面顶部使用一组带有 onclick
事件的 html 链接来创建变量来更改 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 问题,因为我两者都不流利。
最佳答案
是的,你是对的,这些是编程和 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/