@tsingroc/tsingroc-components 5.0.0-alpha.10 → 5.0.0-alpha.12

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.
Files changed (140) hide show
  1. package/dist/components/Auth.d.ts +310 -0
  2. package/dist/components/Auth.js +267 -0
  3. package/dist/components/AutoResizedECharts.d.ts +21 -0
  4. package/dist/components/AutoResizedECharts.js +98 -0
  5. package/dist/components/Calendar.d.ts +50 -0
  6. package/dist/components/Calendar.js +130 -0
  7. package/dist/components/CircularProgress.d.ts +21 -0
  8. package/dist/components/CircularProgress.js +34 -0
  9. package/dist/components/ConnectedECharts.d.ts +31 -0
  10. package/dist/components/ConnectedECharts.js +100 -0
  11. package/dist/components/ECharts.d.ts +57 -0
  12. package/dist/components/ECharts.js +255 -0
  13. package/dist/components/Header.d.ts +67 -0
  14. package/dist/components/Header.js +171 -0
  15. package/dist/components/ImageBackground.d.ts +32 -0
  16. package/dist/components/ImageBackground.js +76 -0
  17. package/dist/components/IndicatorLight.d.ts +44 -0
  18. package/dist/components/IndicatorLight.js +124 -0
  19. package/dist/components/LeftAlignedECharts.d.ts +42 -0
  20. package/dist/components/LeftAlignedECharts.js +270 -0
  21. package/dist/components/LineChartEditor.d.ts +74 -0
  22. package/dist/components/LineChartEditor.js +458 -0
  23. package/dist/components/LineChartTable.d.ts +38 -0
  24. package/dist/components/LineChartTable.js +245 -0
  25. package/dist/components/LinkedLineChart.d.ts +45 -0
  26. package/dist/components/LinkedLineChart.js +159 -0
  27. package/dist/components/QuickDateRangePicker.d.ts +30 -0
  28. package/dist/components/QuickDateRangePicker.js +58 -0
  29. package/dist/components/SegmentedButtons.d.ts +22 -0
  30. package/dist/components/SegmentedButtons.js +86 -0
  31. package/dist/components/Sidebar.d.ts +79 -0
  32. package/dist/components/Sidebar.js +178 -0
  33. package/dist/components/TsingrocDatePicker.d.ts +38 -0
  34. package/dist/components/TsingrocDatePicker.js +64 -0
  35. package/dist/components/TsingrocTheme.d.ts +15 -0
  36. package/dist/components/TsingrocTheme.js +72 -0
  37. package/dist/components/UserButton.d.ts +42 -0
  38. package/dist/components/UserButton.js +105 -0
  39. package/dist/components/VerticalColorLegend.d.ts +7 -0
  40. package/dist/components/VerticalColorLegend.js +208 -0
  41. package/dist/components/WeatherMap.d.ts +18 -0
  42. package/dist/components/WeatherMap.js +658 -0
  43. package/dist/deckgl/TiandituLayer.d.ts +13 -0
  44. package/dist/deckgl/TiandituLayer.js +44 -0
  45. package/dist/deckgl/WeatherData.d.ts +53 -0
  46. package/dist/deckgl/WeatherData.js +94 -0
  47. package/dist/deckgl/index.d.ts +1 -0
  48. package/dist/deckgl/index.js +1 -0
  49. package/dist/echarts/coordinateSystems/grid.d.ts +43 -0
  50. package/dist/echarts/coordinateSystems/grid.js +107 -0
  51. package/dist/echarts/coordinateSystems/index.js +2 -0
  52. package/dist/echarts/coordinateSystems/polar.d.ts +45 -0
  53. package/dist/echarts/coordinateSystems/polar.js +96 -0
  54. package/dist/echarts/gl-types.d.js +0 -0
  55. package/dist/echarts/gl.d.ts +115 -0
  56. package/dist/echarts/gl.js +47 -0
  57. package/dist/echarts/index.d.ts +46 -0
  58. package/dist/echarts/index.js +46 -0
  59. package/dist/echarts/legend.d.ts +17 -0
  60. package/dist/echarts/legend.js +15 -0
  61. package/dist/echarts/radar.d.ts +24 -0
  62. package/dist/echarts/radar.js +22 -0
  63. package/dist/echarts/series/barSeries.d.ts +23 -0
  64. package/dist/echarts/series/barSeries.js +18 -0
  65. package/dist/echarts/series/boxplotSeries.d.ts +21 -0
  66. package/dist/echarts/series/boxplotSeries.js +40 -0
  67. package/dist/echarts/series/index.js +7 -0
  68. package/dist/echarts/series/intervalSeries.d.ts +32 -0
  69. package/dist/echarts/series/intervalSeries.js +55 -0
  70. package/dist/echarts/series/lineSeries.d.ts +36 -0
  71. package/dist/echarts/series/lineSeries.js +45 -0
  72. package/dist/echarts/series/maxBarSeries.d.ts +18 -0
  73. package/dist/echarts/series/maxBarSeries.js +39 -0
  74. package/dist/echarts/series/pieSeries.d.ts +31 -0
  75. package/dist/echarts/series/pieSeries.js +47 -0
  76. package/dist/echarts/series/windLineSeries.d.ts +47 -0
  77. package/dist/echarts/series/windLineSeries.js +51 -0
  78. package/{src/echarts/tooltip.ts → dist/echarts/tooltip.d.ts} +1 -5
  79. package/dist/echarts/tooltip.js +18 -0
  80. package/dist/env.d.js +0 -0
  81. package/dist/index.d.ts +20 -0
  82. package/dist/index.js +20 -0
  83. package/dist/utils/debug.d.ts +1 -0
  84. package/dist/utils/debug.js +25 -0
  85. package/dist/utils/index.d.ts +4 -0
  86. package/dist/utils/index.js +4 -0
  87. package/dist/utils/math.d.ts +9 -0
  88. package/{src/utils/math.ts → dist/utils/math.js} +2 -2
  89. package/dist/utils/mock.d.ts +8 -0
  90. package/dist/utils/mock.js +40 -0
  91. package/dist/utils/startOfQuarter.d.ts +2 -0
  92. package/dist/utils/startOfQuarter.js +4 -0
  93. package/package.json +26 -14
  94. package/src/components/Auth.tsx +0 -623
  95. package/src/components/AutoResizedECharts.tsx +0 -70
  96. package/src/components/Calendar.tsx +0 -182
  97. package/src/components/CircularProgress.tsx +0 -38
  98. package/src/components/ConnectedECharts.tsx +0 -62
  99. package/src/components/ECharts.tsx +0 -206
  100. package/src/components/Header.tsx +0 -136
  101. package/src/components/ImageBackground.tsx +0 -58
  102. package/src/components/IndicatorLight.tsx +0 -106
  103. package/src/components/LeftAlignedECharts.tsx +0 -190
  104. package/src/components/LineChartEditor.tsx +0 -558
  105. package/src/components/LineChartTable.tsx +0 -286
  106. package/src/components/LinkedECharts.tsx +0 -51
  107. package/src/components/LinkedLineChart.tsx +0 -144
  108. package/src/components/QuickDateRangePicker.tsx +0 -84
  109. package/src/components/SegmentedButtons.tsx +0 -46
  110. package/src/components/Sidebar.tsx +0 -271
  111. package/src/components/StrictECharts.d.ts +0 -47
  112. package/src/components/StrictECharts.js +0 -1
  113. package/src/components/TsingrocDatePicker.tsx +0 -103
  114. package/src/components/TsingrocTheme.tsx +0 -48
  115. package/src/components/UserButton.tsx +0 -165
  116. package/src/components/VerticalColorLegend.tsx +0 -73
  117. package/src/components/WeatherMap.tsx +0 -522
  118. package/src/deckgl/TiandituLayer.ts +0 -56
  119. package/src/deckgl/WeatherData.ts +0 -157
  120. package/src/deckgl/index.ts +0 -4
  121. package/src/echarts/coordinateSystems/grid.ts +0 -143
  122. package/src/echarts/coordinateSystems/polar.ts +0 -148
  123. package/src/echarts/gl.ts +0 -159
  124. package/src/echarts/index.ts +0 -129
  125. package/src/echarts/legend.ts +0 -36
  126. package/src/echarts/radar.ts +0 -46
  127. package/src/echarts/series/barSeries.ts +0 -37
  128. package/src/echarts/series/boxplotSeries.ts +0 -62
  129. package/src/echarts/series/intervalSeries.ts +0 -70
  130. package/src/echarts/series/lineSeries.ts +0 -78
  131. package/src/echarts/series/maxBarSeries.ts +0 -55
  132. package/src/echarts/series/pieSeries.ts +0 -76
  133. package/src/echarts/series/windLineSeries.ts +0 -113
  134. package/src/index.ts +0 -118
  135. package/src/types.d.ts +0 -5
  136. package/src/utils/debug.ts +0 -39
  137. package/src/utils/mock.ts +0 -69
  138. package/src/utils/startOfQuarter.ts +0 -6
  139. /package/{src/echarts/coordinateSystems/index.ts → dist/echarts/coordinateSystems/index.d.ts} +0 -0
  140. /package/{src/echarts/series/index.ts → dist/echarts/series/index.d.ts} +0 -0
@@ -1,73 +0,0 @@
1
- import { theme } from "antd";
2
- import type { HTMLAttributes } from "react";
3
-
4
- export interface VerticalColorLegendProps
5
- extends HTMLAttributes<HTMLDivElement> {
6
- title?: string;
7
- palette: [number, [number, number, number]][];
8
- }
9
-
10
- function VerticalColorLegend(props: VerticalColorLegendProps) {
11
- const { title, palette, ...rest } = props;
12
- const { token } = theme.useToken();
13
- const max = (palette.at(-1) as [number, [number, number, number]])[0];
14
- const min = palette[0][0];
15
- const range = max - min;
16
- return (
17
- <div
18
- {...rest}
19
- style={{
20
- display: "flex",
21
- flexDirection: "column",
22
- userSelect: "none",
23
- fontSize: token.fontSizeSM,
24
- color: token.colorText,
25
- textShadow:
26
- "-1px -1px white, 0px -1px white, 1px -1px white, 1px 0px white, " +
27
- "1px 1px white, 0px 1px white, -1px 1px white, -1px 0px white",
28
- ...rest.style,
29
- }}
30
- >
31
- <div style={{ fontWeight: "bold" }}>{title}</div>
32
- <div
33
- style={{
34
- display: "flex",
35
- flexBasis: "100%",
36
- alignItems: "stretch",
37
- gap: token.paddingXXS,
38
- paddingBlock: "0.5em",
39
- }}
40
- >
41
- <div
42
- style={{
43
- width: 24,
44
- background: `linear-gradient(
45
- to top,
46
- ${palette
47
- .map(
48
- ([value, color]) =>
49
- `rgb(${color.join(", ")}) ${((value - min) / range) * 100}%`,
50
- )
51
- .join(", ")}
52
- )`,
53
- }}
54
- />
55
- <div style={{ lineHeight: 0, verticalAlign: "middle" }}>
56
- {palette.map(([value], i) => (
57
- <div
58
- key={i}
59
- style={{
60
- position: "relative",
61
- top: `${((max - value) / range) * 100}%`,
62
- }}
63
- >
64
- {value.toFixed(1)}
65
- </div>
66
- ))}
67
- </div>
68
- </div>
69
- </div>
70
- );
71
- }
72
-
73
- export default VerticalColorLegend;
@@ -1,522 +0,0 @@
1
- import { Button, Flex, Slider, Spin, theme, type ButtonProps } from "antd";
2
- import { createStyles } from "antd-style";
3
- import dayjs from "dayjs";
4
- import DeckGL from "deck.gl";
5
- import {
6
- useMemo,
7
- useState,
8
- type CSSProperties,
9
- type HTMLAttributes,
10
- type ReactNode,
11
- } from "react";
12
- import { MdDewPoint, MdThermostat } from "react-icons/md";
13
- import {
14
- WiBarometer,
15
- WiCloudy,
16
- WiHumidity,
17
- WiRain,
18
- WiStrongWind,
19
- } from "react-icons/wi";
20
- import * as wl from "weatherlayers-gl";
21
-
22
- import { TiandituLayer } from "../deckgl";
23
- import {
24
- extractMagnitudeData,
25
- extractScalarData,
26
- extractVectorData,
27
- getBounds,
28
- type WeatherData,
29
- } from "../deckgl/WeatherData";
30
- import TsingrocTheme from "./TsingrocTheme";
31
- import VerticalColorLegend from "./VerticalColorLegend";
32
-
33
- export { type WeatherData };
34
-
35
- export interface WeatherMapProps extends HTMLAttributes<HTMLDivElement> {
36
- /** 天地图平台的 token。*/
37
- tiandituTk: string;
38
- /** 要显示的天气数据。如果为 `undefined`,则会显示加载界面。*/
39
- data: WeatherData | undefined;
40
- }
41
-
42
- /**
43
- * 一张显示各类天气信息的地图。
44
- *
45
- * 多余的属性会被传递给组件最外层的 [`div` 元素][1]。
46
- *
47
- * [1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div
48
- */
49
- function WeatherMap(props: WeatherMapProps) {
50
- const { tiandituTk, data, ...rest } = props;
51
- const { token } = theme.useToken();
52
- const boundingBox = data ? getBounds(data) : undefined;
53
- const [selectedScalar, setSelectedScalar] = useState(SCALAR_VARIABLES[0]);
54
- const hasWind = !!(
55
- data &&
56
- data.data_vars.wind_component_u_10m &&
57
- data.data_vars.wind_component_v_10m
58
- );
59
- const scalarFrames = useMemo(() => {
60
- if (!data) return undefined;
61
- if (
62
- selectedScalar.key === "wind_speed_10m" &&
63
- !data.data_vars.wind_speed_10m &&
64
- hasWind
65
- ) {
66
- return extractMagnitudeData(
67
- data,
68
- "wind_component_u_10m",
69
- "wind_component_v_10m",
70
- );
71
- }
72
- return extractScalarData(data, selectedScalar.key);
73
- }, [data, selectedScalar, hasWind]);
74
- const [showWind, setShowWind] = useState(true);
75
- const windFrames = useMemo(() => {
76
- if (!(hasWind && showWind)) return undefined;
77
- return extractVectorData(
78
- data,
79
- "wind_component_u_10m",
80
- "wind_component_v_10m",
81
- );
82
- }, [data, hasWind, showWind]);
83
- const [timeIdx, setTimeIdx] = useState(0);
84
- const scalarFrame = scalarFrames?.[timeIdx];
85
- const windFrame = windFrames?.[timeIdx];
86
- const palette = useMemo(() => {
87
- if (!scalarFrame) return undefined;
88
- return adaptiveColorCoding(
89
- scalarFrame.min,
90
- scalarFrame.max,
91
- selectedScalar.adaptivePalette,
92
- );
93
- }, [selectedScalar, scalarFrame]);
94
- return (
95
- <TsingrocTheme>
96
- <div {...rest} style={{ position: "relative", ...rest.style }}>
97
- <DeckGL
98
- initialViewState={{ longitude: 0, latitude: 0, zoom: 0, maxPitch: 0 }}
99
- controller={{ dragRotate: false }}
100
- layers={[
101
- new TiandituLayer({ id: "base", tiandituTk }),
102
- new TiandituLayer({ id: "ann", tiandituTk, layer: "annotation" }),
103
- scalarFrame
104
- ? new wl.RasterLayer({
105
- id: "scalar",
106
- opacity: 0.5,
107
- bounds: boundingBox,
108
- image: scalarFrame.image,
109
- palette,
110
- })
111
- : null,
112
- windFrame
113
- ? new wl.ParticleLayer({
114
- id: "wind",
115
- opacity: 0.5,
116
- bounds: boundingBox,
117
- image: windFrame,
118
- numParticles: 1000,
119
- maxAge: 30,
120
- speedFactor: 10,
121
- width: window.devicePixelRatio,
122
- })
123
- : null,
124
- ]}
125
- />
126
- {data && (
127
- <div
128
- style={{
129
- position: "absolute",
130
- inset: "auto 0 0 0",
131
- padding: "4px 8px 0 8px",
132
- background: "linear-gradient(to bottom, transparent, #0007)",
133
- }}
134
- >
135
- <Slider
136
- value={timeIdx}
137
- min={0}
138
- max={data.dims.time - 1}
139
- step={1}
140
- onChange={setTimeIdx}
141
- tooltip={{
142
- formatter: (value) =>
143
- dayjs
144
- .unix(data.coords.time[value as number])
145
- .format("YYYY-MM-DD HH:mm:ss"),
146
- }}
147
- />
148
- </div>
149
- )}
150
- <Flex
151
- vertical
152
- style={{
153
- position: "absolute",
154
- inset: "8px 8px auto auto",
155
- borderRadius: token.borderRadius,
156
- padding: token.paddingXXS,
157
- background: token.colorBgMask,
158
- }}
159
- >
160
- {SCALAR_VARIABLES.filter(
161
- (scalar) =>
162
- !data ||
163
- scalar.key in data.data_vars ||
164
- (scalar.key === "wind_speed_10m" && hasWind),
165
- ).map((scalar) => (
166
- <ToolbarButton
167
- key={scalar.key}
168
- icon={scalar.icon}
169
- selected={selectedScalar.key === scalar.key}
170
- onClick={() => setSelectedScalar(scalar)}
171
- >
172
- {scalar.name}
173
- </ToolbarButton>
174
- ))}
175
- <hr style={{ margin: token.marginXXS }} />
176
- {(!data || hasWind) && (
177
- <ToolbarButton
178
- icon={<WiStrongWind />}
179
- selected={showWind}
180
- onClick={() => setShowWind((b) => !b)}
181
- >
182
- 风力轨迹
183
- </ToolbarButton>
184
- )}
185
- </Flex>
186
- {palette && (
187
- <VerticalColorLegend
188
- title={selectedScalar.name + "(" + selectedScalar.unit + ")"}
189
- palette={palette}
190
- style={{
191
- position: "absolute",
192
- inset: "auto auto 32px 13px",
193
- height: 135,
194
- pointerEvents: "none",
195
- }}
196
- />
197
- )}
198
- {!data && (
199
- <Spin
200
- size="large"
201
- style={{
202
- position: "absolute",
203
- inset: 0,
204
- background: token.colorFillSecondary,
205
- display: "flex",
206
- alignItems: "center",
207
- justifyContent: "center",
208
- }}
209
- />
210
- )}
211
- </div>
212
- </TsingrocTheme>
213
- );
214
- }
215
-
216
- export default WeatherMap;
217
-
218
- function ToolbarButton(props: ButtonProps & { selected: boolean }) {
219
- const { selected, className, children, ...rest } = props;
220
- const { cx, styles } = useStyles();
221
- return (
222
- <Button
223
- color="default"
224
- variant="text"
225
- className={cx(
226
- styles.toolbarButton,
227
- { [styles.toolbarButtonSelected]: selected },
228
- className,
229
- )}
230
- {...rest}
231
- >
232
- <span className={styles.toolbarButtonText}>{children}</span>
233
- </Button>
234
- );
235
- }
236
-
237
- const useStyles = createStyles(({ token, css, prefixCls }) => {
238
- return {
239
- toolbarButton: css`
240
- padding: 0 ${token.paddingXS}px;
241
- background: transparent;
242
-
243
- &:hover:hover:hover {
244
- background: ${token.colorFillSecondary};
245
- }
246
-
247
- &:active:active:active {
248
- background: ${token.colorFill};
249
- }
250
-
251
- &,
252
- &:hover:hover:hover {
253
- color: ${token.colorWhite};
254
- }
255
-
256
- > .${prefixCls}-btn-icon {
257
- font-size: 18px;
258
- }
259
- `,
260
- toolbarButtonSelected: css`
261
- &,
262
- &:hover:hover:hover {
263
- background: ${token.colorBgContainer};
264
- color: ${token.colorText};
265
- }
266
-
267
- &::before {
268
- content: "";
269
- position: absolute;
270
- inset: -1px;
271
- border: inherit;
272
- border-radius: inherit;
273
- transition: inherit;
274
- }
275
-
276
- &:hover:hover:hover::before {
277
- background: ${token.colorFillSecondary};
278
- }
279
-
280
- &:active:active:active::before {
281
- background: ${token.colorFill};
282
- }
283
- `,
284
- toolbarButtonText: css`
285
- flex-basis: 100%;
286
- text-align: left;
287
- `,
288
- };
289
- });
290
-
291
- interface ScalarInfo {
292
- key: keyof WeatherData["data_vars"];
293
- name: string;
294
- unit: string;
295
- icon: ReactNode;
296
- adaptivePalette: AdaptivePalette;
297
- fixedPalette?: [number, Vec3][];
298
- }
299
-
300
- const iconSizeFix = (ratio: number): CSSProperties => ({
301
- fontSize: `${ratio}em`,
302
- margin: `${-(1 - 1 / ratio) / 3}em ${-(1 - 1 / ratio) / 2}em`,
303
- });
304
-
305
- const TEMPERATURE_ADAPTIVE_PALETTE: AdaptivePalette = {
306
- min: [128, 65, 157],
307
- zero: [239, 255, 45],
308
- max: [254, 19, 12],
309
- };
310
-
311
- const TEMPERATURE_FIXED_PALETTE: [number, Vec3][] = [
312
- [-18, [78, 138, 221]],
313
- [-17, [87, 144, 222]],
314
- [-16, [97, 150, 224]],
315
- [-15, [106, 156, 225]],
316
- [-14, [116, 163, 226]],
317
- [-13, [125, 169, 227]],
318
- [-12, [135, 175, 229]],
319
- [-11, [145, 181, 230]],
320
- [-10, [155, 188, 232]],
321
- [-9, [154, 192, 226]],
322
- [-8, [154, 196, 220]],
323
- [-7, [154, 200, 214]],
324
- [-6, [154, 205, 208]],
325
- [-5, [153, 209, 202]],
326
- [-4, [152, 214, 196]],
327
- [-3, [151, 223, 184]],
328
- [-2, [151, 232, 173]],
329
- [-1, [183, 227, 149]],
330
- [0, [215, 222, 125]],
331
- [1, [224, 220, 118]],
332
- [2, [234, 219, 112]],
333
- [3, [239, 218, 105]],
334
- [4, [244, 217, 99]],
335
- [5, [247, 210, 89]],
336
- [6, [250, 204, 79]],
337
- [7, [248, 192, 62]],
338
- [8, [247, 180, 45]],
339
- [9, [244, 167, 22]],
340
- [10, [242, 155, 0]],
341
- [11, [241, 151, 1]],
342
- [12, [241, 147, 3]],
343
- [13, [240, 140, 6]],
344
- [14, [240, 133, 10]],
345
- [15, [239, 125, 13]],
346
- [16, [239, 117, 17]],
347
- [17, [238, 109, 20]],
348
- [18, [238, 101, 24]],
349
- [19, [238, 94, 27]],
350
- [20, [238, 88, 31]],
351
- [21, [234, 81, 28]],
352
- [22, [231, 75, 26]],
353
- [23, [227, 69, 24]],
354
- [24, [224, 63, 22]],
355
- [25, [220, 57, 20]],
356
- [26, [217, 51, 18]],
357
- [27, [212, 43, 16]],
358
- [28, [208, 36, 14]],
359
- [29, [201, 18, 8]],
360
- [30, [194, 0, 3]],
361
- [31, [187, 0, 6]],
362
- [32, [181, 1, 9]],
363
- [33, [175, 1, 12]],
364
- [34, [169, 2, 16]],
365
- [35, [153, 3, 20]],
366
- [36, [138, 5, 25]],
367
- [37, [124, 2, 23]],
368
- [38, [111, 0, 21]],
369
- [39, [95, 0, 18]],
370
- [40, [80, 0, 15]],
371
- [41, [70, 0, 15]],
372
- [42, [60, 0, 15]],
373
- [43, [50, 0, 15]],
374
- [44, [40, 0, 15]],
375
- [45, [30, 0, 15]],
376
- [46, [20, 0, 15]],
377
- ];
378
-
379
- const SCALAR_VARIABLES: ScalarInfo[] = [
380
- {
381
- key: "temperature_2m",
382
- name: "温度",
383
- unit: "℃",
384
- icon: <MdThermostat />,
385
- adaptivePalette: TEMPERATURE_ADAPTIVE_PALETTE,
386
- fixedPalette: TEMPERATURE_FIXED_PALETTE,
387
- },
388
- {
389
- key: "surface_pressure",
390
- name: "气压",
391
- unit: "hPa",
392
- icon: <WiBarometer style={iconSizeFix(1.4)} />,
393
- adaptivePalette: {
394
- min: [80, 202, 75],
395
- max: [254, 19, 12],
396
- },
397
- },
398
- {
399
- key: "cloud_cover",
400
- name: "云量",
401
- unit: "%",
402
- icon: <WiCloudy style={iconSizeFix(1.2)} />,
403
- adaptivePalette: {
404
- min: [239, 255, 45],
405
- max: [255, 255, 255],
406
- },
407
- },
408
- {
409
- key: "dew_point_2m",
410
- name: "露点",
411
- unit: "℃",
412
- icon: <MdDewPoint />,
413
- adaptivePalette: TEMPERATURE_ADAPTIVE_PALETTE,
414
- fixedPalette: TEMPERATURE_FIXED_PALETTE,
415
- },
416
- {
417
- key: "relative_humidity_2m",
418
- name: "相对湿度",
419
- unit: "%",
420
- icon: <WiHumidity style={iconSizeFix(1.3)} />,
421
- adaptivePalette: {
422
- min: [128, 65, 157],
423
- zero: [239, 255, 45],
424
- zeroPoint: 0.5,
425
- max: [254, 19, 12],
426
- },
427
- },
428
- {
429
- key: "wind_speed_10m",
430
- name: "风速",
431
- unit: "m/s",
432
- icon: <WiStrongWind />,
433
- adaptivePalette: {
434
- min: [239, 255, 45],
435
- max: [128, 65, 157],
436
- },
437
- },
438
- {
439
- key: "rain",
440
- name: "降雨量",
441
- unit: "mm",
442
- icon: <WiRain style={iconSizeFix(1.1)} />,
443
- adaptivePalette: {
444
- min: [80, 202, 75],
445
- max: [254, 19, 12],
446
- },
447
- },
448
- ];
449
-
450
- function lerpVec<T extends number[]>(min: T, max: T, pos: number) {
451
- return min.map((min, i) => min + pos * (max[i] - min)) as T;
452
- }
453
-
454
- type Vec3 = [number, number, number];
455
-
456
- interface AdaptivePalette {
457
- min: Vec3;
458
- zero?: Vec3;
459
- zeroPoint?: number;
460
- max: Vec3;
461
- }
462
-
463
- // 参考 https://www.cma.gov.cn/zfxxgk/gknr/flfgbz/bz/202209/P020220921555079517928.pdf
464
- function adaptiveColorCoding(
465
- min: number,
466
- max: number,
467
- base: AdaptivePalette,
468
- ): [number, Vec3][] {
469
- if (base.zero) {
470
- const palette: [number, Vec3][] = [];
471
- const zeroPoint = base.zeroPoint ?? 0;
472
- if (min < zeroPoint) {
473
- palette.push([
474
- min,
475
- lerpVec(
476
- base.zero,
477
- base.min,
478
- Math.min(1, Math.abs((min - zeroPoint) / (max - zeroPoint))),
479
- ),
480
- ]);
481
- } else {
482
- palette.push([min, base.zero]);
483
- }
484
- if (min < zeroPoint && max > zeroPoint) {
485
- palette.push([zeroPoint, base.zero]);
486
- }
487
- if (max > zeroPoint) {
488
- palette.push([
489
- max,
490
- lerpVec(
491
- base.zero,
492
- base.max,
493
- Math.min(1, Math.abs((max - zeroPoint) / (min - zeroPoint))),
494
- ),
495
- ]);
496
- } else {
497
- palette.push([max, base.zero]);
498
- }
499
- return palette;
500
- } else {
501
- return [
502
- [min, base.min],
503
- [max, base.max],
504
- ];
505
- }
506
- }
507
-
508
- // 参考 https://dbba.sacinfo.org.cn/attachment/downloadStdFile?pk=dda6960be9435ed7ab01e336e197cd67a072a28725f03685bfbdaf19cbfeb267
509
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
510
- function fixedColorCoding<T>(min: number, max: number, palette: [number, T][]) {
511
- let minIdx = palette.findIndex(([value]) => value > min) - 1;
512
- if (minIdx < -1) {
513
- minIdx = palette.length - 1;
514
- } else if (minIdx === -1) {
515
- minIdx = 0;
516
- }
517
- let maxIdx = palette.findIndex(([value]) => value >= max);
518
- if (maxIdx < 0) {
519
- maxIdx = 0;
520
- }
521
- return palette.slice(minIdx, maxIdx + 1);
522
- }
@@ -1,56 +0,0 @@
1
- import { BitmapLayer, CompositeLayer } from "deck.gl";
2
- import type { DefaultProps } from "@deck.gl/core";
3
- import { TileLayer, type TileLayerProps } from "@deck.gl/geo-layers";
4
-
5
- export interface TiandituLayerProps {
6
- tiandituTk: string;
7
- type: "vec" | "img" | "ter";
8
- layer: "base" | "annotation";
9
- }
10
-
11
- export default class TiandituLayer extends CompositeLayer<TiandituLayerProps> {
12
- static readonly layerName = "TiandituLayer";
13
- static readonly defaultProps: DefaultProps<TiandituLayerProps> = {
14
- type: { type: "object", value: "vec" },
15
- layer: { type: "object", value: "base" },
16
- };
17
- renderLayers(): TileLayer {
18
- const { tiandituTk, type, layer } = this.props;
19
- const actualType = layer === "base" ? type : "c" + type[0] + "a";
20
- return new TileLayer(
21
- this.getSubLayerProps({
22
- id: actualType,
23
- data: makeUrlTemplate(tiandituTk, actualType),
24
- maxZoom: 18,
25
- zoomOffset: 1,
26
- renderSubLayers,
27
- }) as TileLayerProps,
28
- );
29
- }
30
- }
31
-
32
- const makeUrlTemplate = (tiandituTk: string, type: string) =>
33
- Array.from(
34
- { length: 8 },
35
- (_, i) =>
36
- `https://t${i}.tianditu.gov.cn/${type}_w/wmts` +
37
- `?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0` +
38
- `&LAYER=${type}&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles` +
39
- `&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}` +
40
- `&tk=${tiandituTk}`,
41
- );
42
-
43
- const renderSubLayers: TileLayerProps["renderSubLayers"] = (props) => {
44
- const { boundingBox } = props.tile;
45
- return new BitmapLayer({
46
- ...props,
47
- data: undefined,
48
- image: props.data as string | null,
49
- bounds: [
50
- boundingBox[0][0],
51
- boundingBox[0][1],
52
- boundingBox[1][0],
53
- boundingBox[1][1],
54
- ],
55
- });
56
- };