如何实现DC.js中卖家与城市销售额的动态总计
解决DC.js中卖家/城市销售额动态总计的问题
嘿,我看了你的代码和需求——你需要让总计数值跟着行选择实时更新对吧?之前尝试crossfilter.add()没成功是因为用错了方法,add()是用来添加新数据的,咱们需要的是基于当前过滤结果计算聚合值,用Crossfilter的groupAll就能搞定。
下面是具体的解决方案,一步步来:
1. 创建全局聚合GroupAll
首先,在你的Crossfilter初始化之后,添加一个groupAll对象,专门计算当前过滤条件下的总销售额(本年和去年):
// 放在d3.json回调里,cf定义好之后 var totalGroupAll = cf.groupAll().reduce( // 累加数据 function(p, v) { p.totalAno += +v.Vendas_Ano; p.totalHomologo += +v.Vendas_Ant; return p; }, // 移除数据时递减 function(p, v) { p.totalAno -= +v.Vendas_Ano; p.totalHomologo -= +v.Vendas_Ant; return p; }, // 初始化聚合对象 function() { return { totalAno: 0, totalHomologo: 0 }; } );
2. 写一个更新总计表格的函数
这个函数会从groupAll拿到最新的总计值,然后更新页面上的两个总计表格:
// 同样放在d3.json回调内 function updateTotals() { const totals = totalGroupAll.value(); // 更新卖家总计表 const vendedorTotalRow = d3.select('#totaisVendedores tbody') .selectAll('tr') .data([totals]); vendedorTotalRow.enter() .append('tr') .merge(vendedorTotalRow) .html(d => ` <td>Total Selected</td> <td>${Number(Math.round(d.totalAno * 100) / 100).toLocaleString("es-ES", { minimumFractionDigits: 2 })}€</td> <td>${Number(Math.round(d.totalHomologo * 100) / 100).toLocaleString("es-ES", { minimumFractionDigits: 2 })}€</td> `); // 更新城市总计表 const cityTotalRow = d3.select('#totaisCities tbody') .selectAll('tr') .data([totals]); cityTotalRow.enter() .append('tr') .merge(cityTotalRow) .html(d => ` <td>Total Selected</td> <td>${Number(Math.round(d.totalAno * 100) / 100).toLocaleString("es-ES", { minimumFractionDigits: 2 })}€</td> <td>${Number(Math.round(d.totalHomologo * 100) / 100).toLocaleString("es-ES", { minimumFractionDigits: 2 })}€</td> `); }
3. 绑定更新函数到DC的事件
在DC渲染完成后,初始化一次总计,然后监听postRedraw事件,这样每次过滤变化(行选择、图表刷选)都会自动更新总计:
// 放在dc.renderAll()之后 dc.renderAll(); // 初始加载时更新总计 updateTotals(); // 监听DC重绘事件,每次过滤变化后自动更新 dc.events.on('postRedraw', updateTotals);
4. 修复HTML表格的结构
你的总计表格缺少<tbody>标签,D3没法正确插入行,补上就行:
<!-- 修改卖家总计表格 --> <table class="table" id="totaisVendedores"> <thead> <tr> <th>Total Sales</th> <th>Current Year</th> <th>Last Year</th> </tr> </thead> <tbody></tbody> <!-- 新增这个tbody --> </table> <!-- 修改城市总计表格 --> <table class="table" id="totaisCities"> <thead> <tr> <th>Total City</th> <th>Current Year</th> <th>Last Year</th> </tr> </thead> <tbody></tbody> <!-- 新增这个tbody --> </table>
为什么这么做?
groupAll会自动跟踪Crossfilter的过滤状态,不管你是选中卖家、城市还是用图表刷选,它都会计算当前可见数据的总和。- DC的
postRedraw事件确保每次图表更新后,总计都会同步刷新,完全不需要手动触发。 - 之前用
crossfilter.add()走偏了,那个方法是用来往数据集里加新数据的,不是用来做聚合计算的。
现在你再试试,选中卖家或者城市行,总计表格会实时更新成选中数据的总和;重置过滤的话,也会回到全局的总销售额。
内容的提问来源于stack exchange,提问作者vbernal
相关产品推荐
相关产品推荐

