☰
F2 环形图(Donut Chart)实战指南:极坐标、中心文本与嵌套环图实现
2026/9/27 7:58:21 网站建设 项目流程
  • 数据可视化
  • 前端

【免费下载链接】F2

📱📈An elegant, interactive and flexible charting library for mobile.

项目地址:https://gitcode.com/gh_mirrors/f2/F2
点击查看免费下载

F2 是一个面向移动端的优雅、交互式且灵活的图表库。本篇指南以site/examples/pie/donut示例模块为核心,系统讲解如何在 F2 中实现环形图(Donut Chart)——从基础环形图与中心总计文本,到圆角环形图、双环形图、嵌套环图和环形进度条。读者完成后将掌握polar极坐标、innerRadius内半径、Interval + adjust="stack"堆叠扇区、Legend图例定制以及ArcGuide/TextGuide辅助标记的完整组合用法。

什么是环形图:饼图的变形

环形图是饼图的一种变形,通过中空的圆环形状来展示数据的占比关系(参见 donut 示例文档)。相比传统饼图,环形图的中心空白区域可以用来显示总计信息或其他重要数据,同时保持了饼图直观展示比例的特点。

在 F2 中,环形图并不是一个独立的 Chart 类型,而是通过**极坐标(polar)坐标系 + 转置(transposed)+ 内半径(innerRadius)**组合出的形态。其底层实现位于 packages/f2/src/coord/polar.ts:当坐标系为polar且transposed: true时,数据维度 x 被映射为弧度、y 被映射为半径,配合innerRadius挖空圆心,即得到环形。

基础环形图:完整可运行示例

环形图目录(site/examples/pie/donut/demo)下的第一个示例 donut.jsx 展示了带有中心文本的环形图,可在中心显示总计信息。

/** @jsx jsx */ import { Canvas, Chart, Interval, jsx, Legend } from '@antv/f2'; const data = [ { name: '股票类', percent: 83.59, a: '1' }, { name: '债券类', percent: 2.17, a: '1' }, { name: '现金类', percent: 14.24, a: '1' }, ]; const context = document.getElementById('container').getContext('2d'); const map = {}; data.forEach(function (obj) { map[obj.name] = obj.percent + '%'; }); const Text = (props, context) => { const { coord } = props; const { center } = coord; return ( <group style={{ display: 'flex', left: center.x, top: center.y - context.px2hd('30px'), width: '100px', }} > <text style={{ text: '总资产', fill: '#000', textAlign: 'center' }} /> <text style={{ marginTop: '10px', text: '100.33亿元', fill: '#000', textAlign: 'center' }} /> </group> ); }; const { props } = ( <Canvas context={context} pixelRatio={window.devicePixelRatio} theme={{ padding: [20, 'auto'] }}> <Chart scale={{ percent: { formatter: function formatter(val) { return val + '%'; }, }, }} data={data} coord={{ type: 'polar', transposed: true, innerRadius: 0.7, radius: 0.85, }} > <Interval x="a" y="percent" adjust="stack" color={{ field: 'name', range: ['#FE5D4D', '#3BA4FF', '#737DDE'], }} /> <Legend position="right" itemFormatter={(val, name) => { return map[name]; }} /> <Text /> </Chart> </Canvas> ); const chart = new Canvas(props); chart.render();

关键点拆解如下:

  • coord.type: 'polar':切换到极坐标系,x 轴代表弧度、y 轴代表半径。
  • transposed: true:转置坐标系,让分类字段a沿角度方向排布、数值字段percent沿半径方向延伸,这是扇区正确展开的前提。
  • innerRadius: 0.7:内半径占外半径的 70%,挖空中心形成"环";该值越大,圆环越细。
  • radius: 0.85:外半径占绘图区域短边一半的 85%,为图例和中心文本留出边距。
  • Interval x="a" y="percent" adjust="stack":用区间图形叠加成"堆叠"扇区;所有数据行的a均为'1',因此各分类在同一个角度范围内按percent比例堆叠,构成完整圆环。
  • color字段映射:field: 'name'让每个分类拥有独立颜色,range自定义调色板。
  • 中心文本:通过自定义组件读取coord.center拿到圆心坐标,配合px2hd完成高清适配下的像素换算,将"总资产 / 100.33亿元"渲染在环心。
  • 图例:Legend position="right"将图例放在右侧,itemFormatter把默认项名替换为map[name](即百分比字符串),使图例直接显示83.59%之类的占比信息。

核心原理:polar 坐标系与 innerRadius 的底层实现

环形图的形态完全由 packages/f2/src/coord/polar.ts 中的Polar类决定。在update中可以看到两个配置的默认值与换算逻辑:

const { radius: radiusRatio = 1, innerRadius: innerRadiusRatio = 0 } = this.option; // 半径取宽高的最小值 const radius = radiusRatio * (Math.min(width, height) / 2); // 极坐标下 x 表示弧度,y 代表半径 const x: Range = [startAngle, endAngle]; const y: Range = [innerRadiusRatio * radius, radius];
  • radius默认为 1,表示外半径取绘图区域宽高中较小值的一半;
  • innerRadius默认为 0,即默认绘制实心饼图;只有显式设置大于 0 的值(如示例中的0.7),y 值域下界才从圆心抬升到innerRadius * radius,从而挖出中空圆环;
  • 角度默认从-Math.PI / 2(12 点方向)顺时针到3 * Math.PI / 2,对应完整一圈。

convertPoint将归一化数据映射为画布坐标:angle = xStart + (xEnd - xStart) * point[xDim]、radius = yStart + (yEnd - yStart) * point[yDim],最终得到center + (cos(angle) * radius, sin(angle) * radius)。理解了这一换算,就能直观推断innerRadius、radius两个参数对环粗细与留白的影响。基类 packages/f2/src/coord/base.ts 中的transposed字段负责在极坐标下交换 x/y 维度的映射角色,正是"角度—半径"布局得以实现的基础。

圆角环形图:扇区圆角样式

donut-radius.jsx 展示了如何为环形图扇区添加圆角,适合营造柔和、现代的数据可视化风格。核心做法是在Interval上通过style配置radius数组:

<Interval x="a" y="percent" adjust="stack" color={{ field: 'name', range: ['#1890FF', '#13C2C2', '#2FC25B', '#FACC14', '#F04864', '#8543E0'], }} style={{ radius: [10, 7, 4, 2], }} />

这里的style.radius为扇区四个角指定圆角半径(依次对应左上、右上、右下、左下或按内部绘制顺序解释的角),数值越大圆角越明显。该示例的innerRadius设为 0.5,得到中等粗细的圆环,同时Legend使用默认位置展示分类名称。

双环形图:同一 Canvas 布局两个图表

double-donut.jsx 展示了在同一个Canvas中并排渲染两个环形图的方法:通过给Chart设置style中的width与left控制横向布局,两份数据与配置相同的图表即可并排呈现,适合对比两个同构数据集(例如两个账户的资产构成)。

<Canvas context={context} pixelRatio={window.devicePixelRatio} theme={{ padding: [20, 'auto'] }}> <Chart ... style={{ width: 200 }}> {/* 第一个环形图:图例在 bottom */} </Chart> <Chart ... style={{ left: 200, width: 200 }}> {/* 第二个环形图:图例在 bottom,left 偏移 200 实现并排 */} </Chart> </Canvas>

值得注意的细节:

  • 每个Chart均需独立配置scale、data、coord与子组件;
  • theme={{ padding: [20, 'auto'] }}让上下留白固定为 20、左右自动计算;
  • 中心文本组件Text在每个图表中复用,读取各自coord.center定位;
  • 两图图例均放底部(position="bottom"),避免与并排布局冲突。

嵌套环图:多分类维度的堆叠

cascade.jsx 展示了用单一数据源绘制多环嵌套结构的能力。其数据包含两个分组字段:a(内环分类,取值为 1/2/3)与c(外环分类,取值为 1/2),通过color="c"让颜色随外层分类变化,同时adjust="stack"将同一a下的数据堆叠,形成内外两层嵌套环的视觉效果。

<Chart data={data} coord={{ type: 'polar', transposed: true, innerRadius: 0.5 }} > <Interval x="a" y="b" color="c" adjust="stack" /> <Legend position="top" /> </Chart>

该实现的关键在于:极坐标下 x 维度的每个取值对应一圈扇区(a = '1'、'2'、'3'各占 120°),而堆叠后c的不同取值在同一角度范围内按b数值分层,视觉上自然形成"内环为分类、外环为子项占比"的嵌套结构。图例置于顶部以容纳更多分类。

环形进度条:ArcGuide + TextGuide 组合

progress-bar.jsx 将环形图的思路应用到进度条场景:用一条灰色底环 + 一段蓝色高亮弧表示进度,并在环心显示百分比文本。它不再使用Legend,而是引入两个辅助标记组件ArcGuide与TextGuide(从@antv/f2直接导入):

import { jsx, Canvas, Chart, Interval, TextGuide, ArcGuide } from '@antv/f2'; const data = [{ x: '1', y: 85 }]; <Chart data={data} coord={{ type: 'polar', transposed: true, innerRadius: 0.8 }} scale={{ y: { max: 100, min: 0 }, }} > <ArcGuide records={[ { x: 0, y: 0 }, { x: 1, y: 99.98 }, ]} style={{ lineWidth: 11, stroke: '#ccc' }} /> <TextGuide records={[{ x: '1', y: '25%' }]} content={'85%'} style={{ fill: '#1890FF' }} /> <Interval x="x" y="y" /> </Chart>

要点说明:

  • scale.y限定 0~100:让单个数据点y: 85对应整个环的 85%,从而精确控制进度弧长;
  • ArcGuide:records给出弧的起止归一化坐标,style.lineWidth: 11控制环的粗细,stroke: '#ccc'作为灰色底环;
  • Interval:绘制蓝色进度弧(沿用默认主题色),innerRadius: 0.8使环较细,进度视觉更清晰;
  • TextGuide:records中的y: '25%'表示沿半径方向 25% 处,content直接指定要显示的文本(如85%),fill设置颜色。

这套组合把"数据可视化"与"信息标注"分离:Interval负责数据层,ArcGuide/TextGuide负责背景与标注层,是 F2 组件化设计(参见 guide 组件目录)的典型应用。

使用场景总结

环形图在 F2 中适用于以下场景(归纳自 donut 示例文档 与各示例):

  1. 展示数据占比的同时显示总计信息:基础环形图在环心放置"总资产 / 100.33亿元"式的汇总文本;
  2. 节省空间的比例展示:圆环比实心饼图视觉更轻盈,中心还可承载其他信息;
  3. 突出显示重要的汇总数据:环形进度条用大字号百分比 + 高亮弧突出单一指标;
  4. 多层级数据的嵌套展示:嵌套环图用多层圆环表达分类与子类的层级占比;
  5. 多数据集的并排对比:双环形图在同一画布内横向呈现两个同构数据集的构成。

延伸阅读

  • 完整示例源码与配套说明见 site/examples/pie/donut(目录内含 index.zh.md 与全部 demo);
  • 示例清单及标题配置见 meta.json;
  • 极坐标实现源码见 packages/f2/src/coord/polar.ts,坐标系基类见 packages/f2/src/coord/base.ts;
  • 饼图/环形图相关的完整测试用例可参考 packages/f2/test/components/pieLabel 与 packages/f2/test/components/legend 目录,用于验证图例与标签在极坐标下的渲染行为。
  • 数据可视化
  • 前端

【免费下载链接】F2

📱📈An elegant, interactive and flexible charting library for mobile.

项目地址:https://gitcode.com/gh_mirrors/f2/F2
点击查看免费下载
上一篇:突破布料渲染难题:RenderDoc法线贴图可视化与调试全指南
下一篇:如何彻底解决ViewerJS安全隐患:内容安全策略(CSP)实施指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询