- 数据可视化
- 前端
【免费下载链接】F2
📱📈An elegant, interactive and flexible charting library for mobile.
坐标轴(Axis)是 F2 图表中承载数据范围与刻度信息的核心组件,它决定了用户如何读取数据分布与变化趋势。本篇指南以 F2 官方示例文档为骨架,围绕labelAutoRotate(自动旋转)、labelAutoHide(自动隐藏)两项高频能力展开,并结合仓库源码与测试用例,深入讲解 Axis 的完整 API、样式定制方案与底层工作原理,帮助你彻底掌控移动端图表坐标轴的配置细节。
Axis 在 F2 中的作用
在 F2 中,坐标轴由两个维度的轴组成:分类轴(通常是 x 轴)与数值轴(通常是 y 轴)。Axis 组件负责把数据字段对应的比例尺(Scale)刻度渲染到画布上,包含四个组成元素:
- 网格线(grid):辅助读数的背景线条;
- 刻度线(tickLine):轴上的小刻度标记;
- 轴线(line):坐标轴本体线条;
- 标签(label):每个刻度对应的文本。
这些元素既可以通过style属性逐一定制,也可以整体隐藏。组件本身不产生数据,而是从Chart上读取对应字段的比例尺刻度,再结合坐标系(直角/极坐标)完成定位渲染,入口实现位于 index.tsx,渲染分派逻辑见 axisView.tsx:极坐标下按dimType分派给 PolarX / PolarY,直角坐标下按position分派给 Top / Bottom / Left / Right 四个方向的视图。
基础用法:声明坐标轴
Axis 通常搭配Chart、图形几何(如Interval)一起使用。只需要为每个需要展示的字段声明一个<Axis>,F2 会自动从比例尺中计算并绘制刻度:
import { jsx, Canvas, Chart, Interval, Axis } from '@antv/f2'; const data = [ { category: 'Category1', value: 10 }, // ... ]; const { props } = ( <Canvas context={context} pixelRatio={window.devicePixelRatio}> <Chart data={data}> <Axis field="category" /> <Axis field="value" /> <Interval x="category" y="value" color="#2FC25B" /> </Chart> </Canvas> );field指明该轴绑定的数据字段名,与Interval的x、y映射保持一致。当移动端屏幕宽度有限、分类刻度特别多时,标签很容易互相重叠,此时就需要用到 F2 的标签自动处理能力。
自动旋转标签:labelAutoRotate
当坐标轴标签过长或数量过多时,可以启用自动旋转功能,避免标签重叠。在<Axis>上开启labelAutoRotate={true},F2 会先检测标签是否发生重叠,若重叠则自动为标签计算一个合适的旋转角度,让每个标签都能完整展示:
import { jsx, Canvas, Chart, Interval, Axis } from '@antv/f2'; const data = [ { category: 'Category1', value: 10 }, { category: 'Category2', value: 15 }, { category: 'Category3', value: 20 }, { category: 'Category4', value: 25 }, { category: 'Category5', value: 30 }, { category: 'Category6', value: 35 }, { category: 'Category7', value: 40 }, { category: 'Category8', value: 45 }, { category: 'Category9', value: 50 }, { category: 'Category10', value: 55 }, { category: 'Category11', value: 60 }, { category: 'Category12', value: 65 }, { category: 'Category13', value: 70 }, { category: 'Category14', value: 75 }, { category: 'Category15', value: 80 }, ]; const { props } = ( <Canvas context={context} pixelRatio={window.devicePixelRatio}> <Chart data={data}> <Axis field="category" labelAutoRotate={true} /> <Axis field="value" /> <Interval x="category" y="value" color="#2FC25B" /> </Chart> </Canvas> );对应完整可运行示例位于 labelAutoRotate.jsx。
旋转角度的计算原理
从源码看,自动旋转并非固定角度,而是动态计算的。在 withAxis.tsx 的findSuitableRotation方法中,F2 会:
- 通过
_getXTicksDistance测量相邻两个刻度点之间的平均间距averageSpace; - 用
measureText测量首个标签文本的宽高,取labelHeight; - 结合安全距离(源码中常量
safetyDistance = 2)得到可用纵向空间availableSpace = labelHeight + safetyDistance; - 计算
sinValue = availableSpace / averageSpace,将其钳制在[-1, 1]区间后通过反三角函数Math.asin求出理论角度,再向上取整得到最终旋转角ceiledAngle; - 若角度在
(0, 90]范围内,则为每个 tick 的labelStyle注入transform: rotate(Xdeg),并将align置为start、transformOrigin设为'0 50%'。
这解释了为什么标签数量越多、间距越小,计算出的旋转角会越大;而当标签本身不重叠时(hasOverlap返回 false),则完全不会触发旋转,保持水平展示。
自动隐藏标签:labelAutoHide
当标签数量过多、即使旋转也无法容纳时,可以改用自动隐藏:F2 会检测重叠情况,并按"等间隔抽稀"的策略隐藏部分标签,同时尽可能保留首、尾标签以保证数据范围的语义完整。
import { jsx, Canvas, Chart, Interval, Axis } from '@antv/f2'; const data = Array.from({ length: 100 }, (_, i) => ({ category: `Cat${i + 1}`, value: ((i % 10) + 1) * 10, })); const { props } = ( <Canvas context={context} pixelRatio={window.devicePixelRatio}> <Chart data={data}> <Axis field="category" labelAutoHide={true} /> <Axis field="value" /> <Interval x="category" y="value" color="#722ED1" /> </Chart> </Canvas> );对应完整示例位于 labelAutoHide.jsx。100 个分类刻度在移动端显然无法全部展示,开启后 F2 会自动保留等间隔的若干标签,图表依旧可读。
抽稀策略的源码解读
自动隐藏的核心逻辑在 withAxis.tsx 的findLabelsToHide方法中:
- 先由
hasOverlap计算出所有标签的宽度,得到最大标签宽度maxLabelWidth; - 以
maxLabelWidth / (坐标轴宽度 / 刻度总数)估算初始抽稀步长initialSeq; - 在不超过总刻度一半(
maxSeq = floor(range / 2))的前提下,逐步增大步长,并用hasOverlapAtSeq验证"每隔 N 个刻度取一个标签"是否仍然重叠; - 若始终找不到完美步长,则退化为仅保留第一个与最后一个标签;当总刻度数超过阈值
SHOW_MIDDLE_LABEL_THRESHOLD = 10时,还会额外保留中间位置的标签; - 最终通过给 tick 设置
visible: false来隐藏对应标签,渲染层在 bottom.tsx 中会直接跳过不可见的 tick。
值得注意的是,labelAutoRotate与labelAutoHide可以同时开启:updateCoord中会先检测重叠,若重叠则先尝试旋转(findSuitableRotation),再执行隐藏(findLabelsToHide),两者协同工作(见 withAxis.tsx)。
完整 API 一览
原文档 API 表格中的五个属性全部保留,并补充源码中 types.d.ts 定义的其他常用属性:
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| field | string | - | 绑定的数据字段名 |
| labelAutoRotate | boolean | false | 是否启用标签自动旋转 |
| labelAutoHide | boolean | false | 是否启用标签自动隐藏 |
| safetyDistance | number | 2 | 标签之间的安全距离,用于重叠检测与旋转计算(文档 API 表标注为 0,源码中默认值为 2,以实际源码为准) |
| style | object | - | 自定义样式配置(见下文"样式定制") |
| visible | boolean | true | 是否显示该坐标轴,设为false可整体隐藏 |
| position | string | 自动 | 坐标轴显示位置:'right'/'left'/'top'/'bottom';不传时根据字段维度与是否转置自动推断 |
| formatter | function | - | 刻度文本格式化回调,同时影响 axis、legend、tooltip 上的显示 |
| type | string | - | 比例尺类型(如'cat'、'linear'、'timeCat') |
| tickCount | number | - | 刻度数量(对连续型比例尺生效) |
| range | any | - | 刻度显示范围 |
| mask | string | - | 时间刻度格式化模板(如'YYYY-MM-DD') |
| min / max | number | - | 强制指定轴的最小值 / 最大值 |
| nice | boolean | - | 是否将刻度取整为友好数值 |
| ticks | Array | - | 手动指定刻度值,测试用例传入 ticks展示了该用法(见 axis.test.tsx) |
| grid | string | - | 极坐标下网格线类型:'line'或'arc' |
safetyDistance 的实际语义
field之外,safetyDistance是影响标签自动处理效果的关键参数。源码中hasOverlapAtSeq(withAxis.tsx)在判断"两个标签的间距是否足够"时,要求相邻标签半宽之和再加上px2hd(safetyDistance)仍小于刻度间距,否则判定为重叠。调大该值会让自动旋转/隐藏更激进(更早触发),调小则更保守。findSuitableRotation内部计算旋转角时同样使用了安全距离 2。
样式定制:style 详解
style是 Axis 最灵活的定制入口,可控制网格线、刻度线、轴线、端部箭头与标签样式。以底部轴渲染实现 bottom.tsx 为准,支持以下字段:
| 字段 | 说明 |
|---|---|
| grid | 网格线样式(stroke、lineWidth、lineDash等),也可传回调函数(text, index, total) => LineStyleProps实现逐条定制 |
| tickLine | 刻度线样式,length控制刻度线长度(如{ length: 3 }) |
| line | 轴线样式,设置line: {}即可显示轴线 |
| symbol | 轴线端部符号(箭头/圆点等),传数组可分别控制两端,如[{ type: 'circle' }, { type: 'arrow' }] |
| label | 标签文本样式,支持fontSize、fill、align、textBaseline等,也可传回调函数逐刻度定制 |
| labelOffset | 标签与轴线之间的距离,支持数值或字符串(如'8px'、'50px') |
| width/height | 手动指定坐标轴占用的宽高(如{ height: '100px' }),覆盖自动测量结果 |
标签对齐与回调定制
label的align属性在底部轴上有更丰富的取值:除常规'left' / 'right' / 'center' / 'start' / 'end'外,还支持'between'与'auto'(见 types.d.ts):
between:让首标签左对齐、尾标签右对齐、中间标签居中,适用于区间型刻度;auto:自动检测标签是否超出轴范围,超出时把标签拉回绘图区内侧,避免被画布裁切。
label和grid都支持回调函数,回调签名分别是(text, index, total),返回样式对象即可实现"按刻度值差异化染色"这类需求。测试用例label 回调中即通过回调让正值显示为红色、负值显示为绿色、零值加粗(见 axis.test.tsx)。同时可用formatter统一改写刻度文本格式,例如formatter={(v) => v.toFixed(2) + '%'}。
坐标轴的测量与布局更新
一个容易被忽略但重要的机制是:坐标轴不只是"画线",它还会主动参与图表整体布局。在 withAxis.tsx 的measureLayout与updateCoord中:
- 组件通过
measureText测量所有标签的最大宽高,加上labelOffset得到轴占用的空间; - 调用
chart.updateCoordFor(this, layout)把该空间从绘图区扣除,确保图形几何(如柱子)不会被坐标轴标签遮挡; - 当开启自动旋转/隐藏时,还会额外为最右侧溢出的标签预留空间(
calculateLabelOverflow计算overflowWidth)。
正因如此,style.width / style.height可以手动覆盖自动测量的布局占用,测试用例定义宽高(axis.test.tsx)展示了<Axis field="time" style={{ height: '100px' }} />的用法。此外,构造 Axis 时还会通过chart.setScale把type / tickCount / range / mask / formatter / min / max / nice / ticks这些比例尺配置注册到 Chart 上(withAxis.tsx),因此轴上的刻度密度、范围与格式化均由 Axis 一处配置即可驱动。
极坐标下的坐标轴
Axis 同样支持极坐标系(雷达图、玫瑰图等)。在coord="polar"下,x 维度轴呈环形、y 维度轴呈放射状,分别由 polar-x.tsx 与 polar-y.tsx 渲染。极坐标下可通过grid: 'arc' | 'line'指定网格线形态,y 轴还会依据 x 轴刻度自动生成环状网格交叉点(_generateGridPoints,见 withAxis.tsx)。测试用例弧形网格线与grid回调(axis.test.tsx)提供了极坐标 + 网格定制、visible={false}隐藏 y 轴等典型写法。
小结
F2 的 Axis 组件以极简的 JSX 声明方式覆盖了移动端坐标轴的全部诉求:标签拥挤时交给labelAutoRotate与labelAutoHide自动处理,观感不满时通过style逐元素定制,刻度语义不对时用formatter、ticks、tickCount等比例尺能力修正,还能在极坐标场景下无缝切换。理解其"测量—布局—渲染"的流水线(withAxis.tsx)与四个方向的渲染实现(rect 目录下的 bottom/left/right/top),即可在实际项目中精准驾驭坐标轴,让移动端图表既紧凑又清晰。
- 数据可视化
- 前端
【免费下载链接】F2
📱📈An elegant, interactive and flexible charting library for mobile.
相关推荐
F2 坐标轴 Axis 组件完全指南:从配置参数到源码原理
F2 坐标轴 Axis 组件完全指南:从配置参数到源码原理 F2 坐标轴(Axis)是图表中承载数据度量映射、展示刻度与网格的关键组件,负责把数据字段转换为可视
数据可视化前端解决90%数据可视化痛点:ECharts坐标轴标签自动旋转完全指南
解决90%数据可视化痛点:ECharts坐标轴标签自动旋转完全指南 你是否还在为长文本标签重叠而烦恼?是否尝试过手动调整旋转角度却效果不佳?本文将系统讲解ECh
数据可视化图表库前端@visx/axis 坐标轴组件全指南:从四个预置轴到自定义渲染
@visx/axis 坐标轴组件全指南:从四个预置轴到自定义渲染 坐标轴(Axis)是图表中帮助读者理解数据的关键元素,它由一条轴线、刻度线(ticks)、刻度
数据可视化前端图表库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考