架构

分层设计、ICanvas2D 契约、渲染管线与原生 App 扩展指南。

分层设计

职责位置
core纯引擎:ICanvas2D 契约、比例尺、布局、坐标轴、图例、ChartBase 渲染管线(零平台依赖)lib/core/
charts图表策略类:LineChart / BarChart / PieChart / RadarChart,只依赖 corelib/charts/
adapters平台差异:web / miniprogram(wx·my·tt)/ native(契约占位)lib/adapters/
factorycreateChart 按 option.type 分发到图表策略lib/factory.ts
componentTcChart 声明式组件(可选,依赖 transone)lib/component.ts

上层只依赖下层的公开接口,平台差异被收敛在 adapters——新增一个端只需要实现一个适配器,图表层零改动。

ICanvas2D 契约

跨端解耦的唯一边界是ICanvas2Dlib/core/canvas.ts):图表所需的最小 Canvas 2D 子集,约 20 个方法。刻意不含Path2Dfill / stroke无参调用;包含measureText / createLinearGradient。Web 标准 2D context 天然满足;小程序 Canvas 2D 节点经node.getContext('2d')适配;原生端按契约实现即可。

typescript
// 契约核心形状(精简示意)
interface ICanvas2D {
  beginPath(): void;
  moveTo(x: number, y: number): void;
  lineTo(x: number, y: number): void;
  bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void;
  arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
  fill(): void;
  stroke(): void;
  measureText(text: string): { width: number };
  createLinearGradient(x0: number, y0: number, x1: number, y1: number): IGradient;
  // ... 见 lib/core/canvas.ts 完整定义
}

渲染管线

ChartBase 统一渲染顺序,各图表只实现 drawSeries:

text
save → scale(dpr) → clear → 背景 → 布局(title/legend/轴区逐层扣除)
→ 标题 → 图例 → 坐标轴(仅笛卡尔类) → drawSeries → restore
  • seriesColor 按索引取 DEFAULT_PALETTE 色板,显式 color 优先。
  • 数值轴自动 nice 刻度;类目轴无标签时不预留轴区。
  • 图例:series 带 name 且未显式配置时,默认 top 显示。

原生 App 扩展指南

引擎与平台完全解耦:原生端实现ICanvas2D(Skia / ArkUI Canvas / 原生桥),再通过resolveNativeCanvas(host)注入即可,图表层零改动。

typescript
import { createChart } from 'transone-chart';
import { resolveNativeCanvas } from 'transone-chart/adapters';

// 原生桥层:把原生画布上下文包装成 ICanvas2D,并实现 NativeCanvasHost
const host = {
  width: 375,
  height: 260,
  pixelRatio: 2,
  getContext(type: '2d') {
    return { beginPath() {}, moveTo() {}, /* ...实现 ICanvas2D */ };
  },
};
const chart = createChart(resolveNativeCanvas(host), option);
chart.render();
快速失败
adapters/native.ts 当前是契约占位:未实现时调用会显式抛错,绝不静默降级,保证原生端不会出现"看起来渲染了其实空白"的隐性故障。