deckgl-expansion 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 米斯特呜
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # deckgl-expansion
2
+
3
+ 前端工具库,提供常用工具函数
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pnpm install deckgl-expansion
9
+ ```
10
+
11
+ ## 使用
12
+
13
+ ```typescript
14
+ import { add, subtract, multiply, divide } from 'deckgl-expansion'
15
+
16
+ console.log(add(1, 2)) // 3
17
+ console.log(subtract(5, 3)) // 2
18
+ console.log(multiply(2, 4)) // 8
19
+ console.log(divide(10, 2)) // 5
20
+ ```
21
+
22
+ ## 发布
23
+
24
+ ```bash
25
+ pnpm run build
26
+ npm publish
27
+ ```
@@ -0,0 +1,824 @@
1
+ var W = Object.defineProperty;
2
+ var E = (n, t, e) => t in n ? W(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
3
+ var b = (n, t, e) => E(n, typeof t != "symbol" ? t + "" : t, e);
4
+ import { Layer as $ } from "@deck.gl/core";
5
+ function G() {
6
+ }
7
+ function N(n) {
8
+ return Object.getOwnPropertySymbols(n).filter((t) => Object.prototype.propertyIsEnumerable.call(n, t));
9
+ }
10
+ function P(n) {
11
+ return n == null ? n === void 0 ? "[object Undefined]" : "[object Null]" : Object.prototype.toString.call(n);
12
+ }
13
+ const K = "[object RegExp]", k = "[object String]", q = "[object Number]", Z = "[object Boolean]", z = "[object Arguments]", _ = "[object Symbol]", H = "[object Date]", J = "[object Map]", Q = "[object Set]", tt = "[object Array]", et = "[object Function]", it = "[object ArrayBuffer]", j = "[object Object]", nt = "[object Error]", st = "[object DataView]", ot = "[object Uint8Array]", rt = "[object Uint8ClampedArray]", ct = "[object Uint16Array]", at = "[object Uint32Array]", lt = "[object BigUint64Array]", ht = "[object Int8Array]", ut = "[object Int16Array]", ft = "[object Int32Array]", dt = "[object BigInt64Array]", gt = "[object Float32Array]", xt = "[object Float64Array]";
14
+ function V(n) {
15
+ if (!n || typeof n != "object")
16
+ return !1;
17
+ const t = Object.getPrototypeOf(n);
18
+ return t === null || t === Object.prototype || Object.getPrototypeOf(t) === null ? Object.prototype.toString.call(n) === "[object Object]" : !1;
19
+ }
20
+ function yt(n, t) {
21
+ return n === t || Number.isNaN(n) && Number.isNaN(t);
22
+ }
23
+ function pt(n, t, e) {
24
+ return m(n, t, void 0, void 0, void 0, void 0, e);
25
+ }
26
+ function m(n, t, e, i, s, o, c) {
27
+ const a = c(n, t, e, i, s, o);
28
+ if (a !== void 0)
29
+ return a;
30
+ if (typeof n == typeof t)
31
+ switch (typeof n) {
32
+ case "bigint":
33
+ case "string":
34
+ case "boolean":
35
+ case "symbol":
36
+ case "undefined":
37
+ return n === t;
38
+ case "number":
39
+ return n === t || Object.is(n, t);
40
+ case "function":
41
+ return n === t;
42
+ case "object":
43
+ return w(n, t, o, c);
44
+ }
45
+ return w(n, t, o, c);
46
+ }
47
+ function w(n, t, e, i) {
48
+ if (Object.is(n, t))
49
+ return !0;
50
+ let s = P(n), o = P(t);
51
+ if (s === z && (s = j), o === z && (o = j), s !== o)
52
+ return !1;
53
+ switch (s) {
54
+ case k:
55
+ return n.toString() === t.toString();
56
+ case q: {
57
+ const r = n.valueOf(), l = t.valueOf();
58
+ return yt(r, l);
59
+ }
60
+ case Z:
61
+ case H:
62
+ case _:
63
+ return Object.is(n.valueOf(), t.valueOf());
64
+ case K:
65
+ return n.source === t.source && n.flags === t.flags;
66
+ case et:
67
+ return n === t;
68
+ }
69
+ e = e ?? /* @__PURE__ */ new Map();
70
+ const c = e.get(n), a = e.get(t);
71
+ if (c != null && a != null)
72
+ return c === t;
73
+ e.set(n, t), e.set(t, n);
74
+ try {
75
+ switch (s) {
76
+ case J: {
77
+ if (n.size !== t.size)
78
+ return !1;
79
+ for (const [r, l] of n.entries())
80
+ if (!t.has(r) || !m(l, t.get(r), r, n, t, e, i))
81
+ return !1;
82
+ return !0;
83
+ }
84
+ case Q: {
85
+ if (n.size !== t.size)
86
+ return !1;
87
+ const r = Array.from(n.values()), l = Array.from(t.values());
88
+ for (let f = 0; f < r.length; f++) {
89
+ const h = r[f], u = l.findIndex((d) => m(h, d, void 0, n, t, e, i));
90
+ if (u === -1)
91
+ return !1;
92
+ l.splice(u, 1);
93
+ }
94
+ return !0;
95
+ }
96
+ case tt:
97
+ case ot:
98
+ case rt:
99
+ case ct:
100
+ case at:
101
+ case lt:
102
+ case ht:
103
+ case ut:
104
+ case ft:
105
+ case dt:
106
+ case gt:
107
+ case xt: {
108
+ if (typeof Buffer < "u" && Buffer.isBuffer(n) !== Buffer.isBuffer(t) || n.length !== t.length)
109
+ return !1;
110
+ for (let r = 0; r < n.length; r++)
111
+ if (!m(n[r], t[r], r, n, t, e, i))
112
+ return !1;
113
+ return !0;
114
+ }
115
+ case it:
116
+ return n.byteLength !== t.byteLength ? !1 : w(new Uint8Array(n), new Uint8Array(t), e, i);
117
+ case st:
118
+ return n.byteLength !== t.byteLength || n.byteOffset !== t.byteOffset ? !1 : w(new Uint8Array(n), new Uint8Array(t), e, i);
119
+ case nt:
120
+ return n.name === t.name && n.message === t.message;
121
+ case j: {
122
+ if (!(w(n.constructor, t.constructor, e, i) || V(n) && V(t)))
123
+ return !1;
124
+ const l = [...Object.keys(n), ...N(n)], f = [...Object.keys(t), ...N(t)];
125
+ if (l.length !== f.length)
126
+ return !1;
127
+ for (let h = 0; h < l.length; h++) {
128
+ const u = l[h], d = n[u];
129
+ if (!Object.hasOwn(t, u))
130
+ return !1;
131
+ const x = t[u];
132
+ if (!m(d, x, u, n, t, e, i))
133
+ return !1;
134
+ }
135
+ return !0;
136
+ }
137
+ default:
138
+ return !1;
139
+ }
140
+ } finally {
141
+ e.delete(n), e.delete(t);
142
+ }
143
+ }
144
+ function mt(n, t) {
145
+ return pt(n, t, G);
146
+ }
147
+ const wt = Object.prototype.hasOwnProperty, y = typeof Symbol < "u" ? Symbol.toStringTag : void 0;
148
+ function bt(n) {
149
+ if (n === null)
150
+ return n === void 0 ? "[object Undefined]" : "[object Null]";
151
+ if (!(y && y in Object(n)))
152
+ return toString.call(n);
153
+ const t = wt.call(n, y), e = n[y];
154
+ let i = !1;
155
+ try {
156
+ n[y] = void 0, i = !0;
157
+ } catch {
158
+ }
159
+ const s = Object.prototype.toString.call(n);
160
+ return i && (t ? n[y] = e : delete n[y]), s;
161
+ }
162
+ function p(n) {
163
+ if (!jt(n))
164
+ return !1;
165
+ const t = bt(n);
166
+ return t === "[object Function]" || t === "[object AsyncFunction]" || t === "[object GeneratorFunction]" || t === "[object Proxy]";
167
+ }
168
+ function jt(n) {
169
+ const t = typeof n;
170
+ return n !== null && (t === "object" || t === "function");
171
+ }
172
+ function At(n) {
173
+ return n == null ? !1 : typeof n == "string" || n.constructor !== null && n.constructor === String;
174
+ }
175
+ function A(n) {
176
+ return Object.prototype.toString.call(n) === "[object Number]" && !isNaN(n);
177
+ }
178
+ function vt(n) {
179
+ return Array.isArray(n);
180
+ }
181
+ function St(n, t) {
182
+ console.warn(`${t}: ${n}`);
183
+ }
184
+ const Y = {};
185
+ function Ot(n, t) {
186
+ Y[t] || (St(t, n), Y[t] = !0);
187
+ }
188
+ function It(n, t) {
189
+ return n - t * Math.floor(n / t);
190
+ }
191
+ function g(n) {
192
+ return n != null && !isNaN(n);
193
+ }
194
+ function Tt(n, t = {}) {
195
+ let e, i;
196
+ if (n.forEach(function(c) {
197
+ switch (c.header.parameterCategory + "," + c.header.parameterNumber) {
198
+ case "1,2":
199
+ case "2,2":
200
+ e = c;
201
+ break;
202
+ case "1,3":
203
+ case "2,3":
204
+ i = c;
205
+ break;
206
+ }
207
+ }), !i || !e)
208
+ return;
209
+ const s = e.header;
210
+ return new B({
211
+ xmin: s.lo1,
212
+ // 一般格点数据是按照矩形范围来切割,所以定义其经纬度范围
213
+ ymin: s.la1,
214
+ xmax: s.lo2,
215
+ ymax: s.la2,
216
+ deltaX: s.dx,
217
+ // x(经度)增量
218
+ deltaY: s.dy,
219
+ // y(维度)增量
220
+ cols: s.nx,
221
+ // 列(可由 `(xmax - xmin) / deltaX` 得到)
222
+ rows: s.ny,
223
+ // 行
224
+ us: e.data,
225
+ // U分量
226
+ vs: i.data,
227
+ // V分量
228
+ ...t
229
+ });
230
+ }
231
+ function Ct(n, t, e, i) {
232
+ if (typeof document < "u") {
233
+ const s = document.createElement("canvas");
234
+ return s.width = n * e, s.height = t * e, s;
235
+ } else
236
+ return new i(n * e, t * e);
237
+ }
238
+ function Mt(n) {
239
+ return n ? (n.parentNode && n.parentNode.removeChild(n), n) : null;
240
+ }
241
+ class L {
242
+ constructor(t, e) {
243
+ this.u = t, this.v = e, this.m = this.magnitude();
244
+ }
245
+ /**
246
+ * 向量值(这里指风速)
247
+ * @returns {Number}
248
+ */
249
+ magnitude() {
250
+ return Math.sqrt(this.u ** 2 + this.v ** 2);
251
+ }
252
+ /**
253
+ * 流体方向 (这里指风向,范围为0-360º)
254
+ * N is 0º and E is 90º
255
+ * @returns {Number}
256
+ */
257
+ directionTo() {
258
+ let e = Math.atan2(this.u, this.v) * (180 / Math.PI);
259
+ return e < 0 && (e += 360), e;
260
+ }
261
+ /**
262
+ * Angle in degrees (0 to 360º) From x-->
263
+ * N is 0º and E is 90º
264
+ * @returns {Number}
265
+ */
266
+ directionFrom() {
267
+ return (this.directionTo() + 180) % 360;
268
+ }
269
+ }
270
+ class B {
271
+ constructor(t) {
272
+ this.grid = [], this.xmin = t.xmin, this.xmax = t.xmax, this.ymin = t.ymin, this.ymax = t.ymax, this.cols = t.cols, this.rows = t.rows, this.us = t.us, this.vs = t.vs, this.deltaX = t.deltaX, this.deltaY = t.deltaY, this.flipY = !!t.flipY, this.ymin = Math.min(t.ymax, t.ymin), this.ymax = Math.max(t.ymax, t.ymin), this.deltaY < 0 && this.ymin < this.ymax || (t.flipY === void 0 && (this.flipY = !0), console.warn("[wind-core]: The data is flipY")), this.isFields = !0;
273
+ const e = Math.ceil((this.xmax - this.xmin) / t.deltaX), i = Math.ceil((this.ymax - this.ymin) / t.deltaY);
274
+ (e !== this.cols || i !== this.rows) && console.warn("[wind-core]: The data grid not equal"), this.isContinuous = Math.floor(this.cols * t.deltaX) >= 360, this.translateX = "translateX" in t ? t.translateX : this.xmax > 180, "wrappedX" in t && Ot("[wind-core]: ", "`wrappedX` namespace will deprecated please use `translateX` instead!"), this.wrapX = !!t.wrapX, this.grid = this.buildGrid(), this.range = this.calculateRange();
275
+ }
276
+ // from https://github.com/sakitam-fdd/wind-layer/blob/95368f9433/src/windy/windy.js#L110
277
+ buildGrid() {
278
+ const t = [];
279
+ let e = 0;
280
+ const { rows: i, cols: s, us: o, vs: c } = this;
281
+ for (let a = 0; a < i; a++) {
282
+ const r = [];
283
+ for (let l = 0; l < s; l++, e++) {
284
+ const f = o[e], h = c[e], u = this.isValid(f) && this.isValid(h);
285
+ r[l] = u ? new L(f, h) : null;
286
+ }
287
+ this.isContinuous && r.push(r[0]), t[a] = r;
288
+ }
289
+ return t;
290
+ }
291
+ /**
292
+ * release data
293
+ */
294
+ release() {
295
+ this.grid = [];
296
+ }
297
+ /**
298
+ * grib data extent
299
+ * 格点数据范围
300
+ */
301
+ extent() {
302
+ return [this.xmin, this.ymin, this.xmax, this.ymax];
303
+ }
304
+ /**
305
+ * Bilinear interpolation for Vector
306
+ * 针对向量进行双线性插值
307
+ * https://en.wikipedia.org/wiki/Bilinear_interpolation
308
+ * @param {Number} x
309
+ * @param {Number} y
310
+ * @param {Number[]} g00
311
+ * @param {Number[]} g10
312
+ * @param {Number[]} g01
313
+ * @param {Number[]} g11
314
+ * @returns {Vector}
315
+ */
316
+ bilinearInterpolateVector(t, e, i, s, o, c) {
317
+ const a = 1 - t, r = 1 - e, l = a * r, f = t * r, h = a * e, u = t * e, d = i.u * l + s.u * f + o.u * h + c.u * u, x = i.v * l + s.v * f + o.v * h + c.v * u;
318
+ return new L(d, x);
319
+ }
320
+ /**
321
+ * calculate vector value range
322
+ */
323
+ calculateRange() {
324
+ if (!this.grid || !this.grid[0])
325
+ return;
326
+ const t = this.grid.length, e = this.grid[0].length;
327
+ let i, s;
328
+ for (let o = 0; o < t; o++)
329
+ for (let c = 0; c < e; c++) {
330
+ const a = this.grid[o][c];
331
+ if (a !== null) {
332
+ const r = a.m || a.magnitude();
333
+ i === void 0 ? i = r : s === void 0 ? (s = r, i = Math.min(i, s), s = Math.max(i, s)) : (i = Math.min(r, i), s = Math.max(r, s));
334
+ }
335
+ }
336
+ return [i, s];
337
+ }
338
+ /**
339
+ * 检查 uv是否合法
340
+ * @param x
341
+ * @private
342
+ */
343
+ isValid(t) {
344
+ return t != null;
345
+ }
346
+ getWrappedLongitudes() {
347
+ let t = this.xmin, e = this.xmax;
348
+ return this.translateX && (this.isContinuous ? (t = -180, e = 180) : (e = this.xmax - 360, t = this.xmin - 360)), [t, e];
349
+ }
350
+ contains(t, e) {
351
+ const [i, s] = this.getWrappedLongitudes();
352
+ s > 180 && t >= -180 && t <= s - 360 ? t += 360 : i < -180 && t <= 180 && t >= i + 360 && (t -= 360);
353
+ const o = t >= i && t <= s;
354
+ let c;
355
+ return this.deltaY >= 0 ? c = e >= this.ymin && e <= this.ymax : c = e >= this.ymax && e <= this.ymin, o && c;
356
+ }
357
+ /**
358
+ * 获取经纬度所在的位置索引
359
+ * @param lon
360
+ * @param lat
361
+ */
362
+ getDecimalIndexes(t, e) {
363
+ const i = It(t - this.xmin, 360) / this.deltaX;
364
+ if (this.flipY) {
365
+ const s = (this.ymax - e) / this.deltaY;
366
+ return [i, s];
367
+ } else {
368
+ const s = (this.ymin + e) / this.deltaY;
369
+ return [i, s];
370
+ }
371
+ }
372
+ /**
373
+ * Nearest value at lon-lat coordinates
374
+ * 线性插值
375
+ * @param lon
376
+ * @param lat
377
+ */
378
+ valueAt(t, e) {
379
+ let i = !1;
380
+ if ((this.wrapX || this.contains(t, e)) && (i = !0), !i)
381
+ return null;
382
+ const s = this.getDecimalIndexes(t, e), o = Math.floor(s[0]), c = Math.floor(s[1]), a = this.clampColumnIndex(o), r = this.clampRowIndex(c);
383
+ return this.valueAtIndexes(a, r);
384
+ }
385
+ /**
386
+ * Get interpolated grid value lon-lat coordinates
387
+ * 双线性插值
388
+ * @param lon
389
+ * @param lat
390
+ */
391
+ interpolatedValueAt(t, e) {
392
+ let i = !1;
393
+ if ((this.wrapX || this.contains(t, e)) && (i = !0), !i)
394
+ return null;
395
+ const [s, o] = this.getDecimalIndexes(t, e);
396
+ return this.interpolatePoint(s, o);
397
+ }
398
+ hasValueAt(t, e) {
399
+ return this.valueAt(t, e) !== null;
400
+ }
401
+ /**
402
+ * 基于向量的双线性插值
403
+ * @param i
404
+ * @param j
405
+ */
406
+ interpolatePoint(t, e) {
407
+ const i = this.getFourSurroundingIndexes(t, e), [s, o, c, a] = i, r = this.getFourSurroundingValues(s, o, c, a);
408
+ if (r) {
409
+ const [l, f, h, u] = r;
410
+ return this.bilinearInterpolateVector(t - s, e - c, l, f, h, u);
411
+ }
412
+ return null;
413
+ }
414
+ /**
415
+ * Check the column index is inside the field,
416
+ * adjusting to min or max when needed
417
+ * @private
418
+ * @param {Number} ii - index
419
+ * @returns {Number} i - inside the allowed indexes
420
+ */
421
+ clampColumnIndex(t) {
422
+ let e = t;
423
+ t < 0 && (e = 0);
424
+ const i = this.cols - 1;
425
+ return t > i && (e = i), e;
426
+ }
427
+ /**
428
+ * Check the row index is inside the field,
429
+ * adjusting to min or max when needed
430
+ * @private
431
+ * @param {Number} jj index
432
+ * @returns {Number} j - inside the allowed indexes
433
+ */
434
+ clampRowIndex(t) {
435
+ let e = t;
436
+ t < 0 && (e = 0);
437
+ const i = this.rows - 1;
438
+ return t > i && (e = i), e;
439
+ }
440
+ /**
441
+ * 计算索引位置周围的数据
442
+ * @private
443
+ * @param {Number} i - decimal index
444
+ * @param {Number} j - decimal index
445
+ * @returns {Array} [fi, ci, fj, cj]
446
+ */
447
+ getFourSurroundingIndexes(t, e) {
448
+ const i = Math.floor(t);
449
+ let s = i + 1;
450
+ this.isContinuous && s >= this.cols && (s = 0), s = this.clampColumnIndex(s);
451
+ const o = this.clampRowIndex(Math.floor(e)), c = this.clampRowIndex(o + 1);
452
+ return [i, s, o, c];
453
+ }
454
+ /**
455
+ * Get four surrounding values or null if not available,
456
+ * from 4 integer indexes
457
+ * @private
458
+ * @param {Number} fi
459
+ * @param {Number} ci
460
+ * @param {Number} fj
461
+ * @param {Number} cj
462
+ * @returns {Array}
463
+ */
464
+ getFourSurroundingValues(t, e, i, s) {
465
+ let o;
466
+ if (o = this.grid[i]) {
467
+ const c = o[t], a = o[e];
468
+ if (this.isValid(c) && this.isValid(a) && (o = this.grid[s])) {
469
+ const r = o[t], l = o[e];
470
+ if (this.isValid(r) && this.isValid(l))
471
+ return [c, a, r, l];
472
+ }
473
+ }
474
+ return null;
475
+ }
476
+ /**
477
+ * Value for grid indexes
478
+ * @param {Number} i - column index (integer)
479
+ * @param {Number} j - row index (integer)
480
+ * @returns {Vector|Number}
481
+ */
482
+ valueAtIndexes(t, e) {
483
+ return this.grid[e][t];
484
+ }
485
+ /**
486
+ * Lon-Lat for grid indexes
487
+ * @param {Number} i - column index (integer)
488
+ * @param {Number} j - row index (integer)
489
+ * @returns {Number[]} [lon, lat]
490
+ */
491
+ lonLatAtIndexes(t, e) {
492
+ const i = this.longitudeAtX(t), s = this.latitudeAtY(e);
493
+ return [i, s];
494
+ }
495
+ /**
496
+ * Longitude for grid-index
497
+ * @param {Number} i - column index (integer)
498
+ * @returns {Number} longitude at the center of the cell
499
+ */
500
+ longitudeAtX(t) {
501
+ const e = this.deltaX / 2;
502
+ let i = this.xmin + e + t * this.deltaX;
503
+ return this.translateX && (i = i > 180 ? i - 360 : i), i;
504
+ }
505
+ /**
506
+ * Latitude for grid-index
507
+ * @param {Number} j - row index (integer)
508
+ * @returns {Number} latitude at the center of the cell
509
+ */
510
+ latitudeAtY(t) {
511
+ const e = this.deltaY / 2;
512
+ return this.ymax - e - t * this.deltaY;
513
+ }
514
+ /**
515
+ * 生成粒子位置
516
+ * @param o
517
+ * @param width
518
+ * @param height
519
+ * @param unproject
520
+ * @return IPosition
521
+ */
522
+ randomize(t = {}, e, i, s) {
523
+ const o = Math.random() * (e || this.cols) | 0, c = Math.random() * (i || this.rows) | 0, a = s([o, c]);
524
+ return a !== null ? (t.x = a[0], t.y = a[1]) : (t.x = this.longitudeAtX(o), t.y = this.latitudeAtY(c)), t;
525
+ }
526
+ /**
527
+ * 判断是否是 `Field` 的实例
528
+ * @return boolean
529
+ */
530
+ checkFields() {
531
+ return this.isFields;
532
+ }
533
+ }
534
+ const U = {
535
+ globalAlpha: 0.9,
536
+ // 全局透明度
537
+ lineWidth: 1,
538
+ // 线条宽度
539
+ colorScale: "#fff",
540
+ velocityScale: 1 / 25,
541
+ // particleAge: 90,
542
+ maxAge: 90,
543
+ // alias for particleAge
544
+ // particleMultiplier: 1 / 300, // TODO: PATHS = Math.round(width * height * particleMultiplier);
545
+ paths: 800,
546
+ frameRate: 20,
547
+ useCoordsDraw: !0
548
+ };
549
+ function R(n, t, e, i) {
550
+ return Math.max(0, Math.min(i.length - 1, Math.round((n - t) / (e - t) * (i.length - 1))));
551
+ }
552
+ const S = class S {
553
+ constructor(t, e, i) {
554
+ if (this.particles = [], this.generated = !1, this.ctx = t, !this.ctx)
555
+ throw new Error("ctx error");
556
+ this.animate = this.animate.bind(this), this.setOptions(e), i && this.updateData(i);
557
+ }
558
+ /**
559
+ * 设置配置项
560
+ * @param options
561
+ */
562
+ setOptions(t) {
563
+ this.options = { ...U, ...t };
564
+ const { width: e, height: i } = this.ctx.canvas;
565
+ "particleAge" in t && !("maxAge" in t) && A(this.options.particleAge) && (this.options.maxAge = this.options.particleAge), "particleMultiplier" in t && !("paths" in t) && A(this.options.particleMultiplier) && (this.options.paths = Math.round(e * i * this.options.particleMultiplier)), this.prerender();
566
+ }
567
+ /**
568
+ * 获取配置项
569
+ */
570
+ getOptions() {
571
+ return this.options;
572
+ }
573
+ /**
574
+ * 更新数据
575
+ * @param field
576
+ */
577
+ updateData(t) {
578
+ this.field = t, this.generated && (this.particles = this.prepareParticlePaths());
579
+ }
580
+ // @ts-ignore
581
+ project(...t) {
582
+ throw new Error("project must be overriden");
583
+ }
584
+ // @ts-ignore
585
+ unproject(...t) {
586
+ throw new Error("unproject must be overriden");
587
+ }
588
+ /**
589
+ * 判断位置是否在当前视窗内
590
+ * @param coordinates
591
+ */
592
+ intersectsCoordinate(t) {
593
+ throw new Error("must be overriden");
594
+ }
595
+ /**
596
+ * 清空当前画布
597
+ */
598
+ clearCanvas() {
599
+ this.stop(), this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height), this.forceStop = !1;
600
+ }
601
+ isStop() {
602
+ return !this.starting;
603
+ }
604
+ /**
605
+ * 启动粒子动画
606
+ */
607
+ start() {
608
+ this.starting = !0, this.forceStop = !1, this.then = Date.now(), this.animate();
609
+ }
610
+ /**
611
+ * 停止粒子动画
612
+ */
613
+ stop() {
614
+ cancelAnimationFrame(this.animationLoop), this.starting = !1, this.forceStop = !0;
615
+ }
616
+ animate() {
617
+ this.animationLoop && cancelAnimationFrame(this.animationLoop), this.animationLoop = requestAnimationFrame(this.animate);
618
+ const t = Date.now(), e = t - this.then;
619
+ e > this.options.frameRate && (this.then = t - e % this.options.frameRate, this.render());
620
+ }
621
+ /**
622
+ * 渲染前处理
623
+ */
624
+ prerender() {
625
+ this.generated = !1, this.field && (this.particles = this.prepareParticlePaths(), this.generated = !0, !this.starting && !this.forceStop && (this.starting = !0, this.then = Date.now(), this.animate()));
626
+ }
627
+ /**
628
+ * 开始渲染
629
+ */
630
+ render() {
631
+ this.moveParticles(), this.drawParticles(), this.postrender();
632
+ }
633
+ /**
634
+ * each frame render end
635
+ */
636
+ postrender() {
637
+ }
638
+ moveParticles() {
639
+ const { width: t, height: e } = this.ctx.canvas, i = this.particles, s = this.options.maxAge, o = p(this.options.velocityScale) ? this.options.velocityScale() : this.options.velocityScale;
640
+ let c = 0;
641
+ const a = i.length;
642
+ for (; c < a; c++) {
643
+ const r = i[c];
644
+ r.age > s && (r.age = 0, this.field.randomize(r, t, e, this.unproject));
645
+ const l = r.x, f = r.y, h = this.field.interpolatedValueAt(l, f);
646
+ if (h === null)
647
+ r.age = s;
648
+ else {
649
+ const u = l + h.u * o, d = f + h.v * o;
650
+ this.field.hasValueAt(u, d) ? (r.xt = u, r.yt = d, r.m = h.m) : (r.x = u, r.y = d, r.age = s);
651
+ }
652
+ r.age++;
653
+ }
654
+ }
655
+ fadeIn() {
656
+ const t = this.ctx.globalCompositeOperation;
657
+ this.ctx.globalCompositeOperation = "destination-in", this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height), this.ctx.globalCompositeOperation = t;
658
+ }
659
+ drawParticles() {
660
+ const t = this.particles;
661
+ this.fadeIn(), this.ctx.globalAlpha = this.options.globalAlpha, this.ctx.fillStyle = `rgba(0, 0, 0, ${this.options.globalAlpha})`, this.ctx.lineWidth = A(this.options.lineWidth) ? this.options.lineWidth : 1, this.ctx.strokeStyle = At(this.options.colorScale) ? this.options.colorScale : "#fff";
662
+ let e = 0;
663
+ const i = t.length;
664
+ if (this.field && i > 0) {
665
+ let s, o;
666
+ for (g(this.options.minVelocity) && g(this.options.maxVelocity) ? (s = this.options.minVelocity, o = this.options.maxVelocity) : [s, o] = this.field.range; e < i; e++)
667
+ this[this.options.useCoordsDraw ? "drawCoordsParticle" : "drawPixelParticle"](t[e], s, o);
668
+ }
669
+ }
670
+ /**
671
+ * 用于绘制像素粒子
672
+ * @param particle
673
+ * @param min
674
+ * @param max
675
+ */
676
+ drawPixelParticle(t, e, i) {
677
+ const s = [t.x, t.y], o = [t.xt, t.yt];
678
+ if (o && s && g(o[0]) && g(o[1]) && g(s[0]) && g(s[1]) && t.age <= this.options.maxAge) {
679
+ if (this.ctx.beginPath(), this.ctx.moveTo(s[0], s[1]), this.ctx.lineTo(o[0], o[1]), p(this.options.colorScale))
680
+ this.ctx.strokeStyle = this.options.colorScale(t.m);
681
+ else if (Array.isArray(this.options.colorScale)) {
682
+ const c = R(t.m, e, i, this.options.colorScale);
683
+ this.ctx.strokeStyle = this.options.colorScale[c];
684
+ }
685
+ p(this.options.lineWidth) && (this.ctx.lineWidth = this.options.lineWidth(t.m)), t.x = t.xt, t.y = t.yt, this.ctx.stroke();
686
+ }
687
+ }
688
+ /**
689
+ * 用于绘制坐标粒子
690
+ * @param particle
691
+ * @param min
692
+ * @param max
693
+ */
694
+ drawCoordsParticle(t, e, i) {
695
+ const s = [t.x, t.y], o = [t.xt, t.yt];
696
+ if (o && s && g(o[0]) && g(o[1]) && g(s[0]) && g(s[1]) && this.intersectsCoordinate(o) && t.age <= this.options.maxAge) {
697
+ const c = this.project(s), a = this.project(o);
698
+ if (c && a) {
699
+ if (this.ctx.beginPath(), this.ctx.moveTo(c[0], c[1]), this.ctx.lineTo(a[0], a[1]), t.x = t.xt, t.y = t.yt, p(this.options.colorScale))
700
+ this.ctx.strokeStyle = this.options.colorScale(t.m);
701
+ else if (Array.isArray(this.options.colorScale)) {
702
+ const r = R(t.m, e, i, this.options.colorScale);
703
+ this.ctx.strokeStyle = this.options.colorScale[r];
704
+ }
705
+ p(this.options.lineWidth) && (this.ctx.lineWidth = this.options.lineWidth(t.m)), this.ctx.stroke();
706
+ }
707
+ }
708
+ }
709
+ prepareParticlePaths() {
710
+ const { width: t, height: e } = this.ctx.canvas, i = typeof this.options.paths == "function" ? this.options.paths(this) : this.options.paths, s = [];
711
+ if (!this.field)
712
+ return [];
713
+ let o = 0;
714
+ for (; o < i; o++)
715
+ s.push(
716
+ this.field.randomize(
717
+ {
718
+ age: this.randomize()
719
+ },
720
+ t,
721
+ e,
722
+ this.unproject
723
+ )
724
+ );
725
+ return s;
726
+ }
727
+ randomize() {
728
+ return Math.floor(Math.random() * this.options.maxAge);
729
+ }
730
+ };
731
+ S.Field = B;
732
+ let v = S;
733
+ class Ft extends $ {
734
+ constructor(e) {
735
+ super(e);
736
+ b(this, "_defaultOptions", {
737
+ ...U
738
+ });
739
+ this.props.zIndex = this.props.zIndex || "unset";
740
+ }
741
+ initializeState() {
742
+ this.init();
743
+ }
744
+ shouldUpdateState({ changeFlags: e }) {
745
+ return e.somethingChanged;
746
+ }
747
+ updateState({ props: e, oldProps: i, context: s }) {
748
+ var f;
749
+ const { bounds: o, wind: c, windOptions: a } = this.state, r = (o == null ? void 0 : o.reduce((h, u) => h + u, 0)) || 0, l = ((f = s.viewport.getBounds()) == null ? void 0 : f.reduce((h, u) => h + u, 0)) || 0;
750
+ if (r !== l && this.setState({
751
+ bounds: s.viewport.getBounds()
752
+ }), (i == null ? void 0 : i.data) !== (e == null ? void 0 : e.data) && this.setData(e.data, (e == null ? void 0 : e.fieldOptions) || {}), (i == null ? void 0 : i.windOptions) !== (e == null ? void 0 : e.windOptions) && this.init(), (i == null ? void 0 : i.visible) !== e.visible && this.setVisible(e.visible), (i == null ? void 0 : i.zIndex) !== e.zIndex && this.setzIndex(String(e.zIndex) || "unset"), !mt(a, e == null ? void 0 : e.windOptions)) {
753
+ const h = Object.assign({}, a, e.windOptions);
754
+ c.setOptions(h), this.setState({
755
+ windOptions: h
756
+ });
757
+ }
758
+ }
759
+ intersectsCoordinate([e, i]) {
760
+ const [s, o, c, a] = this.state.bounds;
761
+ return e >= s && e <= c && i >= o && i <= a;
762
+ }
763
+ init() {
764
+ var I, T, C, M, F, D, X;
765
+ const { viewport: e, deck: i } = this.context, s = i == null ? void 0 : i.width, o = i == null ? void 0 : i.height, c = this.getDevicePixelRatio(), a = Ct(s, o, c);
766
+ a.style.position = "absolute", a.style.top = "0px", a.style.left = "0px", a.style.right = "0px", a.style.bottom = "0px", a.style.width = `${s}px`, a.style.height = `${o}px`, a.style.display = (I = this.props) != null && I.visible ? "block" : "none", a.style.zIndex = ((C = (T = this.props) == null ? void 0 : T.zIndex) == null ? void 0 : C.toString()) || "unset";
767
+ const r = a.getContext("2d"), l = e.getBounds(), f = (M = this.props) == null ? void 0 : M.data, h = Object.assign(this._defaultOptions, ((F = this.props) == null ? void 0 : F.windOptions) || {}), u = ((D = this.props) == null ? void 0 : D.fieldOptions) || null, d = this.checkData(f, u), x = new v(r, h, d);
768
+ x.postrender = this.postrender.bind(this), x.project = this.cproject.bind(this), x.unproject = this.cunproject.bind(this), x.intersectsCoordinate = this.intersectsCoordinate.bind(this);
769
+ const O = (X = i == null ? void 0 : i.getCanvas()) == null ? void 0 : X.parentNode;
770
+ O && O.appendChild(a), this.setState({
771
+ bounds: l,
772
+ canvas: a,
773
+ wind: x,
774
+ windOpitons: h
775
+ });
776
+ }
777
+ setVisible(e) {
778
+ this.state.canvas.style.display = e ? "block" : "none";
779
+ }
780
+ setzIndex(e) {
781
+ this.state.canvas.style.zIndex = String(e) || "unset";
782
+ }
783
+ getDevicePixelRatio() {
784
+ return (window == null ? void 0 : window.devicePixelRatio) || 1;
785
+ }
786
+ postrender() {
787
+ var e, i;
788
+ (i = (e = this.props) == null ? void 0 : e.onPostRender) == null || i.call(e, this);
789
+ }
790
+ cproject([e, i]) {
791
+ const s = this.getDevicePixelRatio(), [o, c] = this.context.viewport.project([e, i, 0]);
792
+ return [o * s, c * s];
793
+ }
794
+ cunproject([e, i]) {
795
+ const s = this.context.viewport.unproject([e, i]);
796
+ return s ? [s[0], s[1]] : null;
797
+ }
798
+ checkData(e, i) {
799
+ return typeof e == "string" ? null : e && e.checkFields && e.checkFields() ? e : vt(e) ? Tt(e, i) : (console.error("Illegal data"), null);
800
+ }
801
+ setData(e, i) {
802
+ const s = this.checkData(e, i);
803
+ this.setState({
804
+ data: s
805
+ }), this.state.wind.updateData(s), this.state.wind.prerender();
806
+ }
807
+ destory() {
808
+ const { wind: e } = this.state;
809
+ e == null || e.stop(), e == null || e.clearCanvas(), Mt(this.state.canvas), this.setState({
810
+ canvas: null,
811
+ wind: null,
812
+ bounds: null,
813
+ windOptions: null,
814
+ fieldOptions: null
815
+ });
816
+ }
817
+ finalizeState() {
818
+ this.destory();
819
+ }
820
+ }
821
+ b(Ft, "layerName", "WindLayer");
822
+ export {
823
+ Ft as WindyLayer
824
+ };
@@ -0,0 +1 @@
1
+ (function(d,g){typeof exports=="object"&&typeof module<"u"?g(exports,require("@deck.gl/core")):typeof define=="function"&&define.amd?define(["exports","@deck.gl/core"],g):(d=typeof globalThis<"u"?globalThis:d||self,g(d["deckgl-expansion"]={},d.Deck["gl/core"]))})(this,function(d,g){"use strict";var Ft=Object.defineProperty;var Dt=(d,g,w)=>g in d?Ft(d,g,{enumerable:!0,configurable:!0,writable:!0,value:w}):d[g]=w;var T=(d,g,w)=>Dt(d,typeof g!="symbol"?g+"":g,w);function w(){}function C(n){return Object.getOwnPropertySymbols(n).filter(t=>Object.prototype.propertyIsEnumerable.call(n,t))}function M(n){return n==null?n===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(n)}const G="[object RegExp]",q="[object String]",K="[object Number]",Z="[object Boolean]",F="[object Arguments]",_="[object Symbol]",H="[object Date]",J="[object Map]",Q="[object Set]",tt="[object Array]",et="[object Function]",it="[object ArrayBuffer]",A="[object Object]",nt="[object Error]",st="[object DataView]",ot="[object Uint8Array]",rt="[object Uint8ClampedArray]",ct="[object Uint16Array]",at="[object Uint32Array]",lt="[object BigUint64Array]",ht="[object Int8Array]",ut="[object Int16Array]",ft="[object Int32Array]",dt="[object BigInt64Array]",gt="[object Float32Array]",xt="[object Float64Array]";function D(n){if(!n||typeof n!="object")return!1;const t=Object.getPrototypeOf(n);return t===null||t===Object.prototype||Object.getPrototypeOf(t)===null?Object.prototype.toString.call(n)==="[object Object]":!1}function yt(n,t){return n===t||Number.isNaN(n)&&Number.isNaN(t)}function pt(n,t,e){return b(n,t,void 0,void 0,void 0,void 0,e)}function b(n,t,e,i,s,o,c){const a=c(n,t,e,i,s,o);if(a!==void 0)return a;if(typeof n==typeof t)switch(typeof n){case"bigint":case"string":case"boolean":case"symbol":case"undefined":return n===t;case"number":return n===t||Object.is(n,t);case"function":return n===t;case"object":return j(n,t,o,c)}return j(n,t,o,c)}function j(n,t,e,i){if(Object.is(n,t))return!0;let s=M(n),o=M(t);if(s===F&&(s=A),o===F&&(o=A),s!==o)return!1;switch(s){case q:return n.toString()===t.toString();case K:{const r=n.valueOf(),l=t.valueOf();return yt(r,l)}case Z:case H:case _:return Object.is(n.valueOf(),t.valueOf());case G:return n.source===t.source&&n.flags===t.flags;case et:return n===t}e=e??new Map;const c=e.get(n),a=e.get(t);if(c!=null&&a!=null)return c===t;e.set(n,t),e.set(t,n);try{switch(s){case J:{if(n.size!==t.size)return!1;for(const[r,l]of n.entries())if(!t.has(r)||!b(l,t.get(r),r,n,t,e,i))return!1;return!0}case Q:{if(n.size!==t.size)return!1;const r=Array.from(n.values()),l=Array.from(t.values());for(let f=0;f<r.length;f++){const h=r[f],u=l.findIndex(x=>b(h,x,void 0,n,t,e,i));if(u===-1)return!1;l.splice(u,1)}return!0}case tt:case ot:case rt:case ct:case at:case lt:case ht:case ut:case ft:case dt:case gt:case xt:{if(typeof Buffer<"u"&&Buffer.isBuffer(n)!==Buffer.isBuffer(t)||n.length!==t.length)return!1;for(let r=0;r<n.length;r++)if(!b(n[r],t[r],r,n,t,e,i))return!1;return!0}case it:return n.byteLength!==t.byteLength?!1:j(new Uint8Array(n),new Uint8Array(t),e,i);case st:return n.byteLength!==t.byteLength||n.byteOffset!==t.byteOffset?!1:j(new Uint8Array(n),new Uint8Array(t),e,i);case nt:return n.name===t.name&&n.message===t.message;case A:{if(!(j(n.constructor,t.constructor,e,i)||D(n)&&D(t)))return!1;const l=[...Object.keys(n),...C(n)],f=[...Object.keys(t),...C(t)];if(l.length!==f.length)return!1;for(let h=0;h<l.length;h++){const u=l[h],x=n[u];if(!Object.hasOwn(t,u))return!1;const p=t[u];if(!b(x,p,u,n,t,e,i))return!1}return!0}default:return!1}}finally{e.delete(n),e.delete(t)}}function mt(n,t){return pt(n,t,w)}const wt=Object.prototype.hasOwnProperty,m=typeof Symbol<"u"?Symbol.toStringTag:void 0;function bt(n){if(n===null)return n===void 0?"[object Undefined]":"[object Null]";if(!(m&&m in Object(n)))return toString.call(n);const t=wt.call(n,m),e=n[m];let i=!1;try{n[m]=void 0,i=!0}catch{}const s=Object.prototype.toString.call(n);return i&&(t?n[m]=e:delete n[m]),s}function v(n){if(!jt(n))return!1;const t=bt(n);return t==="[object Function]"||t==="[object AsyncFunction]"||t==="[object GeneratorFunction]"||t==="[object Proxy]"}function jt(n){const t=typeof n;return n!==null&&(t==="object"||t==="function")}function vt(n){return n==null?!1:typeof n=="string"||n.constructor!==null&&n.constructor===String}function S(n){return Object.prototype.toString.call(n)==="[object Number]"&&!isNaN(n)}function At(n){return Array.isArray(n)}function St(n,t){console.warn(`${t}: ${n}`)}const X={};function Ot(n,t){X[t]||(St(t,n),X[t]=!0)}function It(n,t){return n-t*Math.floor(n/t)}function y(n){return n!=null&&!isNaN(n)}function Tt(n,t={}){let e,i;if(n.forEach(function(c){switch(c.header.parameterCategory+","+c.header.parameterNumber){case"1,2":case"2,2":e=c;break;case"1,3":case"2,3":i=c;break}}),!i||!e)return;const s=e.header;return new P({xmin:s.lo1,ymin:s.la1,xmax:s.lo2,ymax:s.la2,deltaX:s.dx,deltaY:s.dy,cols:s.nx,rows:s.ny,us:e.data,vs:i.data,...t})}function Ct(n,t,e,i){if(typeof document<"u"){const s=document.createElement("canvas");return s.width=n*e,s.height=t*e,s}else return new i(n*e,t*e)}function Mt(n){return n?(n.parentNode&&n.parentNode.removeChild(n),n):null}class N{constructor(t,e){this.u=t,this.v=e,this.m=this.magnitude()}magnitude(){return Math.sqrt(this.u**2+this.v**2)}directionTo(){let e=Math.atan2(this.u,this.v)*(180/Math.PI);return e<0&&(e+=360),e}directionFrom(){return(this.directionTo()+180)%360}}class P{constructor(t){this.grid=[],this.xmin=t.xmin,this.xmax=t.xmax,this.ymin=t.ymin,this.ymax=t.ymax,this.cols=t.cols,this.rows=t.rows,this.us=t.us,this.vs=t.vs,this.deltaX=t.deltaX,this.deltaY=t.deltaY,this.flipY=!!t.flipY,this.ymin=Math.min(t.ymax,t.ymin),this.ymax=Math.max(t.ymax,t.ymin),this.deltaY<0&&this.ymin<this.ymax||(t.flipY===void 0&&(this.flipY=!0),console.warn("[wind-core]: The data is flipY")),this.isFields=!0;const e=Math.ceil((this.xmax-this.xmin)/t.deltaX),i=Math.ceil((this.ymax-this.ymin)/t.deltaY);(e!==this.cols||i!==this.rows)&&console.warn("[wind-core]: The data grid not equal"),this.isContinuous=Math.floor(this.cols*t.deltaX)>=360,this.translateX="translateX"in t?t.translateX:this.xmax>180,"wrappedX"in t&&Ot("[wind-core]: ","`wrappedX` namespace will deprecated please use `translateX` instead!"),this.wrapX=!!t.wrapX,this.grid=this.buildGrid(),this.range=this.calculateRange()}buildGrid(){const t=[];let e=0;const{rows:i,cols:s,us:o,vs:c}=this;for(let a=0;a<i;a++){const r=[];for(let l=0;l<s;l++,e++){const f=o[e],h=c[e],u=this.isValid(f)&&this.isValid(h);r[l]=u?new N(f,h):null}this.isContinuous&&r.push(r[0]),t[a]=r}return t}release(){this.grid=[]}extent(){return[this.xmin,this.ymin,this.xmax,this.ymax]}bilinearInterpolateVector(t,e,i,s,o,c){const a=1-t,r=1-e,l=a*r,f=t*r,h=a*e,u=t*e,x=i.u*l+s.u*f+o.u*h+c.u*u,p=i.v*l+s.v*f+o.v*h+c.v*u;return new N(x,p)}calculateRange(){if(!this.grid||!this.grid[0])return;const t=this.grid.length,e=this.grid[0].length;let i,s;for(let o=0;o<t;o++)for(let c=0;c<e;c++){const a=this.grid[o][c];if(a!==null){const r=a.m||a.magnitude();i===void 0?i=r:s===void 0?(s=r,i=Math.min(i,s),s=Math.max(i,s)):(i=Math.min(r,i),s=Math.max(r,s))}}return[i,s]}isValid(t){return t!=null}getWrappedLongitudes(){let t=this.xmin,e=this.xmax;return this.translateX&&(this.isContinuous?(t=-180,e=180):(e=this.xmax-360,t=this.xmin-360)),[t,e]}contains(t,e){const[i,s]=this.getWrappedLongitudes();s>180&&t>=-180&&t<=s-360?t+=360:i<-180&&t<=180&&t>=i+360&&(t-=360);const o=t>=i&&t<=s;let c;return this.deltaY>=0?c=e>=this.ymin&&e<=this.ymax:c=e>=this.ymax&&e<=this.ymin,o&&c}getDecimalIndexes(t,e){const i=It(t-this.xmin,360)/this.deltaX;if(this.flipY){const s=(this.ymax-e)/this.deltaY;return[i,s]}else{const s=(this.ymin+e)/this.deltaY;return[i,s]}}valueAt(t,e){let i=!1;if((this.wrapX||this.contains(t,e))&&(i=!0),!i)return null;const s=this.getDecimalIndexes(t,e),o=Math.floor(s[0]),c=Math.floor(s[1]),a=this.clampColumnIndex(o),r=this.clampRowIndex(c);return this.valueAtIndexes(a,r)}interpolatedValueAt(t,e){let i=!1;if((this.wrapX||this.contains(t,e))&&(i=!0),!i)return null;const[s,o]=this.getDecimalIndexes(t,e);return this.interpolatePoint(s,o)}hasValueAt(t,e){return this.valueAt(t,e)!==null}interpolatePoint(t,e){const i=this.getFourSurroundingIndexes(t,e),[s,o,c,a]=i,r=this.getFourSurroundingValues(s,o,c,a);if(r){const[l,f,h,u]=r;return this.bilinearInterpolateVector(t-s,e-c,l,f,h,u)}return null}clampColumnIndex(t){let e=t;t<0&&(e=0);const i=this.cols-1;return t>i&&(e=i),e}clampRowIndex(t){let e=t;t<0&&(e=0);const i=this.rows-1;return t>i&&(e=i),e}getFourSurroundingIndexes(t,e){const i=Math.floor(t);let s=i+1;this.isContinuous&&s>=this.cols&&(s=0),s=this.clampColumnIndex(s);const o=this.clampRowIndex(Math.floor(e)),c=this.clampRowIndex(o+1);return[i,s,o,c]}getFourSurroundingValues(t,e,i,s){let o;if(o=this.grid[i]){const c=o[t],a=o[e];if(this.isValid(c)&&this.isValid(a)&&(o=this.grid[s])){const r=o[t],l=o[e];if(this.isValid(r)&&this.isValid(l))return[c,a,r,l]}}return null}valueAtIndexes(t,e){return this.grid[e][t]}lonLatAtIndexes(t,e){const i=this.longitudeAtX(t),s=this.latitudeAtY(e);return[i,s]}longitudeAtX(t){const e=this.deltaX/2;let i=this.xmin+e+t*this.deltaX;return this.translateX&&(i=i>180?i-360:i),i}latitudeAtY(t){const e=this.deltaY/2;return this.ymax-e-t*this.deltaY}randomize(t={},e,i,s){const o=Math.random()*(e||this.cols)|0,c=Math.random()*(i||this.rows)|0,a=s([o,c]);return a!==null?(t.x=a[0],t.y=a[1]):(t.x=this.longitudeAtX(o),t.y=this.latitudeAtY(c)),t}checkFields(){return this.isFields}}const z={globalAlpha:.9,lineWidth:1,colorScale:"#fff",velocityScale:1/25,maxAge:90,paths:800,frameRate:20,useCoordsDraw:!0};function V(n,t,e,i){return Math.max(0,Math.min(i.length-1,Math.round((n-t)/(e-t)*(i.length-1))))}const I=class I{constructor(t,e,i){if(this.particles=[],this.generated=!1,this.ctx=t,!this.ctx)throw new Error("ctx error");this.animate=this.animate.bind(this),this.setOptions(e),i&&this.updateData(i)}setOptions(t){this.options={...z,...t};const{width:e,height:i}=this.ctx.canvas;"particleAge"in t&&!("maxAge"in t)&&S(this.options.particleAge)&&(this.options.maxAge=this.options.particleAge),"particleMultiplier"in t&&!("paths"in t)&&S(this.options.particleMultiplier)&&(this.options.paths=Math.round(e*i*this.options.particleMultiplier)),this.prerender()}getOptions(){return this.options}updateData(t){this.field=t,this.generated&&(this.particles=this.prepareParticlePaths())}project(...t){throw new Error("project must be overriden")}unproject(...t){throw new Error("unproject must be overriden")}intersectsCoordinate(t){throw new Error("must be overriden")}clearCanvas(){this.stop(),this.ctx.clearRect(0,0,this.ctx.canvas.width,this.ctx.canvas.height),this.forceStop=!1}isStop(){return!this.starting}start(){this.starting=!0,this.forceStop=!1,this.then=Date.now(),this.animate()}stop(){cancelAnimationFrame(this.animationLoop),this.starting=!1,this.forceStop=!0}animate(){this.animationLoop&&cancelAnimationFrame(this.animationLoop),this.animationLoop=requestAnimationFrame(this.animate);const t=Date.now(),e=t-this.then;e>this.options.frameRate&&(this.then=t-e%this.options.frameRate,this.render())}prerender(){this.generated=!1,this.field&&(this.particles=this.prepareParticlePaths(),this.generated=!0,!this.starting&&!this.forceStop&&(this.starting=!0,this.then=Date.now(),this.animate()))}render(){this.moveParticles(),this.drawParticles(),this.postrender()}postrender(){}moveParticles(){const{width:t,height:e}=this.ctx.canvas,i=this.particles,s=this.options.maxAge,o=v(this.options.velocityScale)?this.options.velocityScale():this.options.velocityScale;let c=0;const a=i.length;for(;c<a;c++){const r=i[c];r.age>s&&(r.age=0,this.field.randomize(r,t,e,this.unproject));const l=r.x,f=r.y,h=this.field.interpolatedValueAt(l,f);if(h===null)r.age=s;else{const u=l+h.u*o,x=f+h.v*o;this.field.hasValueAt(u,x)?(r.xt=u,r.yt=x,r.m=h.m):(r.x=u,r.y=x,r.age=s)}r.age++}}fadeIn(){const t=this.ctx.globalCompositeOperation;this.ctx.globalCompositeOperation="destination-in",this.ctx.fillRect(0,0,this.ctx.canvas.width,this.ctx.canvas.height),this.ctx.globalCompositeOperation=t}drawParticles(){const t=this.particles;this.fadeIn(),this.ctx.globalAlpha=this.options.globalAlpha,this.ctx.fillStyle=`rgba(0, 0, 0, ${this.options.globalAlpha})`,this.ctx.lineWidth=S(this.options.lineWidth)?this.options.lineWidth:1,this.ctx.strokeStyle=vt(this.options.colorScale)?this.options.colorScale:"#fff";let e=0;const i=t.length;if(this.field&&i>0){let s,o;for(y(this.options.minVelocity)&&y(this.options.maxVelocity)?(s=this.options.minVelocity,o=this.options.maxVelocity):[s,o]=this.field.range;e<i;e++)this[this.options.useCoordsDraw?"drawCoordsParticle":"drawPixelParticle"](t[e],s,o)}}drawPixelParticle(t,e,i){const s=[t.x,t.y],o=[t.xt,t.yt];if(o&&s&&y(o[0])&&y(o[1])&&y(s[0])&&y(s[1])&&t.age<=this.options.maxAge){if(this.ctx.beginPath(),this.ctx.moveTo(s[0],s[1]),this.ctx.lineTo(o[0],o[1]),v(this.options.colorScale))this.ctx.strokeStyle=this.options.colorScale(t.m);else if(Array.isArray(this.options.colorScale)){const c=V(t.m,e,i,this.options.colorScale);this.ctx.strokeStyle=this.options.colorScale[c]}v(this.options.lineWidth)&&(this.ctx.lineWidth=this.options.lineWidth(t.m)),t.x=t.xt,t.y=t.yt,this.ctx.stroke()}}drawCoordsParticle(t,e,i){const s=[t.x,t.y],o=[t.xt,t.yt];if(o&&s&&y(o[0])&&y(o[1])&&y(s[0])&&y(s[1])&&this.intersectsCoordinate(o)&&t.age<=this.options.maxAge){const c=this.project(s),a=this.project(o);if(c&&a){if(this.ctx.beginPath(),this.ctx.moveTo(c[0],c[1]),this.ctx.lineTo(a[0],a[1]),t.x=t.xt,t.y=t.yt,v(this.options.colorScale))this.ctx.strokeStyle=this.options.colorScale(t.m);else if(Array.isArray(this.options.colorScale)){const r=V(t.m,e,i,this.options.colorScale);this.ctx.strokeStyle=this.options.colorScale[r]}v(this.options.lineWidth)&&(this.ctx.lineWidth=this.options.lineWidth(t.m)),this.ctx.stroke()}}}prepareParticlePaths(){const{width:t,height:e}=this.ctx.canvas,i=typeof this.options.paths=="function"?this.options.paths(this):this.options.paths,s=[];if(!this.field)return[];let o=0;for(;o<i;o++)s.push(this.field.randomize({age:this.randomize()},t,e,this.unproject));return s}randomize(){return Math.floor(Math.random()*this.options.maxAge)}};I.Field=P;let O=I;class Y extends g.Layer{constructor(e){super(e);T(this,"_defaultOptions",{...z});this.props.zIndex=this.props.zIndex||"unset"}initializeState(){this.init()}shouldUpdateState({changeFlags:e}){return e.somethingChanged}updateState({props:e,oldProps:i,context:s}){var f;const{bounds:o,wind:c,windOptions:a}=this.state,r=(o==null?void 0:o.reduce((h,u)=>h+u,0))||0,l=((f=s.viewport.getBounds())==null?void 0:f.reduce((h,u)=>h+u,0))||0;if(r!==l&&this.setState({bounds:s.viewport.getBounds()}),(i==null?void 0:i.data)!==(e==null?void 0:e.data)&&this.setData(e.data,(e==null?void 0:e.fieldOptions)||{}),(i==null?void 0:i.windOptions)!==(e==null?void 0:e.windOptions)&&this.init(),(i==null?void 0:i.visible)!==e.visible&&this.setVisible(e.visible),(i==null?void 0:i.zIndex)!==e.zIndex&&this.setzIndex(String(e.zIndex)||"unset"),!mt(a,e==null?void 0:e.windOptions)){const h=Object.assign({},a,e.windOptions);c.setOptions(h),this.setState({windOptions:h})}}intersectsCoordinate([e,i]){const[s,o,c,a]=this.state.bounds;return e>=s&&e<=c&&i>=o&&i<=a}init(){var R,B,W,U,E,k,$;const{viewport:e,deck:i}=this.context,s=i==null?void 0:i.width,o=i==null?void 0:i.height,c=this.getDevicePixelRatio(),a=Ct(s,o,c);a.style.position="absolute",a.style.top="0px",a.style.left="0px",a.style.right="0px",a.style.bottom="0px",a.style.width=`${s}px`,a.style.height=`${o}px`,a.style.display=(R=this.props)!=null&&R.visible?"block":"none",a.style.zIndex=((W=(B=this.props)==null?void 0:B.zIndex)==null?void 0:W.toString())||"unset";const r=a.getContext("2d"),l=e.getBounds(),f=(U=this.props)==null?void 0:U.data,h=Object.assign(this._defaultOptions,((E=this.props)==null?void 0:E.windOptions)||{}),u=((k=this.props)==null?void 0:k.fieldOptions)||null,x=this.checkData(f,u),p=new O(r,h,x);p.postrender=this.postrender.bind(this),p.project=this.cproject.bind(this),p.unproject=this.cunproject.bind(this),p.intersectsCoordinate=this.intersectsCoordinate.bind(this);const L=($=i==null?void 0:i.getCanvas())==null?void 0:$.parentNode;L&&L.appendChild(a),this.setState({bounds:l,canvas:a,wind:p,windOpitons:h})}setVisible(e){this.state.canvas.style.display=e?"block":"none"}setzIndex(e){this.state.canvas.style.zIndex=String(e)||"unset"}getDevicePixelRatio(){return(window==null?void 0:window.devicePixelRatio)||1}postrender(){var e,i;(i=(e=this.props)==null?void 0:e.onPostRender)==null||i.call(e,this)}cproject([e,i]){const s=this.getDevicePixelRatio(),[o,c]=this.context.viewport.project([e,i,0]);return[o*s,c*s]}cunproject([e,i]){const s=this.context.viewport.unproject([e,i]);return s?[s[0],s[1]]:null}checkData(e,i){return typeof e=="string"?null:e&&e.checkFields&&e.checkFields()?e:At(e)?Tt(e,i):(console.error("Illegal data"),null)}setData(e,i){const s=this.checkData(e,i);this.setState({data:s}),this.state.wind.updateData(s),this.state.wind.prerender()}destory(){const{wind:e}=this.state;e==null||e.stop(),e==null||e.clearCanvas(),Mt(this.state.canvas),this.setState({canvas:null,wind:null,bounds:null,windOptions:null,fieldOptions:null})}finalizeState(){this.destory()}}T(Y,"layerName","WindLayer"),d.WindyLayer=Y,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1 @@
1
+ export * from './layers/index';
@@ -0,0 +1,2 @@
1
+ export * from './src/windy-layer';
2
+ export { default as WindyLayer } from './src/windy-layer';
@@ -0,0 +1,36 @@
1
+ import { Layer, LayerProps, UpdateParameters } from '@deck.gl/core';
2
+ import { IField, IGFSItem, IOptions, WindCore } from 'wind-core';
3
+ export interface WindLayerProps extends LayerProps {
4
+ data: IGFSItem[] | string;
5
+ windOptions?: Partial<IOptions> | undefined;
6
+ zIndex?: string | number;
7
+ fieldOptions?: Partial<IField> | undefined;
8
+ onPostRender?: (ctx: Layer) => void;
9
+ }
10
+ export default class WindyLayer extends Layer<WindLayerProps> {
11
+ static layerName: string;
12
+ private _defaultOptions;
13
+ constructor(props: WindLayerProps);
14
+ state: {
15
+ canvas: HTMLCanvasElement;
16
+ wind: WindCore;
17
+ bounds: [number, number, number, number];
18
+ windOptions: Partial<IOptions> | undefined;
19
+ fieldOptions: Partial<IField> | undefined;
20
+ };
21
+ initializeState(): void;
22
+ shouldUpdateState({ changeFlags }: UpdateParameters<this>): boolean;
23
+ updateState({ props, oldProps, context }: UpdateParameters<this>): void;
24
+ intersectsCoordinate([lng, lat]: [number, number]): boolean;
25
+ init(): void;
26
+ setVisible(visible: boolean): void;
27
+ setzIndex(zIndex: WindLayerProps['zIndex']): void;
28
+ getDevicePixelRatio(): number;
29
+ postrender(): void;
30
+ cproject([lng, lat]: [number, number]): number[];
31
+ cunproject([x, y]: [number, number]): number[] | null;
32
+ checkData(data: any, options: Partial<IField>): any;
33
+ setData(data: any, options: Partial<IField>): void;
34
+ destory(): void;
35
+ finalizeState(): void;
36
+ }
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "deckgl-expansion",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "private": false,
6
+ "types": "dist/types/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/ThorSmallice/deckgl-expansion.git"
13
+ },
14
+ "publishConfig": {
15
+ "registry": "https://registry.npmjs.org/"
16
+ },
17
+ "exports": {
18
+ ".": {
19
+ "import": "./dist/lib/index.es.js",
20
+ "require": "./dist/lib/index.umd.js",
21
+ "types": "./dist/types/src/main.d.ts",
22
+ "default": "./dist/lib/index.umd.js"
23
+ },
24
+ "./*": "./*"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc && vite build",
28
+ "test": "echo \"Error: no test specified\" && exit 1",
29
+ "push": "npm publish"
30
+ },
31
+ "keywords": [
32
+ "deckgl",
33
+ "deckgl-windy"
34
+ ],
35
+ "author": "dbthor",
36
+ "license": "MIT",
37
+ "packageManager": "pnpm@10.27.0",
38
+ "devDependencies": {
39
+ "@deck.gl/core": "~9.2.0",
40
+ "@deck.gl/layers": "~9.2.0",
41
+ "@deck.gl/mapbox": "~9.2.0",
42
+ "@luma.gl/constants": "~9.2.6",
43
+ "@luma.gl/core": "~9.2.6",
44
+ "@luma.gl/engine": "~9.2.6",
45
+ "@types/node": "^25.2.1",
46
+ "typescript": "^5.9.3",
47
+ "vite": "^5.4.21",
48
+ "vite-plugin-dts": "^4.5.4"
49
+ },
50
+ "peerDependencies": {
51
+ "@deck.gl/core": "~9.2.0",
52
+ "@deck.gl/layers": "~9.2.0",
53
+ "@deck.gl/mapbox": "~9.2.0",
54
+ "@luma.gl/constants": "~9.2.6",
55
+ "@luma.gl/core": "~9.2.6",
56
+ "@luma.gl/engine": "~9.2.6"
57
+ },
58
+ "dependencies": {
59
+ "es-toolkit": "^1.44.0",
60
+ "wind-core": "^1.1.8"
61
+ }
62
+ }