Loading...
矩形树图是一种用于展示层次化数据的可视化图表,通过一系列嵌套的矩形来表示树状结构的数据。每个矩形的面积大小与其对应的数值成正比,颜色通常用来区分不同的类别或层级。矩形树图将树形数据结构转化为平面空间的矩形填充,能够直观地展示数据的层次关系和数值比例。
矩形树图特别适合展示具有层级关系的大量数据,如文件系统、组织架构、预算分配、股票市场等。相比传统的树形结构图,矩形树图能更有效地利用空间,并且具有展示占比功能,使得用户能够快速理解数据的分布和重要性。
矩形树图还支持交互式下钻功能,用户可以点击某个矩形区域来查看该层级的详细子项,这使得它成为数据探索和分析的强大工具。
英文名:Treemap
图表类型 | 矩形树图 |
---|---|
适合的数据 | 层次化数据:具有树状结构的嵌套数据,包含分类字段和数值字段 |
功能 | 展示层次化数据的比例关系和分布情况 |
数据与图形的映射 | 层级关系映射到嵌套矩形 数值大小映射到矩形面积 不同类别通过颜色和位置进行区分 |
适合的场景 | 文件系统、组织架构、预算分配、股票组合等具有清晰层次关系的数据展示 |
例子 1: 展示文件系统结构
下图展示了软件项目文件系统的层次结构,通过矩形树图可以清晰地看到各个模块和文件的大小分布,帮助开发者了解代码结构。
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});chart.options({type: 'treemap',data: {type: 'fetch',value: 'https://assets.antv.antgroup.com/g2/flare-treemap.json',},layout: {path: (d) => d.name.replace(/\./g, '/'),tile: 'treemapBinary',paddingInner: 1,},encode: {value: 'size',color: (d) => d.parent?.data.name.split('.')[1] || 'root',},style: {labelText: (d) => {const name = d.data.name.split('.').pop().split(/(?=[A-Z][a-z])/g)[0];return name;},labelFill: '#000',labelPosition: 'top-left',labelDx: 3,labelDy: 3,fillOpacity: 0.7,},tooltip: {title: (d) => d.path?.join?.('.') || d.data.name,items: [{ field: 'value', name: '大小' }],},});chart.render();
说明:
path
配置将扁平化数据转换为层次结构layout.tile
设置为 treemapBinary
使用二分布局算法paddingInner
设置矩形间的内边距,增强视觉分离效果例子 2: 展示预算分配情况
矩形树图非常适合展示预算在不同项目和子项目之间的分配情况,帮助管理者快速了解资源配置。
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const budgetData = {name: '年度预算',children: [{name: '研发部门',children: [{ name: '前端开发', value: 1200 },{ name: '后端开发', value: 1500 },{ name: '测试', value: 800 },{ name: '设计', value: 600 },],},{name: '市场部门',children: [{ name: '广告投放', value: 2000 },{ name: '活动策划', value: 800 },{ name: '内容营销', value: 500 },],},{name: '运营部门',children: [{ name: '客户服务', value: 700 },{ name: '数据分析', value: 400 },{ name: '运营支持', value: 300 },],},{ name: '其他支出', value: 1200 },],};chart.options({type: 'treemap',data: { value: budgetData },layout: {tile: 'treemapSquarify',paddingInner: 2,},encode: {value: 'value',color: (d) => d.path[1] || d.data.name,},style: {labelText: (d) => d.data.name,labelFill: '#fff',labelStroke: '#000',labelLineWidth: 0.5,labelFontSize: 12,},tooltip: {title: (d) => d.data.name,items: [{ field: 'value', name: '预算', valueFormatter: (v) => `${v}万元` },],},});chart.render();
说明:
path
tile: 'treemapSquarify'
使用黄金比例算法,产生更接近正方形的矩形labelPosition: 'center'
将标签居中显示例子 3: 展示销售数据层次
矩形树图可以有效展示销售数据的多层级结构,从地区到产品类别再到具体产品。
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const salesData = {name: '全国销售',children: [{name: '华东地区',children: [{name: '数码产品',children: [{ name: '手机', value: 3200 },{ name: '电脑', value: 2800 },{ name: '平板', value: 1500 },],},{name: '家电',children: [{ name: '冰箱', value: 2100 },{ name: '洗衣机', value: 1800 },{ name: '空调', value: 2500 },],},],},{name: '华北地区',children: [{name: '数码产品',children: [{ name: '手机', value: 2800 },{ name: '电脑', value: 2400 },{ name: '平板', value: 1200 },],},{name: '家电',children: [{ name: '冰箱', value: 1900 },{ name: '洗衣机', value: 1600 },{ name: '空调', value: 2200 },],},],},{name: '华南地区',children: [{ name: '数码产品', value: 2200 },{ name: '家电', value: 1800 },],},],};chart.options({type: 'treemap',data: { value: salesData },layout: {tile: 'treemapSliceDice',paddingInner: 3,layer: 2, // 只显示前两层},encode: {value: 'value',color: (d) => d.path[1] || 'default',},style: {labelText: (d) => {const name = d.data.name;const value = d.value;return d.depth <= 1 ? `${name}\n${Math.round(value)}万` : name;},labelFill: '#000',labelFontSize: (d) =>Math.max(10, Math.min(16, Math.sqrt(d.x1 - d.x0) * 2)),stroke: '#fff',lineWidth: 2,},interaction: {treemapDrillDown: {breadCrumbY: 12,activeFill: '#873bf4',breadCrumbFill: 'rgba(0, 0, 0, 0.85)',breadCrumbFontSize: 12,},},legend: false,});chart.render();
例子 1: 数值差异极小的数据对比
当数据中各项目的数值差异很小时,矩形树图的面积差异不明显,用户难以感知到数值的细微差别。
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});// 数值差异很小的数据const similarData = {name: '地区销售(相似数值)',children: [{ name: '北京', value: 9995 },{ name: '上海', value: 10001 },{ name: '广州', value: 9999 },{ name: '深圳', value: 10003 },{ name: '杭州', value: 9997 },{ name: '南京', value: 10002 },],};chart.options({type: 'treemap',data: { value: similarData },encode: { value: 'value' },style: {labelText: (d) => `${d.data.name}\n${d.value}`,labelFill: '#000',},});chart.render();
柱状图(推荐)
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const similarDataFlat = [{ name: '北京', value: 9995 },{ name: '上海', value: 10001 },{ name: '广州', value: 9999 },{ name: '深圳', value: 10003 },{ name: '杭州', value: 9997 },{ name: '南京', value: 10002 },];chart.options({type: 'interval',data: similarDataFlat,encode: { x: 'name', y: 'value', color: 'name' },axis: {y: { nice: false, domain: [9990, 10010] }, // 缩小Y轴范围突出差异},});chart.render();
说明:当数据值差异小于 5% 时,矩形树图的面积差异几乎不可感知,此时建议使用柱状图并调整 Y 轴范围来突出差异。
例子 2: 非层次化的简单分类数据
对于没有层次关系的简单分类数据,矩形树图会显得过于复杂,不如饼图或柱状图直观。
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});// 简单的分类数据,没有层次关系const simpleData = {name: '产品销量',children: [{ name: '产品A', value: 230 },{ name: '产品B', value: 180 },{ name: '产品C', value: 150 },{ name: '产品D', value: 120 },],};chart.options({type: 'treemap',data: { value: simpleData },encode: { value: 'value' },style: {labelText: (d) => d.data.name,labelFill: '#000',},});chart.render();
饼图(推荐)
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const simpleDataFlat = [{ name: '产品A', value: 230 },{ name: '产品B', value: 180 },{ name: '产品C', value: 150 },{ name: '产品D', value: 120 },];chart.options({type: 'interval',data: simpleDataFlat,encode: { y: 'value', color: 'name' },transform: [{ type: 'stackY' }],coordinate: { type: 'theta' },legend: {color: { position: 'right' },},});chart.render();
说明:对于简单的分类占比数据,饼图能更直观地展示各部分在整体中的比例关系。
矩形树图最强大的功能之一是支持下钻交互,用户可以点击某个区域来深入查看该层级的详细信息:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const drillDownData = {name: '商品',children: [{name: '文具',children: [{name: '笔类',children: [{ name: '铅笔', value: 430 },{ name: '圆珠笔', value: 530 },{ name: '钢笔', value: 80 },{ name: '水彩笔', value: 130 },],},{ name: '笔记本', value: 160 },{ name: '文件夹', value: 90 },{ name: '其他', value: 80 },],},{name: '零食',children: [{ name: '饼干', value: 280 },{ name: '辣条', value: 150 },{ name: '糖果', value: 210 },{name: '饮品',children: [{ name: '可乐', value: 122 },{ name: '矿泉水', value: 244 },{ name: '果汁', value: 49 },{ name: '牛奶', value: 82 },],},{ name: '其他', value: 40 },],},{ name: '其他商品', value: 450 },],};chart.options({type: 'treemap',data: { value: drillDownData },layout: {tile: 'treemapBinary',paddingInner: 5,},encode: { value: 'value' },style: {labelFill: '#000',labelStroke: '#fff',labelLineWidth: 1.5,labelFontSize: 14,labelPosition: 'top-left',labelDx: 5,labelDy: 5,},interaction: {treemapDrillDown: {breadCrumbY: 12,activeFill: '#873bf4',breadCrumbFill: 'rgba(0, 0, 0, 0.85)',breadCrumbFontSize: 12,},},tooltip: {title: (d) => d.data.name,items: [{ field: 'value', name: '数量' }],},});chart.render();
通过丰富的样式配置,可以创建个性化的矩形树图:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const customData = {name: '技术栈',children: [{name: '前端',children: [{ name: 'React', value: 45 },{ name: 'Vue', value: 35 },{ name: 'Angular', value: 20 },],},{name: '后端',children: [{ name: 'Node.js', value: 40 },{ name: 'Python', value: 35 },{ name: 'Java', value: 25 },],},{name: '数据库',children: [{ name: 'MySQL', value: 50 },{ name: 'MongoDB', value: 30 },{ name: 'Redis', value: 20 },],},],};chart.options({type: 'treemap',data: { value: customData },layout: {tile: 'treemapResquarify',paddingInner: 4,paddingOuter: 2,},encode: {value: 'value',color: (d) => d.path[1] || 'default',},scale: {color: {range: ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD'],},},style: {labelText: (d) => d.data.name,labelFill: '#fff',labelStroke: '#000',labelLineWidth: 1,labelFontSize: (d) => Math.max(10, Math.min(18, (d.x1 - d.x0) * 0.1)),labelFontWeight: 'bold',stroke: '#fff',lineWidth: 3,radius: 4, // 圆角fillOpacity: 0.9,shadowColor: 'rgba(0, 0, 0, 0.1)',shadowBlur: 4,shadowOffsetX: 2,shadowOffsetY: 2,},interaction: [{type: 'elementHighlight',},],});chart.render();
通过渐变色可以增强矩形树图的视觉效果:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',autoFit: true,});const gradientData = {name: '市场份额',children: [{ name: '阿里巴巴', value: 28 },{ name: '腾讯', value: 25 },{ name: '字节跳动', value: 18 },{ name: '美团', value: 15 },{ name: '京东', value: 12 },{ name: '百度', value: 10 },{ name: '网易', value: 8 },{ name: '小米', value: 7 },{ name: '滴滴', value: 6 },{ name: '拼多多', value: 5 },{ name: '新浪', value: 4 },{ name: '搜狐', value: 3 },{ name: '360', value: 2 },{ name: '其他', value: 7 },],};chart.options({type: 'treemap',data: { value: gradientData },layout: {tile: 'treemapSquarify',paddingInner: 3,},encode: {value: 'value',color: 'value',},scale: {color: {type: 'sequential',range: ['#E8F4FD', '#1890FF'],},},style: {labelText: (d) => `${d.data.name}\n${d.value}%`,labelFill: (d) => (d.value > 20 ? '#fff' : '#000'),labelFontSize: 14,labelFontWeight: 'bold',stroke: '#fff',lineWidth: 2,},tooltip: {title: (d) => d.data.name,items: [{ field: 'value', name: '市场份额', valueFormatter: (v) => `${v}%` },],},});chart.render();
矩形树图和旭日图都可以展示层次化数据,但有不同的特点:
对比维度 | 矩形树图 | 旭日图 |
---|---|---|
视觉形式 | 矩形布局 | 圆形布局 |
空间利用 | 矩形填充,利用率高 | 圆形边界,利用率较低 |
比例感知 | 面积比较,更准确 | 角度比较,适中 |
层次展示 | 嵌套矩形,包含关系明确 | 同心圆,层次关系清晰 |
适用场景 | 强调精确的比例对比 | 强调层次关系和整体结构 |
矩形树图相比饼图的优势:
饼图的优势: