@tsingroc/tsingroc-components 3.14.0 → 3.14.1

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.
@@ -0,0 +1,157 @@
1
+ import type * as wl from "weatherlayers-gl";
2
+ import type { BitmapBoundingBox } from "@deck.gl/layers";
3
+
4
+ export interface WeatherData {
5
+ dims: {
6
+ longitude: number;
7
+ latitude: number;
8
+ time: number;
9
+ };
10
+ coords: {
11
+ /** deg */
12
+ longitude: number[];
13
+ /** deg */
14
+ latitude: number[];
15
+ /** Unix 时间戳 */
16
+ time: number[];
17
+ };
18
+ data_vars: {
19
+ /** ℃ */
20
+ temperature_2m?: number[][][];
21
+ /** hPa */
22
+ surface_pressure?: number[][][];
23
+ /** % */
24
+ cloud_cover?: number[][][];
25
+ /** ℃ */
26
+ dew_point_2m?: number[][][];
27
+ /** % */
28
+ relative_humidity_2m?: number[][][];
29
+ /** 风速沿纬线向**东**吹(西风)的分量,m/s */
30
+ wind_component_u_10m?: number[][][];
31
+ /** 风速沿经线向**北**吹(南风)的分量,m/s */
32
+ wind_component_v_10m?: number[][][];
33
+ /** m/s */
34
+ wind_speed_10m?: number[][][];
35
+ /** deg,`0` 表示**北风**(往南吹),随着角度增大,风向**顺时针**旋转。*/
36
+ wind_direction_10m?: number[][][];
37
+ /** mm */
38
+ rain?: number[][][];
39
+ };
40
+ }
41
+
42
+ export const getBounds = (data: WeatherData): BitmapBoundingBox => {
43
+ const [lngMin, lngMax] = [
44
+ data.coords.longitude[0],
45
+ data.coords.longitude.at(-1)!,
46
+ ].sort();
47
+ const [latMin, latMax] = [
48
+ data.coords.latitude[0],
49
+ data.coords.latitude.at(-1)!,
50
+ ].sort();
51
+ return [lngMin, latMin, lngMax, latMax];
52
+ };
53
+
54
+ export function extractScalarData(
55
+ data: WeatherData,
56
+ variable: keyof WeatherData["data_vars"],
57
+ ) {
58
+ const result = Array.from({ length: data.dims.time }, () => ({
59
+ image: {
60
+ data: new Float32Array(data.dims.longitude * data.dims.latitude),
61
+ width: data.dims.longitude,
62
+ height: data.dims.latitude,
63
+ } satisfies wl.TextureData as wl.TextureData,
64
+ min: Infinity,
65
+ max: -Infinity,
66
+ mean: 0,
67
+ }));
68
+ let p = 0;
69
+ for (let i = 0; i < data.dims.longitude; i++) {
70
+ for (let j = 0; j < data.dims.latitude; j++) {
71
+ for (let t = 0; t < data.dims.time; t++) {
72
+ let value = data.data_vars[variable]![i][j][t];
73
+ if (value === -9999) value = NaN;
74
+ result[t].image.data[p] = value;
75
+ if (value > result[t].max) result[t].max = value;
76
+ if (value < result[t].min) result[t].min = value;
77
+ }
78
+ p++;
79
+ }
80
+ }
81
+ for (const item of result) {
82
+ item.mean =
83
+ (item.image.data as Float32Array).reduce((a, b) => a + b) /
84
+ item.image.data.length;
85
+ }
86
+ return result;
87
+ }
88
+
89
+ export function extractVectorData(
90
+ data: WeatherData,
91
+ variableU: keyof WeatherData["data_vars"],
92
+ variableV: keyof WeatherData["data_vars"],
93
+ ) {
94
+ const result = Array.from(
95
+ { length: data.dims.time },
96
+ () =>
97
+ ({
98
+ data: new Float32Array(data.dims.longitude * data.dims.latitude * 2),
99
+ width: data.dims.longitude,
100
+ height: data.dims.latitude,
101
+ }) satisfies wl.TextureData as wl.TextureData,
102
+ );
103
+ let p = 0;
104
+ for (let i = 0; i < data.dims.longitude; i++) {
105
+ for (let j = 0; j < data.dims.latitude; j++) {
106
+ for (let t = 0; t < data.dims.time; t++) {
107
+ let u = data.data_vars[variableU]![i][j][t];
108
+ let v = data.data_vars[variableV]![i][j][t];
109
+ if (u === -9999) u = NaN;
110
+ if (v === -9999) v = NaN;
111
+ result[t].data[p] = u;
112
+ result[t].data[p + 1] = v;
113
+ }
114
+ p += 2;
115
+ }
116
+ }
117
+ return result;
118
+ }
119
+
120
+ export function extractMagnitudeData(
121
+ data: WeatherData,
122
+ variableU: keyof WeatherData["data_vars"],
123
+ variableV: keyof WeatherData["data_vars"],
124
+ ) {
125
+ const result = Array.from({ length: data.dims.time }, () => ({
126
+ image: {
127
+ data: new Float32Array(data.dims.longitude * data.dims.latitude),
128
+ width: data.dims.longitude,
129
+ height: data.dims.latitude,
130
+ } satisfies wl.TextureData as wl.TextureData,
131
+ min: Infinity,
132
+ max: -Infinity,
133
+ mean: 0,
134
+ }));
135
+ let p = 0;
136
+ for (let i = 0; i < data.dims.longitude; i++) {
137
+ for (let j = 0; j < data.dims.latitude; j++) {
138
+ for (let t = 0; t < data.dims.time; t++) {
139
+ let u = data.data_vars[variableU]![i][j][t];
140
+ let v = data.data_vars[variableV]![i][j][t];
141
+ if (u === -9999) u = NaN;
142
+ if (v === -9999) v = NaN;
143
+ const value = Math.sqrt(u * u + v * v);
144
+ result[t].image.data[p] = value;
145
+ if (value > result[t].max) result[t].max = value;
146
+ if (value < result[t].min) result[t].min = value;
147
+ }
148
+ p++;
149
+ }
150
+ }
151
+ for (const item of result) {
152
+ item.mean =
153
+ (item.image.data as Float32Array).reduce((a, b) => a + b) /
154
+ item.image.data.length;
155
+ }
156
+ return result;
157
+ }
@@ -0,0 +1,4 @@
1
+ export {
2
+ default as TiandituLayer,
3
+ type TiandituLayerProps,
4
+ } from "./TiandituLayer";
@@ -0,0 +1,132 @@
1
+ import type {
2
+ BarSeriesOption,
3
+ BoxplotSeriesOption,
4
+ FlowGLSeriesOption,
5
+ GridComponentOption,
6
+ LineSeriesOption,
7
+ XAXisComponentOption,
8
+ YAXisComponentOption,
9
+ } from "echarts";
10
+ import { useId } from "react";
11
+
12
+ import type { EChartsComponent, EChartsSeries } from ".";
13
+
14
+ export type GridPreset = (
15
+ grid: GridComponentOption,
16
+ xAxis: XAXisComponentOption,
17
+ yAxis: YAXisComponentOption,
18
+ ) => void;
19
+
20
+ export interface GridOption {
21
+ /**
22
+ * 坐标网格的其它设置,参见 [ECharts 文档][1]。
23
+ *
24
+ * [1]: https://echarts.apache.org/zh/option.html#grid
25
+ */
26
+ option?: GridComponentOption;
27
+ /**
28
+ * X 轴的设置,参见 [ECharts 文档][1]。
29
+ *
30
+ * [1]: https://echarts.apache.org/zh/option.html#xAxis
31
+ */
32
+ xAxis?: XAXisComponentOption;
33
+ /**
34
+ * Y 轴的设置,参见 [ECharts 文档][1]。
35
+ *
36
+ * [1]: https://echarts.apache.org/zh/option.html#yAxis
37
+ */
38
+ yAxis?: YAXisComponentOption;
39
+ /**
40
+ * 预设列表。预设的优先级**高于**上述设置。
41
+ *
42
+ * 可用的预设:{@linkcode minimalGrid}
43
+ */
44
+ presets?: GridPreset[];
45
+ /** 要绘制在该坐标系上的系列。*/
46
+ series?: EChartsSeries<
47
+ | LineSeriesOption
48
+ | BarSeriesOption
49
+ | BoxplotSeriesOption
50
+ | FlowGLSeriesOption
51
+ >[];
52
+ }
53
+
54
+ /**
55
+ * 添加一个直角坐标系。X 轴和 Y 轴的数据类型默认值与 ECharts 原版一致。
56
+ *
57
+ * **注意**:该组件是一个 React hook,需要遵守正常使用 hook 的准则。
58
+ */
59
+ export function useGrid(option: GridOption): EChartsComponent {
60
+ const grid: GridComponentOption = {
61
+ id: useId(),
62
+ left: 0,
63
+ right: 0,
64
+ top: 24,
65
+ bottom: 0,
66
+ containLabel: true,
67
+ ...option.option,
68
+ };
69
+ const gridId = grid.id as string;
70
+ const xAxis: XAXisComponentOption = {
71
+ id: gridId + "x",
72
+ gridId,
73
+ nameGap: 6,
74
+ ...option.xAxis,
75
+ nameTextStyle: { fontWeight: "bold", ...option.xAxis?.nameTextStyle },
76
+ axisTick: {
77
+ alignWithLabel: true,
78
+ ...option.xAxis?.axisTick,
79
+ // 此处需要强转,因为 alignWithLabel 仅当 boundaryGap = true 时有效,但无效也没有影响
80
+ } as XAXisComponentOption["axisTick"],
81
+ };
82
+ const xAxisId = xAxis.id as string;
83
+ const yAxis: YAXisComponentOption = {
84
+ id: gridId + "y",
85
+ type: option.yAxis?.type ?? "value",
86
+ gridId,
87
+ nameGap: 12,
88
+ ...option.yAxis,
89
+ nameTextStyle: {
90
+ align: "left",
91
+ fontWeight: "bold",
92
+ ...option.yAxis?.nameTextStyle,
93
+ },
94
+ };
95
+ const yAxisId = yAxis.id as string;
96
+ option.presets?.forEach((preset) => preset(grid, xAxis, yAxis));
97
+ return {
98
+ grid: [grid],
99
+ xAxis: [xAxis],
100
+ yAxis: [yAxis],
101
+ series: option.series
102
+ ?.flatMap((item) => item.series)
103
+ ?.map((series) => ({
104
+ ...series,
105
+ coordinateSystem: "cartesian2d",
106
+ xAxisId,
107
+ yAxisId,
108
+ })),
109
+ };
110
+ }
111
+
112
+ const MINIMAL_GRID: GridPreset = (grid, xAxis, yAxis) => {
113
+ grid.top = 0;
114
+ xAxis.show = false;
115
+ if (
116
+ (xAxis.type === undefined && (xAxis as { data: [] }).data !== undefined) ||
117
+ xAxis.type === "category"
118
+ ) {
119
+ (xAxis as { boundaryGap: boolean }).boundaryGap = false;
120
+ } else {
121
+ xAxis.min = "dataMin";
122
+ xAxis.max = "dataMax";
123
+ }
124
+ xAxis.axisLabel = { inside: true };
125
+ yAxis.show = false;
126
+ yAxis.axisLabel = { inside: true };
127
+ };
128
+
129
+ /** 使用该预设可以隐藏直角坐标系的坐标轴和网格线,只留下图像本身,并且使其填满整个容器。*/
130
+ export function minimalGrid() {
131
+ return MINIMAL_GRID;
132
+ }
@@ -0,0 +1,158 @@
1
+ import type {
2
+ ComponentOption,
3
+ SeriesOnCartesianOptionMixin,
4
+ SeriesOnGeoOptionMixin,
5
+ } from "echarts/types/src/util/types.js";
6
+ import type { FlowGLSeriesOption as OrigFlowGLSeriesOption } from "echarts";
7
+ import "echarts-gl";
8
+
9
+ import type { EChartsSeries } from ".";
10
+
11
+ // 由于官方没有提供类型定义,这里只能自行补充
12
+ declare module "echarts/types/dist/echarts" {
13
+ interface RegisteredSeriesOption {
14
+ flowGL: FlowGLSeriesOption;
15
+ }
16
+ interface FlowGLSeriesOption
17
+ extends ComponentOption,
18
+ SeriesOnCartesianOptionMixin,
19
+ SeriesOnGeoOptionMixin {
20
+ type: "flowGL";
21
+ /**
22
+ * 粒子的密度,实际的粒子数量是设置数目的平方。粒子密度越大迹线效果越好,但是性能开销也会越大。
23
+ * 除了该属性,使用 `particleType` 也可以得到更加清晰连贯的迹线。
24
+ * @default 128
25
+ */
26
+ particleDensity?: number;
27
+ /**
28
+ * 粒子的类型,可以设置为点 `"point"` 或线 `"line"`。
29
+ * 线类型的粒子会用一条线连接上个运动的位置和当前运动的位置,这会让这个轨迹更加连贯。
30
+ * @default "point"
31
+ */
32
+ particleType?: "point" | "line";
33
+ /**
34
+ * 粒子的大小,如果 `particleType == "line"` 则代表线宽。
35
+ * @default 1
36
+ */
37
+ particleSize?: number;
38
+ /**
39
+ * 粒子的速度,默认为 1。注意在 `particleType` 为 `"point"` 的时候过大的速度会让整个轨迹变得断断续续。
40
+ * @default 1
41
+ */
42
+ particleSpeed?: number;
43
+ /**
44
+ * 粒子的轨迹长度,数值越大轨迹越长。
45
+ * @default 2
46
+ */
47
+ particleTrail?: number;
48
+ /**
49
+ * 画面的超采样比率,采用 4 的超采样可以有效的提高画面的清晰度,减少画面锯齿。
50
+ * 但是因为需要处理更多的像素数量,所以也对性能有更高的要求。
51
+ * @default 1
52
+ */
53
+ supersampling?: number;
54
+ /**
55
+ * 传入的网格数据的网格宽度数量。
56
+ * @default "auto"
57
+ */
58
+ gridWidth?: number | "auto";
59
+ /**
60
+ * 传入的网格数据的网格高度数量。
61
+ * @default "auto"
62
+ */
63
+ gridHeight?: number | "auto";
64
+ /**
65
+ * 每行数据包含四个值,分别表示位置 x、y,速度 sx、sy。
66
+ * 如果使用地理坐标系,则分别表示位置 lng、lat,速度 sLng、sLat。
67
+ */
68
+ data: [number, number, number, number][];
69
+ /**
70
+ * 向量场迹线的样式。
71
+ */
72
+ itemStyle?: FlowGLSeriesItemStyle;
73
+ }
74
+ interface FlowGLSeriesItemStyle {
75
+ /**
76
+ * 向量场迹线的颜色。
77
+ * @default "#fff"
78
+ */
79
+ color?: string;
80
+ /**
81
+ * 向量场迹线的透明度。
82
+ * @default 0.8
83
+ */
84
+ opacity?: number;
85
+ }
86
+ }
87
+
88
+ export interface FlowGLSeriesOption {
89
+ /** 系列名称,不可与其他系列重名。*/
90
+ name: string;
91
+ /**
92
+ * 每行数据包含四个值,分别表示位置 x、y,速度 sx、sy。
93
+ *
94
+ * 如果需要使用风场数据,可以直接调用 {@linkcode preprocessWindData} 来将数据处理成此处需要的格式。
95
+ */
96
+ data: [number, number, number, number][];
97
+ /**
98
+ * 其它需要添加到系列上的选项,参见 [ECharts 文档][1]。
99
+ *
100
+ * [1]: https://echarts.apache.org/zh/option-gl.html#series-flowGL
101
+ */
102
+ option?: Partial<OrigFlowGLSeriesOption>;
103
+ }
104
+
105
+ /**
106
+ * 在坐标系上绘制一个流场。
107
+ *
108
+ * 推荐使用以下坐标系配置:
109
+ *
110
+ * ```ts
111
+ * echarts.useGrid({
112
+ * xAxis: { type: "value" },
113
+ * yAxis: { min: "dataMin", max: "dataMax" },
114
+ * presets: [echarts.minimalGrid()],
115
+ * })
116
+ * ```
117
+ */
118
+ export function flowGLSeries(
119
+ option: FlowGLSeriesOption,
120
+ ): EChartsSeries<OrigFlowGLSeriesOption> {
121
+ return {
122
+ series: [
123
+ {
124
+ type: "flowGL",
125
+ id: option.name,
126
+ name: option.name,
127
+ data: option.data,
128
+ particleDensity: 20,
129
+ particleSize: 3,
130
+ supersampling: window.devicePixelRatio,
131
+ ...option.option,
132
+ },
133
+ ],
134
+ };
135
+ }
136
+
137
+ export interface WindData {
138
+ /** 位置,由空格分隔的经纬度数字组成。*/
139
+ location: string;
140
+ /** 风向,单位是角度(deg),`0` 表示**东风**,随着角度增大,风向**顺时针**旋转。*/
141
+ wind_direction_80m: number;
142
+ /** 风速。*/
143
+ wind_speed_80m: number;
144
+ }
145
+
146
+ /** 将 JSON 格式的天气数据预处理成 FlowGL 接受的格式。*/
147
+ export function preprocessWindData(
148
+ data: WindData[],
149
+ ): [number, number, number, number][] {
150
+ return data.map((item) => {
151
+ const [x, y] = item.location.split(" ").map(Number.parseFloat);
152
+ // prettier-ignore
153
+ const sx = -Math.cos(item.wind_direction_80m * (Math.PI / 180)) * item.wind_speed_80m;
154
+ // prettier-ignore
155
+ const sy = +Math.sin(item.wind_direction_80m * (Math.PI / 180)) * item.wind_speed_80m;
156
+ return [x, y, sx, sy];
157
+ });
158
+ }
@@ -0,0 +1,120 @@
1
+ import type {
2
+ AxisPointerComponentOption,
3
+ Color,
4
+ DataZoomComponentOption,
5
+ EChartsOption,
6
+ GraphicComponentOption,
7
+ GridComponentOption,
8
+ LegendComponentOption,
9
+ RadarComponentOption,
10
+ SeriesOption,
11
+ TooltipComponentOption,
12
+ XAXisComponentOption,
13
+ YAXisComponentOption,
14
+ } from "echarts";
15
+ import { useMemo } from "react";
16
+
17
+ export * from "./coordinateSystem";
18
+ export * from "./radar";
19
+ export * from "./legend";
20
+ export * from "./tooltip";
21
+ export * from "./series";
22
+
23
+ /** 一个可组合的 ECharts 组件。*/
24
+ export interface EChartsComponent {
25
+ grid?: GridComponentOption[];
26
+ xAxis?: XAXisComponentOption[];
27
+ yAxis?: YAXisComponentOption[];
28
+ radar?: RadarComponentOption[];
29
+ legend?: LegendComponentOption[];
30
+ tooltip?: TooltipComponentOption[];
31
+ axisPointer?: AxisPointerComponentOption[];
32
+ dataZoom?: DataZoomComponentOption[];
33
+ graphic?: GraphicComponentOption[];
34
+ series?: SeriesOption[];
35
+ }
36
+
37
+ /** 一个 ECharts 系列。*/
38
+ export interface EChartsSeries<T = SeriesOption> {
39
+ series: T[];
40
+ }
41
+
42
+ /** ECharts 中不可组合的设置项。*/
43
+ export interface EChartsNonComposableOption {
44
+ color?: Color[];
45
+ backgroundColor?: string;
46
+ }
47
+
48
+ /**
49
+ * 第一个参数 `base` 中可以填入不可组合的 ECharts 配置项,例如 `color`。
50
+ * 剩余的参数就是需要组合的各个 ECharts 组件。
51
+ */
52
+ export function buildEChartsOption(
53
+ base: EChartsNonComposableOption,
54
+ ...components: EChartsComponent[]
55
+ ) {
56
+ const option: EChartsComponent & EChartsNonComposableOption = { ...base };
57
+ for (const component of components) {
58
+ Object.entries(component).forEach(([k, value]) => {
59
+ const key = k as keyof EChartsComponent;
60
+ (option[key] ??= []).push(...(value ?? []));
61
+ });
62
+ }
63
+ return option as EChartsOption;
64
+ }
65
+
66
+ /**
67
+ * 用组件组合出 ECharts 的配置对象,并将其缓存以减少重渲染。
68
+ *
69
+ * **注意**:该优化只有在传入的每个组件都已经分别被缓存的情况下才有效!
70
+ * 如果不需要细粒度的记忆化,可以直接将所有组件和 `buildEChartsOption`
71
+ * 整个用 `useMemo` 包裹起来。
72
+ */
73
+ export function useMemoizedEChartsOption(
74
+ base: EChartsNonComposableOption,
75
+ ...components: EChartsComponent[]
76
+ ) {
77
+ return useMemo(
78
+ () => buildEChartsOption(base, ...components),
79
+ components, // eslint-disable-line react-hooks/exhaustive-deps
80
+ );
81
+ }
82
+
83
+ // 一些零散工具
84
+
85
+ /** 一个从 01:00 到 24:00 的数组,可以在等待数据加载时填充 X 轴。*/
86
+ export const HOURS_OF_DAY = Array.from(
87
+ { length: 24 },
88
+ (_, index) => (index + 1).toString().padStart(2, "0") + ":00",
89
+ );
90
+
91
+ /** 虚线图标,可用于图例。*/
92
+ export const DASHES_ICON: string =
93
+ "path://M304.43 532.76H221.4c-11.47 0-20.76-9.3-20.76-20.76s9.29-20.76 20.76-20.76h83.03c11.47 0 20.76 9.3 20.76 20.76s-9.29 20.76-20.76 20.76zM581.19 532.76H442.81c-11.47 0-20.76-9.3-20.76-20.76s9.29-20.76 20.76-20.76h138.38c11.47 0 20.76 9.3 20.76 20.76s-9.3 20.76-20.76 20.76zM802.59 532.76h-83.03c-11.47 0-20.76-9.3-20.76-20.76s9.29-20.76 20.76-20.76h83.03c11.47 0 20.76 9.3 20.76 20.76s-9.29 20.76-20.76 20.76z";
94
+
95
+ /** 公用调色板 1。*/
96
+ export const PALETTE_1 = [
97
+ "#2FDAFF",
98
+ "#77DA9B",
99
+ "#FFB82E",
100
+ "#5470C6",
101
+ "#91CC75",
102
+ "#FAC858",
103
+ "#EE6666",
104
+ "#73C0DE",
105
+ "#3BA272",
106
+ "#FC8452",
107
+ "#9A60B4",
108
+ "#EA7CCC",
109
+ ];
110
+
111
+ /** 公用调色板 2。*/
112
+ export const PALETTE_2 = [
113
+ "#ECA926",
114
+ "#32ADF4",
115
+ "#DC7756",
116
+ "#62CE89",
117
+ "#4256B9",
118
+ "#00D0FF",
119
+ "#96D0DD",
120
+ ];
@@ -0,0 +1,36 @@
1
+ import type { LegendComponentOption } from "echarts";
2
+
3
+ import type { EChartsComponent } from ".";
4
+
5
+ export type LegendDataItem = Exclude<
6
+ (LegendComponentOption["data"] & {})[0],
7
+ string
8
+ >;
9
+
10
+ export interface LegendOption {
11
+ /**
12
+ * 图例中要显示的系列或数据项。
13
+ */
14
+ data: (string | LegendDataItem)[];
15
+ /**
16
+ * 其它图例设置项,参见 [ECharts 文档][1]。
17
+ *
18
+ * [1]: https://echarts.apache.org/zh/option.html#legend
19
+ */
20
+ option?: LegendComponentOption;
21
+ }
22
+
23
+ /** 添加一个图例。 */
24
+ export function legend(option: LegendOption): EChartsComponent {
25
+ return {
26
+ legend: [
27
+ {
28
+ top: 0,
29
+ right: 0,
30
+ padding: 0,
31
+ data: option.data,
32
+ ...option.option,
33
+ },
34
+ ],
35
+ };
36
+ }
@@ -0,0 +1,46 @@
1
+ import type { RadarComponentOption, RadarSeriesOption } from "echarts";
2
+
3
+ import type { EChartsComponent } from ".";
4
+
5
+ export interface RadarOption {
6
+ /** 名称,不可与其它组件和系列重名。*/
7
+ name: string;
8
+ /** 雷达图的各维度。*/
9
+ dimensions: RadarComponentOption["indicator"] & {};
10
+ /** 雷达图的数据。*/
11
+ data: RadarSeriesOption["data"] & {};
12
+ /**
13
+ * 其它传递给雷达图组件的设置项,参见 [ECharts 文档][1]。
14
+ *
15
+ * [1]: https://echarts.apache.org/zh/option.html#radar
16
+ */
17
+ option?: RadarComponentOption;
18
+ /**
19
+ * 其它传递给雷达系列的设置项,参见 [ECharts 文档][1]。
20
+ *
21
+ * [1]: https://echarts.apache.org/zh/option.html#series-radar
22
+ */
23
+ series?: RadarSeriesOption;
24
+ }
25
+
26
+ /** 添加一张雷达图。*/
27
+ export function radar(option: RadarOption): EChartsComponent {
28
+ return {
29
+ radar: [
30
+ {
31
+ id: option.name + "-radar",
32
+ indicator: option.dimensions,
33
+ ...option.option,
34
+ },
35
+ ],
36
+ series: [
37
+ {
38
+ type: "radar",
39
+ name: option.name,
40
+ radarId: option.name + "-radar",
41
+ data: option.data,
42
+ ...option.series,
43
+ },
44
+ ],
45
+ };
46
+ }