
鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库 原创 精华
::: hljs-center
UCharts for Harmony
:::
前言
在移动应用开发中,数据可视化是提升用户体验的重要手段。随着 HarmonyOS 生态的快速发展,开发者们迫切需要一款功能强大、易于使用的图表库。今天为大家介绍一款优秀的开源第三方组件 —— UCharts,它为 HarmonyOS 开发者提供了丰富的图表解决方案。
介绍
UCharts 是一个基于 TypeScript 实现的类型丰富、高性能、模块化、可扩展、支持主题定制的跨平台图表库。底层渲染逻辑全部采用 TypeScript 实现,上层通过适配层(adapters)适配到不同平台,包括鸿蒙(HarmonyOS)、微信小程序、uniapp 等,真正实现"一套核心,多端复用"。
现已适配 HarmonyOS 平台。支持多种常用图表类型,满足鸿蒙应用的数据可视化需求。目前代码已经全部开源到Github,三方库中心仓,欢迎各位下载使用并提出宝贵意见!
背景
UCharts的前身uCharts是一款使用JavaScript基于canvas API开发的多平台前端应用图表库,已是2020年开发的版本。旧版本存在的一些架构问题和多端适配耦合问题,面对现如今高速发展的各种前端技术和平台,已不在具有技术优势。
UCharts重新设计了底层架构,模块化开发,核心层只实现与平台无关的渲染逻辑,独立的事件系统和动画系统。上层设计通过适配层适配到不同平台,解耦各个平台的交互逻辑。
用户只需要简单的配置,即可实现各种精美图表的绘制展示,满足各类应用的数据可视化需求。
特性
🧩 模块化设计:底层渲染与平台适配解耦,易于扩展和维护
🛡️ TypeScript 全面支持:类型安全,开发体验优秀
🎨 丰富图表类型:柱状图、条状图、折线图、区域图、山峰图等20种不同类型图表
⚡ 高性能渲染:底层优化,独立的动画和事件系统
🔌 易于扩展:支持自定义图表类型和平台适配
🍭 自定义样式:支持主题定制
支持的图表类型
UCharts 提供了丰富的图表类型,能够满足大部分数据可视化需求:
基础图表
- 柱状图(Column):适用于比较不同类别的数据
- 条形图(Bar):水平方向的柱状图
- 折线图(Line):展示数据随时间的变化趋势
- 面积图(Area):在折线图基础上填充面积
统计图表
- 饼图(Pie):展示数据的占比关系
- 环形图(Ring):饼图的变体,中心留空
- 雷达图(Radar):多维度数据对比
- 散点图(Scatter):展示两个变量之间的关系
专业图表
- K线图(Candle):金融数据可视化
- 仪表盘(Gauge):展示单一指标的完成度
- 热力图(Heatmap):矩阵数据的可视化
- 词云图(Word):文本数据的可视化
特殊图表
- 漏斗图(Funnel):展示业务流程中的转化率
- 玫瑰图(Rose):极坐标下的柱状图
- 气泡图(Bubble):三维数据的可视化
- 山峰图(Mount):地形数据可视化
更多图表类型请查看仓库文档。
下载安装
ohpm install @ibestservices/ucharts
体验预览
升级到 HarmonyOS NEXT 的手机, 可在应用商店搜索 best、ibest 关键字, 下载第一个名为 IBest-UI 的应用, 即可体验。
组件效果展示
UCharts图表通过扩展配置可以呈现出多种样式。下面将展示部分样式绘制效果,更多绘制样式请查看仓库文档。
柱状图
下图展示了一个由随机数据生成的柱状图,并配置了x轴、y轴、辅助线、圆角、自定义颜色等多项配置。
山峰图
下图是基于班级人数绘制的圆角山峰图。
饼状图
下图是基于班级人数比例绘制的饼状图。
词云图
样例解析
图表绘制
如果想要绘制图表,只需要简单几个步骤即可实现:
- 页面中添加图表组件,并为组件初始化控制器。
- 设置图表配置,通过组件控制器更新图表。
import { ChartOptions, UCharts, UChartsController } from '@ibestservices/ucharts'
@Entry
@Component
struct Index {
private chart: UChartsController = new UChartsController();
private opts: Partial<ChartOptions> = {
type: "column",
categories: ["2018","2019","2020","2021","2022","2023"],
series: [
{ name: "目标值", data: [35,36,31,33,13,34]},
{ name: "完成量", data: [18,27,21,24,6,28]}
],
xAxis: { disableGrid: true },
yAxis: { data: [{min: 0}] }
}
build() {
Column(){
UCharts({ controller: this.chart, onReady: () => {
this.chart.updateData(this.opts)
}})
/*
* 或者初始化时传入默认配置
* @State chart: UChartsController = new UChartsController(this.opts);
* UCharts({ controller: this.chart })
* */
}
}
}
扩展属性
每一种图表类型都有其对应的扩展属性配置,除了上面例子中的基础图表绘制。还可通过设置扩展属性来绘制各种丰富的图表样式。其中柱状图扩展属性配置项如下:
/**
* 柱状图扩展配置
*/
export interface ColumnExtra {
type: 'group'|'stack'|'meter' //柱状图类型,可选值:'group'分组柱状图,'stack'堆叠柱状图,'meter'温度计式图,默认group
width: number //柱状图每个柱子的图形宽度
seriesGap: number //多series每个柱子之间的间距
categoryGap: number //每个category点位(X轴点)柱子组之间的间距
barBorderCircle: boolean //启用分组柱状图半圆边框,默认false
barBorderRadius: [number,number,number,number] //自定义4个圆角半径[左上,右上,右下,左下]
linearType: 'none'|'opacity'|'custom' //渐变类型,可选值:"none"关闭渐变,"opacity"透明渐变,"custom"自定义颜色,默认none
linearOpacity: number //透明渐变的透明度(值范围0到1,值越小越透明),默认1
customColor: string[] //自定义渐变颜色,数组类型对应series的数组长度以匹配不同series颜色的不同配色方案,例如["#FA7D8D", "#EB88E2"]
colorStop: number //渐变色的显示比例(值范围0到1,值越大自定义颜色程度越高)
meterBorder: number //温度计式图表的边框宽度,默认1
meterFillColor: string //温度计式图表的空余填充颜色,默认#FFFFFF
activeBgColor: string //当前点击柱状图的背景颜色,默认#000000
activeBgOpacity: number //当前点击柱状图的背景颜色透明度,默认0.08
labelPosition: 'outside'|'insideTop'|'center'|'bottom' //数据标签位置,有效值为"outside"外部,"insideTop"内顶部,"center"内中间,"bottom"内底部,默认outside
}
目录结构
├── core/ # 图表核心能力(平台无关)
│ ├── types/ # 类型定义
│ ├── utils/ # 工具函数
│ ├── chart/ # 各类图表渲染器
│ ├── event/ # 事件系统
│ ├── animation/ # 动画系统
│ └── factory.ts # 图表工厂
├── adapters/ # 平台适配层
│ ├── harmony/ # 鸿蒙适配
│ ├── h5/ # 原生H5适配
│ ├── wechat/ # 微信小程序适配
│ └── uniapp/ # uniapp适配
├── interface/ # 对外统一接口
│ ├── CanvasContext.ts # 跨平台统一 canvas context 接口定义
├── examples/ # 示例代码
├── docs/ # 文档
└── README.md
跨平台适配层说明
- 每个平台在 adapters/ 下有独立目录,负责将平台 API 适配为统一的底层渲染接口。
- 适配层需实现统一的适配接口,并暴露标准的 context、事件等能力。
- 新增平台时,仅需在 adapters/ 下新增目录并实现适配接口,无需修改 core 层代码。
- CanvasContext 统一接口:
- ChartOptions.context 字段要求传入的 canvas context 必须兼容 interface/CanvasContext 类型。
- 各平台适配层需将平台原生 canvas context 封装/适配为该接口,保证 core 层渲染逻辑的统一调用。
- 具体接口定义见 interface/CanvasContext.ts,如需适配新平台,请实现该接口。
开发指南
新增图表类型
- 在 core/chart/ 下创建新的渲染器类,需继承 BaseRenderer,实现通用渲染逻辑。
- 在 core/factory.ts 中注册新图表类型。
- 在 core/types/extra.ts 和 core/types/series.ts 中添加扩展配置类型。
- 更新文档和示例。
新增平台适配层
- 在 adapters/ 下新建平台目录(如 myplatform/)。
- 实现统一适配接口,封装平台 canvas、事件等能力。
- 在平台入口文件(如 index.ts)中暴露适配能力。
- 如有需要暴露给用户层的适配层类型,在 interface/ 下新建对应平台目录并导出。
- 更新文档说明。
配置选项
详见 core/types/ 目录下类型定义,支持丰富的通用与扩展配置。
类型与接口统一导出
为方便用户开发,所有类型和接口均已在 UCharts/interface 统一导出。无论是图表配置类型、CanvasContext 适配类型,还是平台相关类型,均可通过如下方式导入:
import type { ChartOptions, CanvasContext } from 'UCharts/interface';
如需使用平台专属类型,可从 UCharts/interface/harmony 或 UCharts/interface/wechat 等路径导入。例如:
import type { HarmonyCanvasContext } from 'UCharts/interface/harmony';
import type { WechatCanvasContext } from 'UCharts/interface/wechat';
普通用户只需用 UCharts/interface 统一类型即可,平台专属类型仅在需要平台能力扩展时使用。
鸿蒙平台的适配实现
适配 CanvasContext 类型
使用代理模式,实现CanvasContext适配器,拦截 HarmonyOS 平台不支持的属性,进行兼容处理。
// 定义CanvasRenderingContext2D的CanvasContext适配器
class CanvasContextProxy implements ProxyHandler<CanvasRenderingContext2D>, ProxyHandler<CanvasContext> {
// 拦截属性设置操作
set(target: CanvasRenderingContext2D|CanvasContext, propertyKey: string, value: string, receiver: AnyType): AnyType {
// 确保只设置存在的可写属性
if (typeof propertyKey === 'string') {
try {
(target as AnyType)[propertyKey] = value;
return true;
} catch (e) {
console.warn(`无法设置属性 ${String(propertyKey)}`, e);
}
}
return false;
}
get(target: CanvasRenderingContext2D|CanvasContext, propertyKey: string, receiver: AnyType): AnyType {
if (propertyKey === "createCircularGradient") {
return undefined
}
const value: AnyType = (target as AnyType)[propertyKey];
return typeof value === 'function' ? value.bind(target) : value;
}
}
使用CanvasContextProxy适配CanvasRenderingContext2D
const handler = new CanvasContextProxy();
const context = new CanvasRenderingContext2D(new RenderingContextSettings(true));
const canvasContext = new Proxy(context, handler) as CanvasContext;
适配点击和触屏交互
通过将UCharts组件的点击事件和触摸事件坐标点适配到对应核心层接口
onMouseEvent(event: MouseEvent) {
const p: Point = {
x: event.x,
y: event.y
}
if(event.action == MouseAction.Press) {
this.chartRenderer?.scrollStart(p)
this.chartRenderer?.touchLegend(p)
this.chartRenderer?.showToolTip(p)
} else if(event.action == MouseAction.Move) {
this.chartRenderer?.scroll(p)
if(!this.opts?.enableScroll) this.chartRenderer?.showToolTip(p)
} else if(event.action == MouseAction.Release) {
this.chartRenderer?.scrollEnd()
}
}
onTouchEvent(event: TouchEvent) {
const touch = event.touches[0]
const p: Point = {
x: touch.x,
y: touch.y
}
if(event.type == TouchType.Down) {
this.chartRenderer?.scrollStart(p)
this.chartRenderer?.touchLegend(p)
this.chartRenderer?.showToolTip(p)
} else if(event.type == TouchType.Move) {
this.chartRenderer?.scroll(p)
if(event.touches.length > 1) {
this.chartRenderer?.doubleZoom([
{x: event.touches[0].x, y: event.touches[0].y},
{x: event.touches[1].x, y: event.touches[1].y}
])
}
if(!this.opts?.enableScroll) this.chartRenderer?.showToolTip(p)
} else if(event.type == TouchType.Up) {
this.chartRenderer?.scrollEnd()
}
}
最终实现 HarmonyOS 平台的适配。
未来发展
随着 HarmonyOS 生态的不断完善,UCharts 也在持续演进:
- 更多图表类型:不断增加新的图表类型支持
- 性能优化:持续优化渲染性能和内存使用
- 交互增强:提供更丰富的交互功能
- 主题系统:完善的主题定制系统
对于正在开发 HarmonyOS 应用的开发者来说,UCharts 无疑是一个值得尝试的优秀第三方库。它不仅能够帮助您快速实现数据可视化功能,还能为您的应用带来更好的用户体验。
相关资源
- GitHub 仓库:https://github.com/junbin-yang/uCharts-v3
- 官方文档:https://www.ucharts.cn
- 示例代码:项目中的 examples 目录
- 社区支持:QQ 群、微信群等技术交流平台
希望这篇文章能够帮助您更好地了解和使用 UCharts,在 HarmonyOS 开发中创造出更加精彩的数据可视化应用!
致谢
感谢所有开源贡献者和用户的支持!
