@agions/taroviz 1.11.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +245 -0
- package/README.md +104 -302
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/vendors.js +1 -0
- package/dist/cjs/vendors~echarts.js +1 -0
- package/dist/esm/index.js +1 -58151
- package/dist/esm/vendors.js +1 -0
- package/dist/esm/vendors~echarts.js +1 -0
- package/package.json +19 -25
- package/src/adapters/MiniAppAdapter.ts +136 -0
- package/src/adapters/__tests__/index.test.ts +1 -1
- package/src/adapters/h5/__tests__/index.test.ts +4 -2
- package/src/adapters/h5/index.ts +63 -64
- package/src/adapters/harmony/index.ts +23 -245
- package/src/adapters/index.ts +49 -45
- package/src/adapters/swan/index.ts +6 -69
- package/src/adapters/tt/index.ts +7 -70
- package/src/adapters/types.ts +25 -58
- package/src/adapters/weapp/index.ts +6 -69
- package/src/charts/__tests__/testUtils.tsx +87 -0
- package/src/charts/boxplot/__tests__/index.test.tsx +49 -103
- package/src/charts/boxplot/index.tsx +2 -1
- package/src/charts/boxplot/types.ts +17 -16
- package/src/charts/common/BaseChartWrapper.tsx +90 -82
- package/src/charts/common/__mocks__/BaseChartWrapper.tsx +17 -0
- package/src/charts/createChartComponent.tsx +36 -0
- package/src/charts/createOptionChartComponent.tsx +32 -0
- package/src/charts/funnel/__tests__/index.test.tsx +99 -0
- package/src/charts/funnel/index.tsx +60 -10
- package/src/charts/funnel/types.ts +6 -0
- package/src/charts/graph/__tests__/index.test.tsx +102 -33
- package/src/charts/graph/index.tsx +66 -9
- package/src/charts/graph/types.ts +6 -0
- package/src/charts/heatmap/__tests__/index.test.tsx +139 -0
- package/src/charts/heatmap/index.tsx +103 -10
- package/src/charts/heatmap/types.ts +6 -0
- package/src/charts/index.ts +74 -26
- package/src/charts/liquid/__tests__/index.test.tsx +52 -0
- package/src/charts/liquid/index.tsx +239 -182
- package/src/charts/liquid/types.ts +11 -11
- package/src/charts/parallel/__tests__/index.test.tsx +40 -67
- package/src/charts/parallel/index.tsx +2 -1
- package/src/charts/parallel/types.ts +19 -18
- package/src/charts/radar/__tests__/index.test.tsx +210 -0
- package/src/charts/radar/index.tsx +143 -10
- package/src/charts/radar/types.ts +13 -0
- package/src/charts/sankey/__tests__/index.test.tsx +124 -0
- package/src/charts/sankey/index.tsx +62 -10
- package/src/charts/sankey/types.ts +6 -0
- package/src/charts/tree/__tests__/index.test.tsx +71 -0
- package/src/charts/tree/index.tsx +5 -2
- package/src/charts/tree/types.ts +9 -9
- package/src/charts/types.ts +208 -106
- package/src/charts/utils.ts +9 -7
- package/src/charts/wordcloud/__tests__/index.test.tsx +98 -31
- package/src/charts/wordcloud/index.tsx +75 -9
- package/src/charts/wordcloud/types.ts +6 -0
- package/src/components/DataFilter/index.tsx +32 -10
- package/src/core/animation/types.ts +6 -6
- package/src/core/components/Annotation.tsx +6 -7
- package/src/core/components/BaseChart.tsx +110 -168
- package/src/core/components/ErrorBoundary.tsx +17 -4
- package/src/core/components/LazyChart.tsx +54 -55
- package/src/core/components/hooks/index.ts +6 -2
- package/src/core/components/hooks/useChartInit.ts +6 -3
- package/src/core/components/hooks/usePerformance.ts +8 -2
- package/src/core/components/hooks/useVirtualScroll.ts +2 -1
- package/src/core/index.ts +1 -1
- package/src/core/themes/ThemeManager.ts +1 -1
- package/src/core/types/common.ts +2 -1
- package/src/core/types/index.ts +0 -12
- package/src/core/types/platform.ts +3 -5
- package/src/core/utils/__tests__/deepClone.test.ts +317 -0
- package/src/core/utils/__tests__/index.test.ts +2 -1
- package/src/core/utils/chartInstances.ts +13 -0
- package/src/core/utils/common.ts +20 -29
- package/src/core/utils/deepClone.ts +114 -0
- package/src/core/utils/download.ts +128 -0
- package/src/core/utils/drillDown.ts +34 -353
- package/src/core/utils/drillDownHelpers.ts +426 -0
- package/src/core/utils/events.ts +12 -0
- package/src/core/utils/export/ExportUtils.ts +36 -67
- package/src/core/utils/format.ts +44 -0
- package/src/core/utils/index.ts +21 -154
- package/src/core/utils/merge.ts +25 -0
- package/src/core/utils/performance/PerformanceAnalyzer.ts +38 -21
- package/src/core/utils/performance/hooks.ts +7 -0
- package/src/core/utils/performance/index.ts +2 -0
- package/src/{hooks → core/utils/performance}/useAnimation.ts +45 -41
- package/src/core/utils/performance/useDataZoom.ts +324 -0
- package/src/{hooks → core/utils/performance}/usePerformance.ts +49 -41
- package/src/core/utils/performance/usePerformanceHooks.ts +278 -0
- package/src/core/utils/performanceUtils.ts +310 -0
- package/src/core/utils/runtime.ts +190 -0
- package/src/core/utils/setOptionUtils.ts +59 -0
- package/src/core/version.ts +14 -0
- package/src/editor/EnhancedThemeEditor.tsx +362 -540
- package/src/editor/ThemeEditor.tsx +55 -321
- package/src/editor/components/ThemeBasicSettings.tsx +113 -0
- package/src/editor/components/ThemeColorEditor.tsx +105 -0
- package/src/editor/components/ThemeSelector.tsx +70 -0
- package/src/editor/hooks/useThemeEditorState.ts +201 -0
- package/src/editor/index.ts +10 -2
- package/src/hooks/__tests__/index.test.tsx +3 -1
- package/src/hooks/chartConnectHelpers.ts +341 -0
- package/src/hooks/index.ts +55 -660
- package/src/hooks/types.ts +189 -0
- package/src/hooks/useChartAutoResize.ts +73 -0
- package/src/hooks/useChartConnect.ts +92 -238
- package/src/hooks/useChartDownload.ts +25 -27
- package/src/hooks/useChartHistory.ts +34 -49
- package/src/hooks/useChartInit.ts +59 -0
- package/src/hooks/useChartOptions.ts +259 -0
- package/src/hooks/useChartPerformance.ts +109 -0
- package/src/hooks/useChartSelection.ts +52 -49
- package/src/hooks/useChartTheme.ts +51 -0
- package/src/hooks/useDataTransform.ts +19 -4
- package/src/hooks/utils/chartDownloadUtils.ts +40 -53
- package/src/hooks/utils/dataTransformUtils.ts +22 -0
- package/src/index.ts +48 -34
- package/src/main.tsx +4 -9
- package/src/react-dom.d.ts +3 -3
- package/src/themes/index.ts +30 -855
- package/src/themes/palettes/blue-green.ts +13 -0
- package/src/themes/palettes/chalk.ts +13 -0
- package/src/themes/palettes/cyber.ts +44 -0
- package/src/themes/palettes/dark.ts +52 -0
- package/src/themes/palettes/default.ts +52 -0
- package/src/themes/palettes/elegant.ts +34 -0
- package/src/themes/palettes/forest.ts +13 -0
- package/src/themes/palettes/glass.ts +49 -0
- package/src/themes/palettes/golden.ts +13 -0
- package/src/themes/palettes/neon.ts +43 -0
- package/src/themes/palettes/ocean.ts +39 -0
- package/src/themes/palettes/pastel.ts +37 -0
- package/src/themes/palettes/purple-passion.ts +13 -0
- package/src/themes/palettes/retro.ts +33 -0
- package/src/themes/palettes/sunset.ts +40 -0
- package/src/themes/palettes/walden.ts +13 -0
- package/src/themes/registry.ts +184 -0
- package/src/themes/types.ts +213 -0
- package/src/charts/bar/__tests__/index.test.tsx +0 -113
- package/src/charts/bar/index.tsx +0 -14
- package/src/charts/candlestick/__tests__/index.test.tsx +0 -40
- package/src/charts/candlestick/index.tsx +0 -13
- package/src/charts/gauge/index.tsx +0 -14
- package/src/charts/line/__tests__/index.test.tsx +0 -107
- package/src/charts/line/index.tsx +0 -15
- package/src/charts/pie/__tests__/index.test.tsx +0 -112
- package/src/charts/pie/index.tsx +0 -14
- package/src/charts/scatter/index.tsx +0 -14
- package/src/charts/sunburst/index.tsx +0 -18
- package/src/charts/treemap/index.tsx +0 -18
- package/src/core/utils/codeGenerator/CodeGenerator.ts +0 -669
- package/src/core/utils/codeGenerator/index.ts +0 -13
- package/src/core/utils/codeGenerator/types.ts +0 -198
- package/src/core/utils/configGenerator/ConfigGenerator.ts +0 -583
- package/src/core/utils/configGenerator/index.ts +0 -13
- package/src/core/utils/configGenerator/types.ts +0 -445
- package/src/core/utils/debug/DebugPanel.tsx +0 -637
- package/src/core/utils/debug/debugger.ts +0 -322
- package/src/core/utils/debug/index.ts +0 -21
- package/src/core/utils/debug/types.ts +0 -142
- package/src/hooks/useDataZoom.ts +0 -323
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agions/taroviz",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "基于 Taro 和 ECharts 的多端图表组件库",
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "基于 Taro 和 ECharts 的多端图表组件库 - v2.0.0 大版本更新,新增 6 种图表类型",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
7
7
|
"module": "dist/esm/index.js",
|
|
@@ -40,11 +40,8 @@
|
|
|
40
40
|
"clean": "rimraf dist",
|
|
41
41
|
"test": "jest",
|
|
42
42
|
"test:watch": "jest --watch",
|
|
43
|
+
"test:ci": "jest --ci --maxWorkers=50%",
|
|
43
44
|
"test:coverage": "jest --coverage",
|
|
44
|
-
"cypress:open": "cypress open",
|
|
45
|
-
"cypress:run": "cypress run",
|
|
46
|
-
"cypress:component": "cypress open --component",
|
|
47
|
-
"test:e2e": "cypress run --e2e",
|
|
48
45
|
"lint": "eslint src --ext .ts,.tsx",
|
|
49
46
|
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
50
47
|
"lint:prettier": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
|
@@ -85,31 +82,31 @@
|
|
|
85
82
|
"@commitlint/cli": "^19.0.0",
|
|
86
83
|
"@commitlint/config-conventional": "^19.0.0",
|
|
87
84
|
"@release-it/conventional-changelog": "^8.0.0",
|
|
88
|
-
"@testing-library/cypress": "^10.1.0",
|
|
89
85
|
"@testing-library/dom": "^10.4.1",
|
|
90
86
|
"@testing-library/jest-dom": "^6.9.1",
|
|
91
87
|
"@testing-library/react": "^16.3.0",
|
|
92
88
|
"@types/jest": "^29.5.12",
|
|
93
|
-
"@types/node": "^20.
|
|
89
|
+
"@types/node": "^20.19.39",
|
|
94
90
|
"@types/react": "^18.2.61",
|
|
95
91
|
"@types/react-dom": "^18.3.7",
|
|
96
92
|
"@types/testing-library__jest-dom": "^5.14.9",
|
|
97
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
98
|
-
"@typescript-eslint/parser": "^
|
|
99
|
-
"ajv": "^8.
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "^8.59.1",
|
|
94
|
+
"@typescript-eslint/parser": "^8.59.1",
|
|
95
|
+
"ajv": "^8.20.0",
|
|
96
|
+
"ajv-formats": "^3.0.1",
|
|
100
97
|
"babel-loader": "^10.0.0",
|
|
101
98
|
"clean-webpack-plugin": "^4.0.0",
|
|
102
99
|
"commitizen": "^4.3.0",
|
|
103
100
|
"core-js": "3.41.0",
|
|
104
101
|
"css-loader": "^7.1.2",
|
|
105
|
-
"
|
|
106
|
-
"eslint": "^
|
|
107
|
-
"eslint-config-prettier": "^
|
|
102
|
+
"echarts": "^5.6.0",
|
|
103
|
+
"eslint": "^9.39.4",
|
|
104
|
+
"eslint-config-prettier": "^10.1.8",
|
|
108
105
|
"eslint-import-resolver-typescript": "^4.3.2",
|
|
109
106
|
"eslint-plugin-import": "^2.31.0",
|
|
110
107
|
"eslint-plugin-prettier": "^5.1.3",
|
|
111
|
-
"eslint-plugin-react": "^7.
|
|
112
|
-
"eslint-plugin-react-hooks": "^
|
|
108
|
+
"eslint-plugin-react": "^7.37.5",
|
|
109
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
113
110
|
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
|
114
111
|
"glob": "^10.3.10",
|
|
115
112
|
"husky": "^9.0.11",
|
|
@@ -119,6 +116,7 @@
|
|
|
119
116
|
"marked": "^12.0.2",
|
|
120
117
|
"mini-css-extract-plugin": "^2.9.2",
|
|
121
118
|
"prettier": "^3.2.5",
|
|
119
|
+
"react": "^18.2.0",
|
|
122
120
|
"react-dom": "^18.3.1",
|
|
123
121
|
"release-it": "^17.0.0",
|
|
124
122
|
"rimraf": "^5.0.5",
|
|
@@ -129,17 +127,17 @@
|
|
|
129
127
|
"ts-loader": "^9.5.2",
|
|
130
128
|
"typedoc": "^0.28.2",
|
|
131
129
|
"typedoc-plugin-markdown": "^3.17.1",
|
|
132
|
-
"typescript": "^5.
|
|
130
|
+
"typescript": "^5.9.3",
|
|
133
131
|
"vitepress": "^1.6.4",
|
|
134
132
|
"webpack": "^5.90.3",
|
|
135
133
|
"webpack-bundle-analyzer": "^4.10.2",
|
|
136
134
|
"webpack-cli": "^5.1.4",
|
|
137
135
|
"webpack-dev-server": "^5.0.4",
|
|
138
|
-
"whatwg-fetch": "^3.6.20"
|
|
136
|
+
"whatwg-fetch": "^3.6.20",
|
|
137
|
+
"zrender": "^5.6.1"
|
|
139
138
|
},
|
|
140
139
|
"dependencies": {
|
|
141
140
|
"@babel/runtime": "^7.28.4",
|
|
142
|
-
"echarts-liquidfill": "^3.1.0",
|
|
143
141
|
"tslib": "^2.8.1"
|
|
144
142
|
},
|
|
145
143
|
"peerDependencies": {
|
|
@@ -147,8 +145,7 @@
|
|
|
147
145
|
"@tarojs/runtime": "^3.6.0",
|
|
148
146
|
"@tarojs/taro": "^3.6.0",
|
|
149
147
|
"echarts": "^5.4.3",
|
|
150
|
-
"
|
|
151
|
-
"zrender": "^6.0.0"
|
|
148
|
+
"zrender": "^5.4.3"
|
|
152
149
|
},
|
|
153
150
|
"peerDependenciesMeta": {
|
|
154
151
|
"echarts": {
|
|
@@ -179,14 +176,11 @@
|
|
|
179
176
|
"url": "https://github.com/agions/taroviz/issues"
|
|
180
177
|
},
|
|
181
178
|
"overrides": {
|
|
182
|
-
"ajv": "^8.18.0",
|
|
183
|
-
"ajv-formats": "^3.0.0",
|
|
184
179
|
"brace-expansion": "^3.0.1",
|
|
185
180
|
"esbuild": "^0.24.2",
|
|
186
181
|
"systeminformation": "^5.22.0",
|
|
187
182
|
"ws": "^8.18.0",
|
|
188
|
-
"path-scurry": "^1.11.0"
|
|
189
|
-
"echarts": "^5.4.3"
|
|
183
|
+
"path-scurry": "^1.11.0"
|
|
190
184
|
},
|
|
191
185
|
"release-it": {
|
|
192
186
|
"git": {
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaroViz 小程序适配器基类
|
|
3
|
+
* 消除 weapp/swan/tt 三个适配器间的代码重复
|
|
4
|
+
*/
|
|
5
|
+
import { BaseAdapter } from './BaseAdapter';
|
|
6
|
+
import type { Adapter } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 小程序适配器选项
|
|
10
|
+
*/
|
|
11
|
+
export interface MiniAppAdapterOptions {
|
|
12
|
+
component?: unknown;
|
|
13
|
+
canvasId?: string;
|
|
14
|
+
width?: number | string;
|
|
15
|
+
height?: number | string;
|
|
16
|
+
theme?: string | object;
|
|
17
|
+
option?: unknown;
|
|
18
|
+
onInit?: (instance: unknown) => void;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 小程序适配器基类
|
|
24
|
+
* 封装了小程序 canvas 初始化的通用逻辑
|
|
25
|
+
*/
|
|
26
|
+
export abstract class MiniAppAdapter extends BaseAdapter {
|
|
27
|
+
protected component: unknown = null;
|
|
28
|
+
|
|
29
|
+
constructor(config: MiniAppAdapterOptions) {
|
|
30
|
+
super(config);
|
|
31
|
+
this.component = config.component;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 子类需返回平台名称(用于日志)
|
|
36
|
+
*/
|
|
37
|
+
protected abstract get platformName(): string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 创建图表实例
|
|
41
|
+
* 子类可重写此方法以实现平台特定的创建逻辑
|
|
42
|
+
* 默认实现调用 component.createChart
|
|
43
|
+
*/
|
|
44
|
+
protected createChartInstance(
|
|
45
|
+
component: unknown,
|
|
46
|
+
config: {
|
|
47
|
+
id: string;
|
|
48
|
+
width?: number | string;
|
|
49
|
+
height?: number | string;
|
|
50
|
+
theme?: string | object;
|
|
51
|
+
}
|
|
52
|
+
): unknown {
|
|
53
|
+
return (component as { createChart: (cfg: unknown) => unknown }).createChart({
|
|
54
|
+
id: config.id,
|
|
55
|
+
width: config.width,
|
|
56
|
+
height: config.height,
|
|
57
|
+
theme: config.theme,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 初始化图表
|
|
63
|
+
*/
|
|
64
|
+
init(): unknown {
|
|
65
|
+
const config = this.config as MiniAppAdapterOptions;
|
|
66
|
+
const { canvasId, width, height, theme, option } = config;
|
|
67
|
+
|
|
68
|
+
if (!this.component) {
|
|
69
|
+
console.error(`[TaroViz] ${this.platformName}Adapter: component is required`);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!canvasId) {
|
|
74
|
+
console.error(`[TaroViz] ${this.platformName}Adapter: canvasId is required`);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const chart = this.createChartInstance(this.component, {
|
|
79
|
+
id: canvasId,
|
|
80
|
+
width,
|
|
81
|
+
height,
|
|
82
|
+
theme,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (option) {
|
|
86
|
+
(chart as { setOption: (o: unknown) => void }).setOption(option);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.chartInstance = chart;
|
|
90
|
+
|
|
91
|
+
const onInit = config.onInit;
|
|
92
|
+
if (onInit) {
|
|
93
|
+
onInit(chart);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return chart;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 设置组件引用
|
|
101
|
+
*/
|
|
102
|
+
setComponent(component: unknown): void {
|
|
103
|
+
this.component = component;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 发送 action
|
|
108
|
+
*/
|
|
109
|
+
dispatchAction(action: unknown): void {
|
|
110
|
+
(this.chartInstance as { dispatchAction?: (a: unknown) => void })?.dispatchAction?.(action);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 获取数据 URL
|
|
115
|
+
*/
|
|
116
|
+
getDataURL(opts?: unknown): string | undefined {
|
|
117
|
+
return (this.chartInstance as { getDataURL?: (o?: unknown) => string })?.getDataURL?.(opts);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 创建适配器工厂方法
|
|
123
|
+
* 避免每个子类重复写相同的 static create
|
|
124
|
+
*
|
|
125
|
+
* 注:MiniAppAdapter.init() 返回 unknown ,不满足 Adapter 接口的 EChartsType 要求
|
|
126
|
+
* 但实际使用中通过 as unknown as Adapter 强制转换,与原有子类的 static create 行为一致
|
|
127
|
+
*/
|
|
128
|
+
export function createMiniAppAdapter(
|
|
129
|
+
AdapterClass: new (options: MiniAppAdapterOptions) => MiniAppAdapter
|
|
130
|
+
) {
|
|
131
|
+
return function create(options: MiniAppAdapterOptions): Adapter {
|
|
132
|
+
return new AdapterClass(options) as unknown as Adapter;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export default MiniAppAdapter;
|
|
@@ -33,7 +33,7 @@ describe('Adapter Functions', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
// Skipped: getAdapter uses dynamic imports which don't work well with Jest mocks in this environment
|
|
36
|
-
describe.skip('getAdapter', () => {
|
|
36
|
+
describe.skip('getAdapter', () => {
|
|
37
37
|
it('should return adapter instance for browser environment', async () => {
|
|
38
38
|
const adapter = await getAdapter({});
|
|
39
39
|
expect(adapter).toBeDefined();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as echarts from 'echarts/core';
|
|
2
2
|
|
|
3
3
|
import H5Adapter from '../index';
|
|
4
|
+
import type { Adapter } from '../../types';
|
|
4
5
|
|
|
5
6
|
// Mock ECharts renderers first
|
|
6
7
|
jest.mock('echarts/renderers', () => ({
|
|
@@ -56,7 +57,7 @@ describe('H5Adapter', () => {
|
|
|
56
57
|
height: 300,
|
|
57
58
|
theme: 'dark',
|
|
58
59
|
renderer: 'canvas',
|
|
59
|
-
});
|
|
60
|
+
}) as unknown as H5Adapter;
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
afterEach(() => {
|
|
@@ -93,7 +94,8 @@ describe('H5Adapter', () => {
|
|
|
93
94
|
|
|
94
95
|
it('should handle theme setting', () => {
|
|
95
96
|
adapter.setTheme('light');
|
|
96
|
-
|
|
97
|
+
// Theme is stored internally and applied on init
|
|
98
|
+
expect(adapter.getInstance()).toBeNull();
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
it('should resize the chart', () => {
|
package/src/adapters/h5/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* TaroViz H5 适配器
|
|
3
3
|
* 基于 HTML Canvas 实现图表渲染
|
|
4
4
|
*/
|
|
5
|
-
import type { EChartsType } from 'echarts';
|
|
5
|
+
import type { EChartsType, EChartsOption } from 'echarts';
|
|
6
6
|
import {
|
|
7
7
|
GridComponent,
|
|
8
8
|
TooltipComponent,
|
|
@@ -14,6 +14,7 @@ import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
|
|
|
14
14
|
import * as React from 'react';
|
|
15
15
|
|
|
16
16
|
import { Adapter, H5AdapterOptions } from '../types';
|
|
17
|
+
import type { EventHandler } from '../../core/types/platform';
|
|
17
18
|
|
|
18
19
|
// 扩展 H5AdapterOptions 类型
|
|
19
20
|
interface ExtendedH5AdapterOptions extends H5AdapterOptions {
|
|
@@ -21,9 +22,9 @@ interface ExtendedH5AdapterOptions extends H5AdapterOptions {
|
|
|
21
22
|
width?: number | string;
|
|
22
23
|
height?: number | string;
|
|
23
24
|
theme?: string | object;
|
|
24
|
-
option?:
|
|
25
|
-
onInit?: (
|
|
26
|
-
containerRef?:
|
|
25
|
+
option?: EChartsOption;
|
|
26
|
+
onInit?: (_instance: EChartsType) => void;
|
|
27
|
+
containerRef?: HTMLElement | { current: HTMLElement | null };
|
|
27
28
|
direction?: 'ltr' | 'rtl';
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -45,9 +46,9 @@ class H5Adapter implements Adapter {
|
|
|
45
46
|
/**
|
|
46
47
|
* 图表实例
|
|
47
48
|
*/
|
|
48
|
-
private
|
|
49
|
+
private _instance: EChartsType | null = null;
|
|
49
50
|
private options: ExtendedH5AdapterOptions;
|
|
50
|
-
private containerRef:
|
|
51
|
+
private containerRef: ExtendedH5AdapterOptions['containerRef'] = undefined;
|
|
51
52
|
private canvasId: string;
|
|
52
53
|
|
|
53
54
|
constructor(options: ExtendedH5AdapterOptions) {
|
|
@@ -68,28 +69,32 @@ class H5Adapter implements Adapter {
|
|
|
68
69
|
/**
|
|
69
70
|
* 初始化图表
|
|
70
71
|
*/
|
|
71
|
-
init(_options?:
|
|
72
|
-
if (this.
|
|
73
|
-
return this.
|
|
72
|
+
init(_options?: EChartsOption): EChartsType {
|
|
73
|
+
if (this._instance) {
|
|
74
|
+
return this._instance;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
// 获取容器元素
|
|
77
|
-
const container =
|
|
78
|
+
const container =
|
|
79
|
+
this.containerRef && 'current' in this.containerRef
|
|
80
|
+
? this.containerRef.current
|
|
81
|
+
: this.containerRef || document.getElementById(this.canvasId);
|
|
78
82
|
if (!container) {
|
|
79
83
|
throw new Error(`[TaroViz] H5Adapter: container not found (canvasId: ${this.canvasId})`);
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
// 初始化图表
|
|
83
|
-
|
|
87
|
+
|
|
88
|
+
this._instance = echarts.init(container as HTMLElement, this.options.theme, {
|
|
84
89
|
// 性能优化选项
|
|
85
90
|
useDirtyRect: true, // 使用脏矩形渲染,减少重绘区域
|
|
86
91
|
renderer: this.options.renderer || 'canvas',
|
|
87
|
-
} as
|
|
92
|
+
}) as unknown as EChartsType;
|
|
88
93
|
|
|
89
94
|
// 设置性能优化相关的全局配置
|
|
90
|
-
if (this.
|
|
95
|
+
if (this._instance) {
|
|
91
96
|
// 渐进式渲染配置
|
|
92
|
-
this.
|
|
97
|
+
this._instance.setOption(
|
|
93
98
|
{
|
|
94
99
|
animation: this.options.option?.animation !== false,
|
|
95
100
|
animationDurationUpdate: 300,
|
|
@@ -101,39 +106,32 @@ class H5Adapter implements Adapter {
|
|
|
101
106
|
);
|
|
102
107
|
}
|
|
103
108
|
|
|
104
|
-
// 设置初始化选项,使用
|
|
105
|
-
if (this.options.option && this.
|
|
106
|
-
this.
|
|
107
|
-
notMerge: false, // 合并新选项和旧选项
|
|
108
|
-
lazyUpdate: true, // 延迟更新,合并多次setOption调用
|
|
109
|
-
});
|
|
109
|
+
// 设置初始化选项,使用lazyUpdate优化性能
|
|
110
|
+
if (this.options.option && this._instance) {
|
|
111
|
+
this._instance.setOption(this.options.option, false, true);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
// 执行初始化回调
|
|
113
|
-
if (this.options.onInit && this.
|
|
114
|
-
this.options.onInit(this.
|
|
115
|
+
if (this.options.onInit && this._instance) {
|
|
116
|
+
this.options.onInit(this._instance);
|
|
115
117
|
}
|
|
116
118
|
|
|
117
|
-
return this.
|
|
119
|
+
return this._instance as EChartsType;
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
/**
|
|
121
123
|
* 获取图表实例
|
|
122
124
|
*/
|
|
123
|
-
getInstance():
|
|
124
|
-
return this.
|
|
125
|
+
getInstance(): EChartsType | null {
|
|
126
|
+
return this._instance;
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
/**
|
|
128
130
|
* 设置图表选项
|
|
129
131
|
*/
|
|
130
|
-
setOption(option:
|
|
131
|
-
if (this.
|
|
132
|
-
|
|
133
|
-
this.instance.setOption(option, {
|
|
134
|
-
lazyUpdate: true,
|
|
135
|
-
...opts,
|
|
136
|
-
});
|
|
132
|
+
setOption(option: EChartsOption, notMerge?: boolean, lazyUpdate?: boolean): void {
|
|
133
|
+
if (this._instance) {
|
|
134
|
+
this._instance.setOption(option, notMerge, lazyUpdate);
|
|
137
135
|
} else {
|
|
138
136
|
this.options.option = option;
|
|
139
137
|
}
|
|
@@ -144,9 +142,9 @@ class H5Adapter implements Adapter {
|
|
|
144
142
|
*/
|
|
145
143
|
setTheme(theme: string | object): void {
|
|
146
144
|
this.options.theme = theme;
|
|
147
|
-
if (this.
|
|
145
|
+
if (this._instance) {
|
|
148
146
|
// 使用类型断言来访问私有方法
|
|
149
|
-
(this.
|
|
147
|
+
(this._instance as any).setTheme?.(theme);
|
|
150
148
|
}
|
|
151
149
|
}
|
|
152
150
|
|
|
@@ -154,21 +152,22 @@ class H5Adapter implements Adapter {
|
|
|
154
152
|
* 获取图表宽度
|
|
155
153
|
*/
|
|
156
154
|
getWidth(): number {
|
|
157
|
-
return this.
|
|
155
|
+
return this._instance?.getWidth() || 0;
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
/**
|
|
161
159
|
* 获取图表高度
|
|
162
160
|
*/
|
|
163
161
|
getHeight(): number {
|
|
164
|
-
return this.
|
|
162
|
+
return this._instance?.getHeight() || 0;
|
|
165
163
|
}
|
|
166
164
|
|
|
167
165
|
/**
|
|
168
166
|
* 获取DOM元素
|
|
169
167
|
*/
|
|
170
168
|
getDom(): HTMLElement | null {
|
|
171
|
-
|
|
169
|
+
const ref = this.containerRef;
|
|
170
|
+
return ref && 'current' in ref ? ref.current : (ref as HTMLElement | null);
|
|
172
171
|
}
|
|
173
172
|
|
|
174
173
|
/**
|
|
@@ -179,33 +178,33 @@ class H5Adapter implements Adapter {
|
|
|
179
178
|
pixelRatio?: number;
|
|
180
179
|
backgroundColor?: string;
|
|
181
180
|
}): string | undefined {
|
|
182
|
-
return this.
|
|
181
|
+
return this._instance?.getDataURL(opts);
|
|
183
182
|
}
|
|
184
183
|
|
|
185
184
|
/**
|
|
186
185
|
* 清空图表
|
|
187
186
|
*/
|
|
188
187
|
clear(): void {
|
|
189
|
-
if (this.
|
|
190
|
-
this.
|
|
188
|
+
if (this._instance) {
|
|
189
|
+
this._instance.clear();
|
|
191
190
|
}
|
|
192
191
|
}
|
|
193
192
|
|
|
194
193
|
/**
|
|
195
194
|
* 绑定事件
|
|
196
195
|
*/
|
|
197
|
-
on(event: string, handler:
|
|
198
|
-
if (this.
|
|
199
|
-
this.
|
|
196
|
+
on(event: string, handler: EventHandler): void {
|
|
197
|
+
if (this._instance) {
|
|
198
|
+
this._instance.on(event, handler as any);
|
|
200
199
|
}
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
/**
|
|
204
203
|
* 解绑事件
|
|
205
204
|
*/
|
|
206
|
-
off(event: string, handler?:
|
|
207
|
-
if (this.
|
|
208
|
-
this.
|
|
205
|
+
off(event: string, handler?: EventHandler): void {
|
|
206
|
+
if (this._instance) {
|
|
207
|
+
this._instance.off(event, handler as any);
|
|
209
208
|
}
|
|
210
209
|
}
|
|
211
210
|
|
|
@@ -213,8 +212,8 @@ class H5Adapter implements Adapter {
|
|
|
213
212
|
* 显示加载动画
|
|
214
213
|
*/
|
|
215
214
|
showLoading(opts?: object): void {
|
|
216
|
-
if (this.
|
|
217
|
-
this.
|
|
215
|
+
if (this._instance) {
|
|
216
|
+
this._instance.showLoading(opts);
|
|
218
217
|
}
|
|
219
218
|
}
|
|
220
219
|
|
|
@@ -222,16 +221,16 @@ class H5Adapter implements Adapter {
|
|
|
222
221
|
* 隐藏加载动画
|
|
223
222
|
*/
|
|
224
223
|
hideLoading(): void {
|
|
225
|
-
if (this.
|
|
226
|
-
this.
|
|
224
|
+
if (this._instance) {
|
|
225
|
+
this._instance.hideLoading();
|
|
227
226
|
}
|
|
228
227
|
}
|
|
229
228
|
|
|
230
229
|
/**
|
|
231
230
|
* 设置组件实例
|
|
232
231
|
*/
|
|
233
|
-
setComponent(component:
|
|
234
|
-
this.containerRef = component;
|
|
232
|
+
setComponent(component: unknown): void {
|
|
233
|
+
this.containerRef = component as ExtendedH5AdapterOptions['containerRef'];
|
|
235
234
|
}
|
|
236
235
|
|
|
237
236
|
/**
|
|
@@ -251,18 +250,18 @@ class H5Adapter implements Adapter {
|
|
|
251
250
|
* 销毁图表
|
|
252
251
|
*/
|
|
253
252
|
dispose(): void {
|
|
254
|
-
if (this.
|
|
255
|
-
this.
|
|
256
|
-
this.
|
|
253
|
+
if (this._instance) {
|
|
254
|
+
this._instance.dispose();
|
|
255
|
+
this._instance = null;
|
|
257
256
|
}
|
|
258
257
|
}
|
|
259
258
|
|
|
260
259
|
/**
|
|
261
260
|
* 触发图表行为
|
|
262
261
|
*/
|
|
263
|
-
dispatchAction(payload:
|
|
264
|
-
if (this.
|
|
265
|
-
this.
|
|
262
|
+
dispatchAction(payload: { type: string; [key: string]: unknown }): void {
|
|
263
|
+
if (this._instance) {
|
|
264
|
+
this._instance.dispatchAction(payload);
|
|
266
265
|
}
|
|
267
266
|
}
|
|
268
267
|
|
|
@@ -270,15 +269,15 @@ class H5Adapter implements Adapter {
|
|
|
270
269
|
* 获取DataURL
|
|
271
270
|
*/
|
|
272
271
|
getDataURL(opts?: object): string | undefined {
|
|
273
|
-
return this.
|
|
272
|
+
return this._instance?.getDataURL(opts);
|
|
274
273
|
}
|
|
275
274
|
|
|
276
275
|
/**
|
|
277
276
|
* 处理图表大小变化
|
|
278
277
|
*/
|
|
279
|
-
resize(opts?:
|
|
280
|
-
if (this.
|
|
281
|
-
this.
|
|
278
|
+
resize(opts?: object): void {
|
|
279
|
+
if (this._instance) {
|
|
280
|
+
this._instance.resize(opts);
|
|
282
281
|
}
|
|
283
282
|
}
|
|
284
283
|
|
|
@@ -302,12 +301,12 @@ class H5Adapter implements Adapter {
|
|
|
302
301
|
* 获取平台信息
|
|
303
302
|
* @returns 平台信息
|
|
304
303
|
*/
|
|
305
|
-
getPlatformInfo(): Record<string,
|
|
304
|
+
getPlatformInfo(): Record<string, string> {
|
|
306
305
|
return {
|
|
307
306
|
platform: 'h5',
|
|
308
307
|
renderer: this.options.renderer || 'canvas',
|
|
309
308
|
userAgent: navigator.userAgent,
|
|
310
|
-
devicePixelRatio: window.devicePixelRatio,
|
|
309
|
+
devicePixelRatio: String(window.devicePixelRatio),
|
|
311
310
|
};
|
|
312
311
|
}
|
|
313
312
|
}
|