- 数据可视化
- 前端
【免费下载链接】F2
📱📈An elegant, interactive and flexible charting library for mobile.
折线图是 F2(AntV 面向移动端的可视化图表库)中最常用的几何标记(Geometry)之一,用于通过连接各数据点形成的折线展示数据随时间或其他有序变量的变化趋势。本文以仓库中 基础折线图示例 为核心骨架,结合 Line 组件 API 文档、示例源码 以及 底层实现,带你从零构建基础折线图,并逐级进阶到带数据点、平滑曲线、阶梯线以及支持手势平移的折线图,最后深入源码理解 F2 折线图的映射与渲染原理。
折线图与 F2 中的使用场景
折线图是一种常用的统计图表,通过连接各个数据点形成折线来展示数据的变化趋势。它特别适合展示连续数据随时间或其他有序变量的变化情况,能够清晰地反映数据的趋势和波动。
在 F2 中,折线图由Line几何标记组件承担,官方将其定位为"用于绘制折线图、曲线图、阶梯线图等"的图表类型,并且继承自几何标记 Geometry。具体适用于以下典型场景:
- 展示时间序列数据的变化趋势,例如站点访问量、气温逐日变化;
- 对比多个数据系列的走势,通过
color字段映射实现多系列折线; - 分析数据的周期性和波动性,例如量价数据的高低起伏;
- 预测和趋势分析,从已有序列的走向推断后续形态。
基础折线图:最小可运行示例
先看最精简的写法——这也是官方示例的骨架:
import { jsx, Canvas, Chart, Line, Axis, Tooltip } from '@antv/f2'; const { props } = ( <Canvas context={context}> <Chart data={data}> <Axis field="date" /> <Axis field="value" /> <Line x="date" y="value" /> <Tooltip /> </Chart> </Canvas> );其中:
Canvas:图表画布,接收context(canvas 2d 上下文)与pixelRatio;Chart:图表容器,承载data数据;Axis:坐标轴,分别声明 x 轴(date字段)与 y 轴(value字段);Line:核心几何标记,通过x/y指定数据映射字段;Tooltip:交互提示,用于展示数据点详情。
完整可运行版本
官方演示代码 给出了更完整的可直接运行版本,包括 49 条 2017-06-05 至 2017-07-24 的日度数值数据,以及坐标轴刻度配置:
/** @jsx jsx */ import { jsx, Canvas, Chart, Line, Axis, Tooltip } from '@antv/f2'; const data = [ { date: '2017-06-05', value: 116 }, { date: '2017-06-06', value: 129 }, // ... 其余数据点 { date: '2017-07-24', value: 60 }, ]; const context = document.getElementById('container').getContext('2d'); const LineChart = ( <Canvas context={context} pixelRatio={window.devicePixelRatio}> <Chart data={data}> <Axis field="date" tickCount={3} style={{ label: { align: 'between' }, }} /> <Axis field="value" tickCount={5} /> <Line x="date" y="value" /> <Tooltip /> </Chart> </Canvas> ); const chart = new Canvas(LineChart.props); chart.render();几个值得注意的细节:
pixelRatio={window.devicePixelRatio}保证移动端高分屏下线条清晰;- x 轴
tickCount={3}限制刻度数量,label.align: 'between'让标签对齐到刻度区间之间(类别轴常见做法); - y 轴
tickCount={5}控制数值轴刻度密度; - 通过
new Canvas(LineChart.props)实例化并render()渲染。
进阶用法:四种常见变体
官方进阶演示 列出了四种实用变体,全部源码可在site/examples/line/line/demo/目录下找到。
带点折线图:突出每个数据值
在Line之后并列声明一个Point几何标记即可,数据点与折线共享相同的x/y字段映射:
/** @jsx jsx */ import { jsx, Canvas, Chart, Line, Point, Axis, Tooltip } from '@antv/f2'; const data = [ { day: '周一', value: 300 }, { day: '周二', value: 400 }, // ... 周三到周日 { day: '周日', value: 900 }, ]; const { props } = ( <Canvas context={context} pixelRatio={window.devicePixelRatio}> <Chart data={data}> <Axis field="day" tickCount={3} style={{ label: { align: 'between' } }} /> <Axis field="value" tickCount={5} /> <Line x="day" y="value" /> <Point x="day" y="value" /> <Tooltip /> </Chart> </Canvas> ); const chart = new Canvas(props); chart.render();完整代码见 with-point.jsx。数据点样式(circle、hollowCircle、rect)可在主题 shapes 配置 中查看,默认点形状为圆形。
平滑折线图:更流畅的趋势展示
通过shape="smooth"让折线变为平滑曲线:
const scale = { time: { type: 'timeCat', mask: 'MM/DD', tickCount: 3, range: [0, 1], }, tem: { tickCount: 5, min: 0, alias: '日均温度', }, }; const LineChart = ( <Canvas context={context} pixelRatio={window.devicePixelRatio}> <Chart data={data} scale={scale}> <Axis field="time" style={{ label: { align: 'between' } }} /> <Axis field="tem" /> <Line x="time" y="tem" shape="smooth" /> <Tooltip /> </Chart> </Canvas> );完整代码见 smooth.jsx。这段示例还演示了scale的高级用法:
time字段使用timeCat(时间类型序数)比例尺,mask: 'MM/DD'控制时间标签格式,range: [0, 1]让折线铺满绘图区;tem字段设置min: 0与别名alias: '日均温度',Tooltip 中会显示该别名。
smooth是主题中内置的 shape 之一,对应的默认样式在 theme.ts 中定义为{ smooth: true },折线组件的平滑渲染由 areaView 中调用的Smooth.smooth曲线插值逻辑完成(见 areaView.tsx)。
阶梯折线图:展示阶段性变化
使用shape的对象形式按字段映射阶梯步进方式,这是多系列 + shape 映射的典型用法:
const data = []; [ { time: '2016-08-01', tem: 15, type: 'start' }, // ... 每个日期生成 type 分别为 start / middle / end 的三条数据 ].map((d) => { data.push(d); data.push({ ...d, tem: d.tem + 15, type: 'middle' }); data.push({ ...d, tem: d.tem + 30, type: 'end' }); }); const { props } = ( <Canvas context={context}> <Chart data={data}> <Axis field="time" tickCount={2} style={{ label: { align: 'between' } }} /> <Axis field="tem" tickCount={5} max={60} /> <Line x="time" y="tem" color="type" shape={{ field: 'type', range: ['step-start', 'step-middle', 'step-end'], }} /> </Chart> </Canvas> );完整代码见 step.jsx。这里通过数据构造将每个日期生成start/middle/end三条记录,再以color="type"映射出三条不同颜色的阶梯线,shape的range则分别对应三种阶梯步进方式。三个阶梯 shape 的内置样式定义在 theme.ts:
| shape 值 | 内置样式 |
|---|---|
step-start | step: 'start',台阶先水平后垂直 |
step-middle | step: 'middle',台阶居中过渡 |
step-end | step: 'end',台阶先垂直后水平 |
可平移折线图:手势滑动浏览长序列
当数据序列很长时,可配合ScrollBar实现"视口 + 平移"的交互:
import { jsx, Canvas, Chart, Line, Point, Axis, ScrollBar } from '@antv/f2'; fetch('https://gw.alipayobjects.com/os/antfincdn/Jpuku6k%24q%24/linear-pan.json') .then((res) => res.json()) .then((data) => { const { props } = ( <Canvas context={context} animate={false} pixelRatio={window.devicePixelRatio}> <Chart data={data}> <Axis field="release" tickCount={5} nice={false} /> <Axis field="count" /> <Line x="release" y="count" /> <Point x="release" y="count" /> <ScrollBar mode="x" range={[0.1, 0.3]} /> </Chart> </Canvas> ); const chart = new Canvas(props); chart.render(); });完整代码见 pan.jsx。关键点:
ScrollBar mode="x"声明 x 方向滚动条,range={[0.1, 0.3]}表示初始视口显示数据区间的 10%~30%;Axis field="release" tickCount={5} nice={false}关闭刻度取整(nice),避免平移时坐标轴刻度跳变;animate={false}关闭进场动画,保证滑动过程流畅;- 数据通过
fetch异步加载,渲染放在.then回调中执行。
深入源码:F2 折线图的底层原理
组件结构与默认配置
Line组件由三部分组成(见 components/line 目录):
index.tsx:导出withLine(LineView)包装后的组件;withLine.tsx:继承Geometry的高阶组件,负责数据映射与分段;lineView.tsx:纯渲染视图,负责把映射结果绘制成polyline。
在 withLine.tsx 中可以看到 Line 的默认配置:
getDefaultCfg() { return { geomType: 'line', sortable: true, // 数据按 x 排序后再连线 }; }同时LineProps接口声明了折线图特有属性(见 withLine.tsx):
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
connectNulls | boolean | false | 是否连接空值点,为true时跳过 NaN 点直接连线 |
sizeZoom | number \| (record) => number | 1 | 线条宽度的缩放比例,支持按数据记录回调计算 |
endView | 组件 | - | 动画结束后显示的自定义视图(接收{ origin }) |
空值处理与折线分段
折线图在遇到数据中有NaN时会自动分段。核心逻辑是splitNulls方法(withLine.tsx):
- 当
connectNulls为false(默认)时,遇到NaN点就把当前线段切断,返回多条子折线,这也是 空数据示例 中折线断开的根本原因; - 当
connectNulls为true时,直接过滤掉NaN点,把所有有效点连成一条线。
此外,当 y 字段映射的是数组(如区间数据)时,splitPoints会把每条记录拆成上边界点与下边界点两组(withLine.tsx),concatPoints再决定是否拼接闭合(堆叠adjust: 'stack'时只绘制上边界,见 withLine.tsx)。
映射与渲染流程
mapping()方法(withLine.tsx)完成核心的数据到图形属性的转换:
- 调用父类
super.mapping()得到记录级数据; - 极坐标(雷达图)场景下,把首点追加到末尾以闭合图形(
coord.isPolar判断); - 用
context.px2hd(size)将主题中'4px'这类带单位的线宽换算成高清屏像素,再乘以sizeZoomRatio; - 返回每个子折线的
points、topPoints、bottomPoints等映射结果。
render()最后把映射结果连同裁剪区域传给视图层。在 lineView.tsx 中,每个子折线最终被渲染为<polyline>,并内置了默认动画:
update(数据更新):easing: 'linear',时长 450ms,动画属性为points(折线顶点平滑过渡);appear(进场):直角坐标系下用rect裁剪实现从左到右的擦除效果,极坐标系下用sector扇形裁剪,时长均为 450ms、缓动quadraticOut(见 lineView.tsx)。
这也是 API 文档中描述的"Line 组件默认使用从左到右的擦除效果"的源码出处。若不需要动画,可在Canvas上设置animate={false},如上述平移示例所示。
Line 组件属性速查
Line继承自 Geometry,除x/y外,常用属性汇总如下(详见 line.zh.md):
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
color | string \| object \| array | - | 颜色映射,支持固定值、字段映射、[字段, 颜色数组]与{ field, range, callback }对象 |
size | string \| object \| array \| number | - | 线宽映射,格式同color |
style | object | - | 图形样式,如stroke、lineWidth、lineDash、lineCap、lineJoin、shadowColor等 |
shape | string \| object | 'line' | 折线形态:line/dash/smooth/step-start/step-middle/step-end |
adjust | string | - | 数据调整:stack/dodge/symmetric |
startOnZero | boolean | false | y 轴是否从 0 开始 |
viewClip | boolean | false | 是否只显示两轴之间的部分 |
animation | object \| false | 内置 | 按appear/update/leave三阶段配置动画 |
connectNulls | boolean | false | 是否连接空值点 |
sizeZoom | number \| function | 1 | 线条宽度缩放比例 |
线条样式常用项:lineWidth(默认1,主题中折线默认'4px'经px2hd换算)、strokeOpacity(0-1)、lineCap(butt/round/square)、lineJoin(bevel/round/miter)、lineDash(如[5, 5]表示 5px 实线 + 5px 空白)、shadowBlur(阴影模糊)等。默认折线线宽'4px'、圆角端点与圆角连接的配置可在 theme.ts 中查看。
小结
从基础折线到带点、平滑、阶梯与平移交互,F2 的Line组件覆盖了移动端趋势图表的绝大多数需求。本文对应的五个可运行示例均位于 site/examples/line/line/demo 目录,相关测试用例(含多组快照回归)可参考 packages/f2/test/components/line。实际项目中,建议按数据形态选择 shape(趋势平滑用smooth、阶段变化用阶梯、长序列加ScrollBar平移),并结合scale与坐标轴配置控制刻度和标签密度,即可快速产出适合移动端屏幕的高质量折线图。
- 数据可视化
- 前端
【免费下载链接】F2
📱📈An elegant, interactive and flexible charting library for mobile.
相关推荐
Altair 折线图(line mark)完全指南:从基础绘制到交互式多系列与地理折线
Altair 折线图(line mark)完全指南:从基础绘制到交互式多系列与地理折线 导读 本文基于 Altair 官方用户指南中的折线图(line mark
数据可视化LogicFlow graphModel 完全指南:画布运行时 Model 的属性、方法与实战
LogicFlow graphModel 完全指南:画布运行时 Model 的属性、方法与实战 graphModel 是 LogicFlow 整个画布对应的运行
数据可视化前端bqplot基础绘图教程:从折线图到柱状图实战
bqplot基础绘图教程:从折线图到柱状图实战 引言:为什么选择bqplot? 还在为Jupyter Notebook中的静态图表而烦恼吗?想要创建交互式、动态
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考