鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库 原创 精华

Groot_
发布于 2025-8-13 11:58
浏览
0收藏

::: hljs-center
鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库-鸿蒙开发者社区

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轴、辅助线、圆角、自定义颜色等多项配置。

鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库-鸿蒙开发者社区

山峰图

下图是基于班级人数绘制的圆角山峰图。

鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库-鸿蒙开发者社区

饼状图

下图是基于班级人数比例绘制的饼状图。

鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库-鸿蒙开发者社区

词云图

鸿蒙开源第三方组件 —— UCharts - 鸿蒙可视化图表库-鸿蒙开发者社区

样例解析

图表绘制

如果想要绘制图表,只需要简单几个步骤即可实现:

  1. 页面中添加图表组件,并为组件初始化控制器。
  2. 设置图表配置,通过组件控制器更新图表。
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 无疑是一个值得尝试的优秀第三方库。它不仅能够帮助您快速实现数据可视化功能,还能为您的应用带来更好的用户体验。

相关资源

希望这篇文章能够帮助您更好地了解和使用 UCharts,在 HarmonyOS 开发中创造出更加精彩的数据可视化应用!

致谢

感谢所有开源贡献者和用户的支持!

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2025-8-14 16:50:44修改
2
收藏
回复
举报
回复
    相关推荐