Chapter 14 — Lab 7
边距模型 · SVG 分组 · 多图表布局
掌握 d3.margin convention(边距模型)
学会在同一个 SVG 中整合多个子图表
理解多图表之间的坐标系对应关系
能够设计清晰的多图表联动布局
多图表联动布局不是简单的「把几个图拼在一起」。本阶段你需要设计子图表之间的空间关系、建立统一的数据流,让多个图表成为一个有机的整体。
使用 d3.margin convention 让坐标轴有足够空间:
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const width = 800 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svg = d3.select('#chart')
.append('svg').attr('width', 800).attr('height', 400);
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
g.append('g').attr('class', 'x-axis')...
g.append('g').attr('class', 'y-axis')...
注意:坐标轴的 transform 放在 g 内部,而非外部。
多图表布局的本质,是将认知科学原则转化为空间结构。以下是从理论到实践的系统方法:
① Proximity 邻近性 → 相关图表紧密相邻
② Similarity 相似性 → 统一颜色/形状编码同类数据
③ Continuity 连续性 → 对齐引导 F/Z 浏览路径
④ Closure 闭合性 → 边框/容器明确图表边界
⑤ Symmetry 对称性 → 对称布局增强稳定感
⑥ Common Fate 共向性 → 联动高亮方向保持一致
C — Contrast :KPI 大字号+主色,次要灰色小字
R — Repetition:比例尺/坐标轴样式全图统一
A — Alignment:子图表左/上边缘对齐,网格线横平竖直
P — Proximity:相关图表紧邻,留白定义元素关系
行业实践中沉淀出四种主流多图表空间结构,可根据数据关联强弱与重要性层级选择:

① 上下层叠:KPI 摘要 → 主图 → 辅助图,适合时间序列概览→详情。
② 左右分栏:50/50 或 2/3–1/3,适合两维度对比。
③ 网格排列:2×3 或 3×3,顶部 KPI 行 + 图表网格,适合多指标并行。
④ 主次分离:主图 70% + 侧边 KPI/列表 30%,适合仪表盘模式。
现代 Web 仪表盘普遍采用 12 列响应式网格,任意列数可自由组合:
/* CSS Grid 实现 12 列布局 */
.dashboard {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
padding: 1rem;
}
/* 常见列数组合:*/
.chart-full { grid-column: span 12; } /* 全宽 */
.chart-half { grid-column: span 6; } /* 1/2 */
.chart-third { grid-column: span 4; } /* 1/3 */
.chart-2thirds{ grid-column: span 8; } /* 2/3 */
.chart-quarter{ grid-column: span 3; } /* 1/4 */
.chart-3quarters{ grid-column: span 9; } /* 3/4 */
组合原则:同行列宽之和 = 12。例如三个不同宽度的图表:span 5 + span 4 + span 3 = 12。
□ 每屏不超过 5~7 个独立图表(Miller 法则)
□ 分块策略:核心图(50%) → 辅助图(2~3个) → KPI/Sparkline
□ 优先标红异常值,而非堆砌正常数据
□ 相关图表间加箭头/连线,示意数据联动
多图表联动的核心是「单一数据源,多个可视化视图」:
// 全局状态
const state = {
filterCategory: null,
filterYear: null
};
function getFilteredData() {
return rawData.filter(d =>
(!state.filterCategory || d.category === state.filterCategory)
&& (!state.filterYear || d.year === state.filterYear)
);
}
function updateAll() {
const filtered = getFilteredData();
renderMap(filtered);
renderLine(getTimeSeries(filtered));
renderPie(getCategoryCounts(filtered));
}
// 联动:点击饼图 → 更新地图
pieG.selectAll('path').on('click', (event, d) => {
state.filterCategory = d.data.name;
updateAll();
});
多图表布局的关键原则:各子图表的坐标系要相互对应(点击地图高亮某区域,折线图也要同步更新)。使用全局 state 对象管理过滤条件,让所有图表监听同一个数据变化。
实验报告(Word 填写): ① 布局设计说明(文字描述 + 草图) ② SVG 层级结构(g 的嵌套关系) ③ 数据联动设计 ④ 布局效果截图