基于聚合数据的DC.js双饼图联动实现方案咨询
需求可实现,具体实现方案如下
1. 数据无需转纵向结构
保留现有宽表格式即可,因为需求的联动逻辑是基于事件级别的存在性过滤,不需要颜色和身高维度的交叉关联数据(比如黄种人里的高个子数量)。
2. 构建CrossFilter的维度与自定义组
颜色维度与组
- 先创建基于事件的主维度:
const eventsDim = crossfilter(data).dimension(d => d.Event); - 自定义颜色组,统计每种颜色对应的有效事件数(即该颜色数值>0的事件数量):
const colorGroup = eventsDim.groupAll().reduce( (p, v) => { if(v.Yellows > 0) p.Yellows++; if(v.Reds > 0) p.Reds++; return p; }, (p, v) => { if(v.Yellows > 0) p.Yellows--; if(v.Reds > 0) p.Reds--; return p; }, () => ({Yellows: 0, Reds: 0}) ).top(Infinity)[0]; // 转换为dc.js饼图需要的格式 const colorPieData = Object.entries(colorGroup).map(([key, val]) => ({key, value: val}));
身高维度与组
- 同样基于事件主维度,自定义身高组:
const heightGroup = eventsDim.groupAll().reduce( (p, v) => { p.talls++; // 所有事件都有talls数据 if(v.shorts > 0) p.shorts++; return p; }, (p, v) => { p.talls--; if(v.shorts > 0) p.shorts--; return p; }, () => ({talls: 0, shorts: 0}) ).top(Infinity)[0]; const heightPieData = Object.entries(heightGroup).map(([key, val]) => ({key, value: val}));
3. 实现饼图交互联动
颜色饼图的点击过滤
给颜色饼图绑定filtered事件,根据选中的颜色过滤事件:
const colorPie = dc.pieChart('#color-pie'); colorPie .dimension(new dc.dimension(() => colorPieData.map(d => d.key))) .group(new dc.group(() => colorPieData)) .on('filtered', (chart, filter) => { if(filter) { // 过滤出选中颜色数值>0的事件 eventsDim.filter(d => d[filter] > 0); } else { eventsDim.filterAll(); } dc.redrawAll(); });
身高饼图的点击过滤
针对身高的不同选项做特殊处理:
const heightPie = dc.pieChart('#height-pie'); heightPie .dimension(new dc.dimension(() => heightPieData.map(d => d.key))) .group(new dc.group(() => heightPieData)) .on('filtered', (chart, filter) => { if(filter === 'shorts') { eventsDim.filter(d => d.shorts > 0); } else { // 点击talls或清除过滤时,重置所有过滤器 eventsDim.filterAll(); } dc.redrawAll(); });
4. 核心逻辑说明
- 所有过滤操作都作用于事件维度,确保两个饼图基于同一事件集合计算数据。
- 自定义组函数负责统计符合条件的事件数量,而非数值求和,匹配需求中“显示对应事件范围”的逻辑。
- 无需拆分宽表,避免了无意义的数据拆分(因为没有颜色和身高的交叉数据)。
内容的提问来源于stack exchange,提问作者artfulrobot
相关产品推荐
相关产品推荐

