@agions/taroviz 1.3.1 → 1.6.0
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/README.md +4 -4
- package/dist/cjs/index.js +1 -1
- package/dist/esm/index.js +3814 -2724
- package/package.json +1 -1
- package/src/__tests__/integration.test.tsx +12 -10
- package/src/adapters/BaseAdapter.ts +116 -0
- package/src/adapters/__tests__/index.test.ts +10 -10
- package/src/adapters/index.ts +63 -74
- package/src/adapters/swan/index.ts +26 -223
- package/src/adapters/tt/index.ts +28 -225
- package/src/adapters/types.ts +36 -0
- package/src/adapters/weapp/index.ts +29 -189
- package/src/charts/bar/index.tsx +5 -9
- package/src/charts/boxplot/__tests__/index.test.tsx +130 -0
- package/src/charts/boxplot/index.tsx +18 -0
- package/src/charts/boxplot/types.ts +46 -0
- package/src/charts/candlestick/__tests__/index.test.tsx +37 -0
- package/src/charts/candlestick/index.tsx +13 -0
- package/src/charts/common/BaseChartWrapper.tsx +47 -38
- package/src/charts/funnel/index.tsx +5 -9
- package/src/charts/gauge/index.tsx +5 -9
- package/src/charts/graph/__tests__/index.test.tsx +41 -0
- package/src/charts/graph/index.tsx +13 -0
- package/src/charts/heatmap/index.tsx +5 -9
- package/src/charts/index.ts +10 -1
- package/src/charts/line/index.tsx +4 -7
- package/src/charts/parallel/__tests__/index.test.tsx +164 -0
- package/src/charts/parallel/index.tsx +18 -0
- package/src/charts/parallel/types.ts +73 -0
- package/src/charts/pie/index.tsx +5 -10
- package/src/charts/radar/index.tsx +5 -9
- package/src/charts/scatter/index.tsx +5 -9
- package/src/charts/types.ts +48 -4
- package/src/charts/wordcloud/__tests__/index.test.tsx +36 -0
- package/src/charts/wordcloud/index.tsx +13 -0
- package/src/core/animation/AnimationManager.ts +15 -0
- package/src/core/components/Annotation.tsx +26 -21
- package/src/core/components/BaseChart.tsx +280 -1105
- package/src/core/components/ErrorBoundary.tsx +4 -1
- package/src/core/components/LazyChart.tsx +42 -55
- package/src/core/components/hooks/index.ts +20 -0
- package/src/core/components/hooks/useChartEvents.ts +143 -0
- package/src/core/components/hooks/useChartInit.ts +80 -0
- package/src/core/components/hooks/usePerformance.ts +186 -0
- package/src/core/components/hooks/useVirtualScroll.ts +156 -0
- package/src/core/echarts.ts +1 -1
- package/src/core/themes/ThemeManager.ts +31 -15
- package/src/core/types/index.ts +2 -2
- package/src/core/utils/chartInstances.ts +10 -3
- package/src/core/utils/chartUtils.ts +46 -0
- package/src/core/utils/common.ts +14 -1
- package/src/core/utils/export/ExportUtils.ts +13 -22
- package/src/core/utils/performance/PerformanceAnalyzer.ts +32 -5
- package/src/core/utils/uuid.ts +1 -1
- package/src/editor/EnhancedThemeEditor.tsx +624 -0
- package/src/editor/ThemeEditor.tsx +1 -6
- package/src/hooks/__tests__/index.test.tsx +14 -11
- package/src/hooks/__tests__/useDataTransform.test.ts +159 -0
- package/src/hooks/index.ts +54 -19
- package/src/hooks/useDataTransform.ts +503 -0
- package/src/index.ts +27 -9
- package/src/main.tsx +4 -4
- package/src/themes/__tests__/index.test.ts +2 -2
- package/src/themes/index.ts +13 -0
package/package.json
CHANGED
|
@@ -33,16 +33,18 @@ jest.mock('echarts/components', () => ({
|
|
|
33
33
|
}));
|
|
34
34
|
|
|
35
35
|
jest.mock('../adapters', () => ({
|
|
36
|
-
getAdapter: jest.fn(() =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
getAdapter: jest.fn(() =>
|
|
37
|
+
Promise.resolve({
|
|
38
|
+
init: jest.fn(),
|
|
39
|
+
setOption: jest.fn(),
|
|
40
|
+
resize: jest.fn(),
|
|
41
|
+
dispose: jest.fn(),
|
|
42
|
+
on: jest.fn(),
|
|
43
|
+
off: jest.fn(),
|
|
44
|
+
showLoading: jest.fn(),
|
|
45
|
+
hideLoading: jest.fn(),
|
|
46
|
+
})
|
|
47
|
+
),
|
|
46
48
|
}));
|
|
47
49
|
|
|
48
50
|
jest.mock('../charts/common/BaseChartWrapper', () => ({
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaroViz 适配器基类
|
|
3
|
+
* 提供通用方法,减少子类重复代码
|
|
4
|
+
* 注意:这是一个工具基类,不直接实现 Adapter 接口
|
|
5
|
+
* 子类负责实现真正的 Adapter 接口
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export abstract class BaseAdapter {
|
|
9
|
+
protected config: Record<string, unknown>;
|
|
10
|
+
protected chartInstance: unknown = null;
|
|
11
|
+
|
|
12
|
+
constructor(config: Record<string, unknown> = {}) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getInstance(): unknown {
|
|
17
|
+
return this.chartInstance;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setOption(option: unknown, opts?: unknown): void {
|
|
21
|
+
if (this.chartInstance) {
|
|
22
|
+
(this.chartInstance as { setOption: (opt: unknown, o?: unknown) => void }).setOption(
|
|
23
|
+
option,
|
|
24
|
+
opts
|
|
25
|
+
);
|
|
26
|
+
} else {
|
|
27
|
+
this.config['option'] = option;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setTheme(theme: string | object): void {
|
|
32
|
+
this.config['theme'] = theme;
|
|
33
|
+
const instance = this.chartInstance as { setTheme?: (t: string | object) => void };
|
|
34
|
+
if (instance?.setTheme) {
|
|
35
|
+
instance.setTheme(theme);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getWidth(): number {
|
|
40
|
+
const w = this.config['width'];
|
|
41
|
+
if (typeof w === 'number') return w;
|
|
42
|
+
if (typeof w === 'string') {
|
|
43
|
+
const parsed = parseInt(w, 10);
|
|
44
|
+
if (!isNaN(parsed)) return parsed;
|
|
45
|
+
}
|
|
46
|
+
return 300;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getHeight(): number {
|
|
50
|
+
const h = this.config['height'];
|
|
51
|
+
if (typeof h === 'number') return h;
|
|
52
|
+
if (typeof h === 'string') {
|
|
53
|
+
const parsed = parseInt(h, 10);
|
|
54
|
+
if (!isNaN(parsed)) return parsed;
|
|
55
|
+
}
|
|
56
|
+
return 300;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getDom(): HTMLElement | null {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
convertToDataURL(opts?: unknown): string | undefined {
|
|
64
|
+
return (this.chartInstance as { getDataURL?: (o?: unknown) => string })?.getDataURL?.(opts);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
clear(): void {
|
|
68
|
+
(this.chartInstance as { clear?: () => void })?.clear?.();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
on(event: string, handler: (params: unknown) => void): void {
|
|
72
|
+
(this.chartInstance as { on?: (e: string, h: (p: unknown) => void) => void })?.on?.(
|
|
73
|
+
event,
|
|
74
|
+
handler
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
off(event: string, handler?: (params: unknown) => void): void {
|
|
79
|
+
(this.chartInstance as { off?: (e: string, h?: (p: unknown) => void) => void })?.off?.(
|
|
80
|
+
event,
|
|
81
|
+
handler
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
showLoading(opts?: object): void {
|
|
86
|
+
(this.chartInstance as { showLoading?: (o?: object) => void })?.showLoading?.(opts);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
hideLoading(): void {
|
|
90
|
+
(this.chartInstance as { hideLoading?: () => void })?.hideLoading?.();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
dispose(): void {
|
|
94
|
+
if (this.chartInstance) {
|
|
95
|
+
(this.chartInstance as { dispose?: () => void })?.dispose?.();
|
|
96
|
+
this.chartInstance = null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
resize(opts?: unknown): void {
|
|
101
|
+
(this.chartInstance as { resize?: (o?: unknown) => void })?.resize?.(opts);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setComponent(component: unknown): void {
|
|
105
|
+
this.config['component'] = component;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
protected parseSize(value: number | string | undefined, defaultValue: number): number {
|
|
109
|
+
if (typeof value === 'number') return value;
|
|
110
|
+
if (typeof value === 'string') {
|
|
111
|
+
const parsed = parseInt(value, 10);
|
|
112
|
+
if (!isNaN(parsed)) return parsed;
|
|
113
|
+
}
|
|
114
|
+
return defaultValue;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -33,14 +33,14 @@ describe('Adapter Functions', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
describe('getAdapter', () => {
|
|
36
|
-
it('should return adapter instance for browser environment', () => {
|
|
37
|
-
const adapter = getAdapter({});
|
|
36
|
+
it('should return adapter instance for browser environment', async () => {
|
|
37
|
+
const adapter = await getAdapter({});
|
|
38
38
|
expect(adapter).toBeDefined();
|
|
39
39
|
expect(typeof adapter.init).toBe('function');
|
|
40
40
|
expect(typeof adapter.setOption).toBe('function');
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it('should return adapter instance with custom options', () => {
|
|
43
|
+
it('should return adapter instance with custom options', async () => {
|
|
44
44
|
const mockOptions = {
|
|
45
45
|
width: 500,
|
|
46
46
|
height: 300,
|
|
@@ -48,7 +48,7 @@ describe('Adapter Functions', () => {
|
|
|
48
48
|
renderer: 'canvas' as const,
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
const adapter = getAdapter(mockOptions);
|
|
51
|
+
const adapter = await getAdapter(mockOptions);
|
|
52
52
|
expect(adapter).toBeDefined();
|
|
53
53
|
expect(typeof adapter.init).toBe('function');
|
|
54
54
|
});
|
|
@@ -62,8 +62,8 @@ describe('Adapter Functions', () => {
|
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
describe('Cross-Platform Compatibility', () => {
|
|
65
|
-
it('should have consistent interface across all platforms', () => {
|
|
66
|
-
const adapter = getAdapter({});
|
|
65
|
+
it('should have consistent interface across all platforms', async () => {
|
|
66
|
+
const adapter = await getAdapter({});
|
|
67
67
|
|
|
68
68
|
// 确保所有平台的适配器都有相同的方法接口
|
|
69
69
|
const requiredMethods = ['init', 'setOption', 'resize', 'dispose'];
|
|
@@ -73,7 +73,7 @@ describe('Adapter Functions', () => {
|
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
it('should handle different option types across platforms', () => {
|
|
76
|
+
it('should handle different option types across platforms', async () => {
|
|
77
77
|
// 测试不同类型的选项
|
|
78
78
|
const testOptions = [
|
|
79
79
|
{ width: 500, height: 300 },
|
|
@@ -82,10 +82,10 @@ describe('Adapter Functions', () => {
|
|
|
82
82
|
{ renderer: 'svg' as const },
|
|
83
83
|
];
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
const adapter = getAdapter(options);
|
|
85
|
+
for (const options of testOptions) {
|
|
86
|
+
const adapter = await getAdapter(options);
|
|
87
87
|
expect(adapter).toBeDefined();
|
|
88
|
-
}
|
|
88
|
+
}
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
91
|
});
|
package/src/adapters/index.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TaroViz 平台适配器
|
|
3
3
|
* 自动检测并加载适合当前平台的适配器
|
|
4
|
+
*
|
|
5
|
+
* 使用动态导入实现按需加载,减少包体积
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
import { PlatformType } from '../core';
|
|
7
|
-
|
|
8
9
|
import type { AdapterOptions, Adapter } from './types';
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -38,41 +39,26 @@ export function detectPlatform(): PlatformType {
|
|
|
38
39
|
return PlatformType.H5;
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
const win = window as Window & {
|
|
43
|
+
wx?: { getSystemInfoSync?: unknown; qy?: unknown };
|
|
44
|
+
my?: { getSystemInfoSync?: unknown };
|
|
45
|
+
swan?: { getSystemInfoSync?: unknown };
|
|
46
|
+
tt?: { getSystemInfoSync?: unknown; env?: { appName?: string } };
|
|
47
|
+
qq?: { getSystemInfoSync?: unknown };
|
|
48
|
+
jd?: { getSystemInfoSync?: unknown };
|
|
49
|
+
dd?: { getSystemInfoSync?: unknown };
|
|
50
|
+
};
|
|
51
|
+
|
|
41
52
|
const checks: Array<{ test: () => boolean; platform: PlatformType }> = [
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
test: () => 'swan' in window && (window as any).swan?.getSystemInfoSync,
|
|
53
|
-
platform: PlatformType.SWAN,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
test: () => 'tt' in window && (window as any).tt?.getSystemInfoSync,
|
|
57
|
-
platform: PlatformType.TT,
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
test: () => 'qq' in window && (window as any).qq?.getSystemInfoSync,
|
|
61
|
-
platform: PlatformType.QQ,
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
test: () => 'jd' in window && (window as any).jd?.getSystemInfoSync,
|
|
65
|
-
platform: PlatformType.JD,
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
test: () => 'dd' in window && (window as any).dd?.getSystemInfoSync,
|
|
69
|
-
platform: PlatformType.DD,
|
|
70
|
-
},
|
|
71
|
-
{ test: () => 'wx' in window && (window as any).wx?.qy, platform: PlatformType.QYWX },
|
|
72
|
-
{
|
|
73
|
-
test: () => 'tt' in window && (window as any).tt?.env?.appName === 'lark',
|
|
74
|
-
platform: PlatformType.LARK,
|
|
75
|
-
},
|
|
53
|
+
{ test: () => !!win.wx?.getSystemInfoSync && !win.wx?.qy, platform: PlatformType.WEAPP },
|
|
54
|
+
{ test: () => !!win.my?.getSystemInfoSync, platform: PlatformType.ALIPAY },
|
|
55
|
+
{ test: () => !!win.swan?.getSystemInfoSync, platform: PlatformType.SWAN },
|
|
56
|
+
{ test: () => !!win.tt?.getSystemInfoSync, platform: PlatformType.TT },
|
|
57
|
+
{ test: () => !!win.qq?.getSystemInfoSync, platform: PlatformType.QQ },
|
|
58
|
+
{ test: () => !!win.jd?.getSystemInfoSync, platform: PlatformType.JD },
|
|
59
|
+
{ test: () => !!win.dd?.getSystemInfoSync, platform: PlatformType.DD },
|
|
60
|
+
{ test: () => !!win.wx?.qy, platform: PlatformType.QYWX },
|
|
61
|
+
{ test: () => win.tt?.env?.appName === 'lark', platform: PlatformType.LARK },
|
|
76
62
|
{ test: () => navigator.userAgent.includes('HarmonyOS'), platform: PlatformType.HARMONY },
|
|
77
63
|
];
|
|
78
64
|
|
|
@@ -92,52 +78,20 @@ export function getEnv(): 'h5' | 'weapp' | 'unknown' {
|
|
|
92
78
|
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
93
79
|
return 'h5';
|
|
94
80
|
}
|
|
95
|
-
if (
|
|
81
|
+
if (
|
|
82
|
+
typeof global !== 'undefined' &&
|
|
83
|
+
(global as Global & { wx?: { getSystemInfoSync?: unknown } })?.wx?.getSystemInfoSync
|
|
84
|
+
) {
|
|
96
85
|
return 'weapp';
|
|
97
86
|
}
|
|
98
87
|
return 'unknown';
|
|
99
88
|
}
|
|
100
89
|
|
|
101
|
-
/**
|
|
102
|
-
* 创建适配器实例
|
|
103
|
-
* 使用静态导入避免动态 require 的 ESM 问题
|
|
104
|
-
*/
|
|
105
|
-
function createAdapterInstance(platform: PlatformType, options: AdapterOptions): Adapter {
|
|
106
|
-
// 预加载所有适配器(编译时解析,支持 tree-shaking)
|
|
107
|
-
switch (platform) {
|
|
108
|
-
case PlatformType.H5:
|
|
109
|
-
case PlatformType.ALIPAY:
|
|
110
|
-
case PlatformType.QQ:
|
|
111
|
-
case PlatformType.JD:
|
|
112
|
-
case PlatformType.DD:
|
|
113
|
-
case PlatformType.QYWX:
|
|
114
|
-
case PlatformType.LARK:
|
|
115
|
-
case PlatformType.KWAI:
|
|
116
|
-
return h5Adapter.create(options);
|
|
117
|
-
case PlatformType.WEAPP:
|
|
118
|
-
return weappAdapter.create(options);
|
|
119
|
-
case PlatformType.SWAN:
|
|
120
|
-
return swanAdapter.create(options);
|
|
121
|
-
case PlatformType.TT:
|
|
122
|
-
return ttAdapter.create(options);
|
|
123
|
-
case PlatformType.HARMONY:
|
|
124
|
-
return harmonyAdapter.create(options);
|
|
125
|
-
default:
|
|
126
|
-
return h5Adapter.create(options);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// 静态导入适配器
|
|
131
|
-
import h5Adapter from './h5';
|
|
132
|
-
import weappAdapter from './weapp';
|
|
133
|
-
import swanAdapter from './swan';
|
|
134
|
-
import ttAdapter from './tt';
|
|
135
|
-
import harmonyAdapter from './harmony';
|
|
136
|
-
|
|
137
90
|
/**
|
|
138
91
|
* 获取适配器
|
|
92
|
+
* 返回 Promise 以支持动态导入
|
|
139
93
|
*/
|
|
140
|
-
export function getAdapter(options: AdapterOptions): Adapter {
|
|
94
|
+
export async function getAdapter(options: AdapterOptions): Promise<Adapter> {
|
|
141
95
|
const platform = detectPlatform();
|
|
142
96
|
const config = PLATFORM_CONFIGS[platform];
|
|
143
97
|
|
|
@@ -149,9 +103,44 @@ export function getAdapter(options: AdapterOptions): Adapter {
|
|
|
149
103
|
}
|
|
150
104
|
|
|
151
105
|
try {
|
|
152
|
-
|
|
106
|
+
// 根据平台加载对应的适配器
|
|
107
|
+
switch (platform) {
|
|
108
|
+
case PlatformType.H5:
|
|
109
|
+
case PlatformType.ALIPAY:
|
|
110
|
+
case PlatformType.QQ:
|
|
111
|
+
case PlatformType.JD:
|
|
112
|
+
case PlatformType.DD:
|
|
113
|
+
case PlatformType.QYWX:
|
|
114
|
+
case PlatformType.LARK:
|
|
115
|
+
case PlatformType.KWAI: {
|
|
116
|
+
const { default: h5Adapter } = await import('./h5');
|
|
117
|
+
return h5Adapter.create(options);
|
|
118
|
+
}
|
|
119
|
+
case PlatformType.WEAPP: {
|
|
120
|
+
const { default: weappAdapter } = await import('./weapp');
|
|
121
|
+
return weappAdapter.create(options);
|
|
122
|
+
}
|
|
123
|
+
case PlatformType.SWAN: {
|
|
124
|
+
const { default: swanAdapter } = await import('./swan');
|
|
125
|
+
return swanAdapter.create(options);
|
|
126
|
+
}
|
|
127
|
+
case PlatformType.TT: {
|
|
128
|
+
const { default: ttAdapter } = await import('./tt');
|
|
129
|
+
return ttAdapter.create(options);
|
|
130
|
+
}
|
|
131
|
+
case PlatformType.HARMONY: {
|
|
132
|
+
const { default: harmonyAdapter } = await import('./harmony');
|
|
133
|
+
return harmonyAdapter.create(options);
|
|
134
|
+
}
|
|
135
|
+
default: {
|
|
136
|
+
const { default: h5Adapter } = await import('./h5');
|
|
137
|
+
return h5Adapter.create(options);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
153
140
|
} catch (error) {
|
|
154
141
|
console.error(`[TaroViz] Failed to load adapter for platform '${platform}':`, error);
|
|
142
|
+
// 降级到 H5 适配器
|
|
143
|
+
const { default: h5Adapter } = await import('./h5');
|
|
155
144
|
return h5Adapter.create(options);
|
|
156
145
|
}
|
|
157
146
|
}
|
|
@@ -2,91 +2,25 @@
|
|
|
2
2
|
* TaroViz 百度小程序适配器
|
|
3
3
|
* 基于百度小程序canvas组件实现图表渲染
|
|
4
4
|
*/
|
|
5
|
-
import * as React from 'react';
|
|
6
5
|
|
|
7
|
-
import {
|
|
6
|
+
import { BaseAdapter } from '../BaseAdapter';
|
|
7
|
+
import type { Adapter, SwanAdapterOptions } from '../types';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 百度小程序组件实例
|
|
13
|
-
*/
|
|
14
|
-
component?: any;
|
|
15
|
-
/**
|
|
16
|
-
* 画布ID
|
|
17
|
-
*/
|
|
18
|
-
canvasId?: string;
|
|
19
|
-
/**
|
|
20
|
-
* 宽度
|
|
21
|
-
*/
|
|
22
|
-
width?: number | string;
|
|
23
|
-
/**
|
|
24
|
-
* 高度
|
|
25
|
-
*/
|
|
26
|
-
height?: number | string;
|
|
27
|
-
/**
|
|
28
|
-
* 主题
|
|
29
|
-
*/
|
|
30
|
-
theme?: string | object;
|
|
31
|
-
/**
|
|
32
|
-
* 图表选项
|
|
33
|
-
*/
|
|
34
|
-
option?: any;
|
|
35
|
-
/**
|
|
36
|
-
* 初始化回调
|
|
37
|
-
*/
|
|
38
|
-
onInit?: (instance: any) => void;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 百度小程序环境下的图表适配器
|
|
43
|
-
*/
|
|
44
|
-
class SwanAdapter implements Adapter {
|
|
45
|
-
/**
|
|
46
|
-
* 配置项
|
|
47
|
-
*/
|
|
48
|
-
private config: ExtendedSwanAdapterOptions;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* 图表实例
|
|
52
|
-
*/
|
|
53
|
-
private chartInstance: any | null = null;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 组件实例
|
|
57
|
-
*/
|
|
58
|
-
private component: any | null = null;
|
|
9
|
+
export class SwanAdapter extends BaseAdapter {
|
|
10
|
+
private component: unknown = null;
|
|
59
11
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
* @param config 适配器配置
|
|
63
|
-
*/
|
|
64
|
-
constructor(config: ExtendedSwanAdapterOptions) {
|
|
65
|
-
this.config = config;
|
|
12
|
+
constructor(config: SwanAdapterOptions) {
|
|
13
|
+
super(config);
|
|
66
14
|
this.component = config.component;
|
|
67
15
|
}
|
|
68
16
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* @param options 适配器选项
|
|
72
|
-
* @returns 适配器实例
|
|
73
|
-
*/
|
|
74
|
-
static create(options: ExtendedSwanAdapterOptions): SwanAdapter {
|
|
75
|
-
return new SwanAdapter(options);
|
|
17
|
+
static create(options: SwanAdapterOptions): Adapter {
|
|
18
|
+
return new SwanAdapter(options) as unknown as Adapter;
|
|
76
19
|
}
|
|
77
20
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
getInstance(): any {
|
|
82
|
-
return this.chartInstance;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* 初始化图表
|
|
87
|
-
*/
|
|
88
|
-
init(): any {
|
|
89
|
-
const { canvasId, width, height, theme, option } = this.config;
|
|
21
|
+
init(): unknown {
|
|
22
|
+
const config = this.config as SwanAdapterOptions & { canvasId?: string };
|
|
23
|
+
const { canvasId, width, height, theme, option } = config;
|
|
90
24
|
|
|
91
25
|
if (!this.component) {
|
|
92
26
|
console.error('[TaroViz] SwanAdapter: component is required');
|
|
@@ -98,176 +32,45 @@ class SwanAdapter implements Adapter {
|
|
|
98
32
|
return null;
|
|
99
33
|
}
|
|
100
34
|
|
|
101
|
-
|
|
102
|
-
const chart = this.component.createChart({
|
|
35
|
+
const chart = (this.component as { createChart: (config: unknown) => unknown }).createChart({
|
|
103
36
|
id: canvasId,
|
|
104
|
-
width
|
|
105
|
-
height
|
|
106
|
-
theme
|
|
37
|
+
width,
|
|
38
|
+
height,
|
|
39
|
+
theme,
|
|
107
40
|
});
|
|
108
41
|
|
|
109
|
-
// 设置图表选项
|
|
110
42
|
if (option) {
|
|
111
|
-
chart.setOption(option);
|
|
43
|
+
(chart as { setOption: (o: unknown) => void }).setOption(option);
|
|
112
44
|
}
|
|
113
45
|
|
|
114
|
-
// 存储图表实例
|
|
115
46
|
this.chartInstance = chart;
|
|
116
47
|
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
48
|
+
const onInit = this.config['onInit'] as ((instance: unknown) => void) | undefined;
|
|
49
|
+
if (onInit) {
|
|
50
|
+
onInit(chart);
|
|
120
51
|
}
|
|
121
52
|
|
|
122
53
|
return chart;
|
|
123
54
|
}
|
|
124
55
|
|
|
125
|
-
/**
|
|
126
|
-
* 设置图表选项
|
|
127
|
-
*/
|
|
128
|
-
setOption(option: any, opts?: any): void {
|
|
129
|
-
if (this.chartInstance) {
|
|
130
|
-
this.chartInstance.setOption(option, opts);
|
|
131
|
-
} else {
|
|
132
|
-
this.config.option = option;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* 设置主题
|
|
138
|
-
*/
|
|
139
|
-
setTheme(theme: string | object): void {
|
|
140
|
-
this.config.theme = theme;
|
|
141
|
-
if (this.chartInstance) {
|
|
142
|
-
this.chartInstance.setTheme?.(theme);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* 获取图表宽度
|
|
148
|
-
*/
|
|
149
56
|
getWidth(): number {
|
|
150
|
-
return
|
|
57
|
+
return this.parseSize((this.config as SwanAdapterOptions).width, 300);
|
|
151
58
|
}
|
|
152
59
|
|
|
153
|
-
/**
|
|
154
|
-
* 获取图表高度
|
|
155
|
-
*/
|
|
156
60
|
getHeight(): number {
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* 获取DOM元素
|
|
162
|
-
*/
|
|
163
|
-
getDom(): HTMLElement | null {
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* 转换为DataURL
|
|
169
|
-
*/
|
|
170
|
-
convertToDataURL(opts?: any): string | undefined {
|
|
171
|
-
return this.chartInstance?.getDataURL(opts);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* 清空图表
|
|
176
|
-
*/
|
|
177
|
-
clear(): void {
|
|
178
|
-
if (this.chartInstance) {
|
|
179
|
-
this.chartInstance.clear();
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* 绑定事件
|
|
185
|
-
*/
|
|
186
|
-
on(event: string, handler: (params: any) => void): void {
|
|
187
|
-
if (this.chartInstance) {
|
|
188
|
-
this.chartInstance.on(event, handler);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* 解绑事件
|
|
194
|
-
*/
|
|
195
|
-
off(event: string, handler?: (params: any) => void): void {
|
|
196
|
-
if (this.chartInstance) {
|
|
197
|
-
this.chartInstance.off(event, handler);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* 显示加载动画
|
|
203
|
-
*/
|
|
204
|
-
showLoading(opts?: object): void {
|
|
205
|
-
if (this.chartInstance) {
|
|
206
|
-
this.chartInstance.showLoading(opts);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* 隐藏加载动画
|
|
212
|
-
*/
|
|
213
|
-
hideLoading(): void {
|
|
214
|
-
if (this.chartInstance) {
|
|
215
|
-
this.chartInstance.hideLoading();
|
|
216
|
-
}
|
|
61
|
+
return this.parseSize((this.config as SwanAdapterOptions).height, 300);
|
|
217
62
|
}
|
|
218
63
|
|
|
219
|
-
|
|
220
|
-
* 销毁图表
|
|
221
|
-
*/
|
|
222
|
-
dispose(): void {
|
|
223
|
-
if (this.chartInstance) {
|
|
224
|
-
this.chartInstance.dispose();
|
|
225
|
-
this.chartInstance = null;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* 处理图表大小变化
|
|
231
|
-
*/
|
|
232
|
-
resize(opts?: any): void {
|
|
233
|
-
if (this.chartInstance) {
|
|
234
|
-
this.chartInstance.resize(opts);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* 设置组件实例
|
|
240
|
-
*/
|
|
241
|
-
setComponent(component: any): void {
|
|
64
|
+
setComponent(component: unknown): void {
|
|
242
65
|
this.component = component;
|
|
243
66
|
}
|
|
244
67
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
*/
|
|
248
|
-
render(): JSX.Element {
|
|
249
|
-
const { canvasId = 'ec-canvas', width = '100%', height = '300px', style = {} } = this.config;
|
|
250
|
-
// 注意:这里需要根据实际使用的Taro版本和组件库来调整
|
|
251
|
-
return React.createElement('view', {
|
|
252
|
-
id: canvasId,
|
|
253
|
-
style: { width, height, ...style },
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* 触发图表行为
|
|
259
|
-
*/
|
|
260
|
-
dispatchAction(payload: any): void {
|
|
261
|
-
if (this.chartInstance) {
|
|
262
|
-
this.chartInstance.dispatchAction(payload);
|
|
263
|
-
}
|
|
68
|
+
dispatchAction(action: unknown): void {
|
|
69
|
+
(this.chartInstance as { dispatchAction?: (a: unknown) => void })?.dispatchAction?.(action);
|
|
264
70
|
}
|
|
265
71
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
*/
|
|
269
|
-
getDataURL(opts?: any): string | undefined {
|
|
270
|
-
return this.chartInstance?.getDataURL(opts);
|
|
72
|
+
getDataURL(opts?: unknown): string | undefined {
|
|
73
|
+
return (this.chartInstance as { getDataURL?: (o?: unknown) => string })?.getDataURL?.(opts);
|
|
271
74
|
}
|
|
272
75
|
}
|
|
273
76
|
|