cesium-ocean-current-zkxt123 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/dist/cesium-ocean-current-zkxt.es.js +358 -0
- package/dist/cesium-ocean-current-zkxt.umd.js +1 -0
- package/dist/cesium-ocean-current-zkxt123.es.js +358 -0
- package/dist/cesium-ocean-current-zkxt123.umd.js +1 -0
- package/dist/cesium-windy-layer.es.js +358 -0
- package/dist/cesium-windy-layer.umd.js +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import * as x from "cesium";
|
|
2
|
+
var yt = function(m) {
|
|
3
|
+
var d = m.minVelocity || 0, o = m.maxVelocity || 10, f = (m.velocityScale || 5e-3) * (Math.pow(window.devicePixelRatio, 1 / 3) || 1), u = m.particleAge || 90, y = m.lineWidth || 1, E = m.particleMultiplier || 1 / 300, T = Math.pow(window.devicePixelRatio, 1 / 3) || 1.6, _ = m.frameRate || 15, S = 1e3 / _, b = 0.97, B = [
|
|
4
|
+
"rgb(36,104, 180)",
|
|
5
|
+
"rgb(60,157, 194)",
|
|
6
|
+
"rgb(128,205,193 )",
|
|
7
|
+
"rgb(151,218,168 )",
|
|
8
|
+
"rgb(198,231,181)",
|
|
9
|
+
"rgb(238,247,217)",
|
|
10
|
+
"rgb(255,238,159)",
|
|
11
|
+
"rgb(252,217,125)",
|
|
12
|
+
"rgb(255,182,100)",
|
|
13
|
+
"rgb(252,150,75)",
|
|
14
|
+
"rgb(250,112,52)",
|
|
15
|
+
"rgb(245,64,32)",
|
|
16
|
+
"rgb(237,45,28)",
|
|
17
|
+
"rgb(220,24,32)",
|
|
18
|
+
"rgb(180,0,35)"
|
|
19
|
+
];
|
|
20
|
+
const D = m.colorScale || B;
|
|
21
|
+
var Z = [NaN, NaN, null], I, N, U = m.data, P, q, O, V, z, F, G, j = !1, tt = function(t) {
|
|
22
|
+
U = t;
|
|
23
|
+
}, et = function(t) {
|
|
24
|
+
t.hasOwnProperty("minVelocity") && (d = t.minVelocity), t.hasOwnProperty("maxVelocity") && (o = t.maxVelocity), t.hasOwnProperty("velocityScale") && (f = (t.velocityScale || 5e-3) * (Math.pow(window.devicePixelRatio, 1 / 3) || 1)), t.hasOwnProperty("particleAge") && (u = t.particleAge), t.hasOwnProperty("lineWidth") && (y = t.lineWidth), t.hasOwnProperty("particleMultiplier") && (E = t.particleMultiplier), t.hasOwnProperty("opacity") && (b = +t.opacity), t.hasOwnProperty("frameRate") && (_ = t.frameRate), S = 1e3 / _;
|
|
25
|
+
}, at = function(t, e, a, i, n, s) {
|
|
26
|
+
var r = 1 - t, l = 1 - e, c = r * l, g = t * l, h = r * e, w = t * e, M = a[0] * c + i[0] * g + n[0] * h + s[0] * w, v = a[1] * c + i[1] * g + n[1] * h + s[1] * w;
|
|
27
|
+
return [M, v, Math.sqrt(M * M + v * v)];
|
|
28
|
+
}, it = function(t, e) {
|
|
29
|
+
var a = t.data, i = e.data;
|
|
30
|
+
return {
|
|
31
|
+
header: t.header,
|
|
32
|
+
data: function(n) {
|
|
33
|
+
return [a[n], i[n]];
|
|
34
|
+
},
|
|
35
|
+
interpolate: at
|
|
36
|
+
};
|
|
37
|
+
}, rt = function(t) {
|
|
38
|
+
var e = null, a = null;
|
|
39
|
+
return t.forEach(function(i) {
|
|
40
|
+
switch (i.header.parameterCategory + "," + i.header.parameterNumber) {
|
|
41
|
+
case "1,2":
|
|
42
|
+
case "2,2":
|
|
43
|
+
e = i;
|
|
44
|
+
break;
|
|
45
|
+
case "1,3":
|
|
46
|
+
case "2,3":
|
|
47
|
+
a = i;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}), it(e, a);
|
|
51
|
+
}, nt = function(t, e) {
|
|
52
|
+
I = rt(t);
|
|
53
|
+
var a = I.header;
|
|
54
|
+
q = a.lo1, O = a.la1, V = a.dx, z = a.dy, F = a.nx, G = a.ny, a.la2 && a.la1 < a.la2 ? j = !0 : j = !1, P = new Date(a.refTime), P.setHours(P.getHours() + a.forecastTime), N = [];
|
|
55
|
+
for (var i = 0, n = Math.floor(F * V) >= 360, s = 0; s < G; s++) {
|
|
56
|
+
for (var r = [], l = 0; l < F; l++, i++)
|
|
57
|
+
r[l] = I.data(i);
|
|
58
|
+
n && r.push(r[0]), N[s] = r;
|
|
59
|
+
}
|
|
60
|
+
e({
|
|
61
|
+
date: P,
|
|
62
|
+
interpolate: X
|
|
63
|
+
});
|
|
64
|
+
}, X = function(t, e) {
|
|
65
|
+
if (!N)
|
|
66
|
+
return null;
|
|
67
|
+
var a = ot(t - q, 360) / V, i;
|
|
68
|
+
j ? i = (e - O) / z : i = (O - e) / z;
|
|
69
|
+
var n = Math.floor(a), s = n + 1, r = Math.floor(i), l = r + 1, c;
|
|
70
|
+
if (c = N[r]) {
|
|
71
|
+
var g = c[n], h = c[s];
|
|
72
|
+
if (R(g) && R(h) && (c = N[l])) {
|
|
73
|
+
var w = c[n], M = c[s];
|
|
74
|
+
if (R(w) && R(M))
|
|
75
|
+
return I.interpolate(a - n, i - r, g, h, w, M);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}, R = function(t) {
|
|
80
|
+
return t != null;
|
|
81
|
+
}, ot = function(t, e) {
|
|
82
|
+
return t - e * Math.floor(t / e);
|
|
83
|
+
}, st = function() {
|
|
84
|
+
return /android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent);
|
|
85
|
+
}, lt = function(t, e, a, i, n, s, r) {
|
|
86
|
+
var l = r[0] * s, c = r[1] * s, g = ht(t, e, a, i, n);
|
|
87
|
+
return r[0] = g[0] * l + g[2] * c, r[1] = g[1] * l + g[3] * c, r;
|
|
88
|
+
}, ht = function(t, e, a, i, n) {
|
|
89
|
+
var s = 2 * Math.PI, r = 5, l = e < 0 ? r : -r, c = a < 0 ? r : -r, g = J(a, e + l), h = J(a + c, e), w = Math.cos(a / 360 * s);
|
|
90
|
+
return [
|
|
91
|
+
(g[0] - i) / l / w,
|
|
92
|
+
(g[1] - n) / l / w,
|
|
93
|
+
(h[0] - i) / c,
|
|
94
|
+
(h[1] - n) / c
|
|
95
|
+
];
|
|
96
|
+
}, $ = function(t, e, a) {
|
|
97
|
+
function i(n, s) {
|
|
98
|
+
var r = t[Math.round(n)];
|
|
99
|
+
return r && r[Math.round(s)] || Z;
|
|
100
|
+
}
|
|
101
|
+
i.release = function() {
|
|
102
|
+
t = [];
|
|
103
|
+
}, i.randomize = function(n) {
|
|
104
|
+
var s, r, l = 0;
|
|
105
|
+
do
|
|
106
|
+
s = Math.round(Math.floor(Math.random() * e.width) + e.x), r = Math.round(Math.floor(Math.random() * e.height) + e.y);
|
|
107
|
+
while (i(s, r)[2] === null && l++ < 30);
|
|
108
|
+
return n.x = s, n.y = r, n;
|
|
109
|
+
}, a(e, i);
|
|
110
|
+
}, vt = function(t, e, a) {
|
|
111
|
+
var i = t[0], n = t[1], s = Math.round(i[0]), r = Math.max(Math.floor(i[1], 0), 0);
|
|
112
|
+
Math.min(Math.ceil(n[0], e), e - 1);
|
|
113
|
+
var l = Math.min(Math.ceil(n[1], a), a - 1);
|
|
114
|
+
return { x: s, y: r, xMax: e, yMax: l, width: e, height: a };
|
|
115
|
+
}, A = function(t) {
|
|
116
|
+
return t / 180 * Math.PI;
|
|
117
|
+
}, ct = function(t, e, a) {
|
|
118
|
+
var i = m.map.containerPointToLatLng({ x: t, y: e });
|
|
119
|
+
return [i.lng, i.lat];
|
|
120
|
+
}, J = function(t, e, a) {
|
|
121
|
+
var i = m.map.latLngToContainerPoint({ lat: t, lng: e });
|
|
122
|
+
return [i.x, i.y];
|
|
123
|
+
}, ft = function(t, e, a, i) {
|
|
124
|
+
var n = {}, s = (a.south - a.north) * (a.west - a.east), r = f * Math.pow(s, 0.4), l = [], c = e.x;
|
|
125
|
+
function g(h) {
|
|
126
|
+
for (var w = [], M = e.y; M <= e.yMax; M += 2) {
|
|
127
|
+
var v = ct(h, M);
|
|
128
|
+
if (v) {
|
|
129
|
+
var C = v[0], L = v[1];
|
|
130
|
+
if (isFinite(C)) {
|
|
131
|
+
var p = t.interpolate(C, L);
|
|
132
|
+
p && (p = lt(n, C, L, h, M, r, p), w[M + 1] = w[M] = p);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
l[h + 1] = l[h] = w;
|
|
137
|
+
}
|
|
138
|
+
(function h() {
|
|
139
|
+
for (var w = Date.now(); c < e.width; )
|
|
140
|
+
if (g(c), c += 2, Date.now() - w > 1e3) {
|
|
141
|
+
setTimeout(h, 25);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
$(l, e, i);
|
|
145
|
+
})();
|
|
146
|
+
}, k, ut = function(t, e) {
|
|
147
|
+
function a(v, C) {
|
|
148
|
+
return D.indexFor = function(L) {
|
|
149
|
+
return Math.max(0, Math.min(D.length - 1, Math.round((L - v) / (C - v) * (D.length - 1))));
|
|
150
|
+
}, D;
|
|
151
|
+
}
|
|
152
|
+
var i = a(d, o), n = i.map(function() {
|
|
153
|
+
return [];
|
|
154
|
+
}), s = Math.round(t.width * t.height * E);
|
|
155
|
+
st() && (s *= T);
|
|
156
|
+
for (var r = `rgba(0, 0, 0, ${b})`, l = [], c = 0; c < s; c++)
|
|
157
|
+
l.push(e.randomize({ age: Math.floor(Math.random() * u) + 0 }));
|
|
158
|
+
function g() {
|
|
159
|
+
n.forEach(function(v) {
|
|
160
|
+
v.length = 0;
|
|
161
|
+
}), l.forEach(function(v) {
|
|
162
|
+
v.age > u && (e.randomize(v).age = 0);
|
|
163
|
+
var C = v.x, L = v.y, p = e(C, L), Q = p[2];
|
|
164
|
+
if (Q === null)
|
|
165
|
+
v.age = u;
|
|
166
|
+
else {
|
|
167
|
+
var H = C + p[0], Y = L + p[1];
|
|
168
|
+
e(H, Y)[2] !== null ? (v.xt = H, v.yt = Y, n[i.indexFor(Q)].push(v)) : (v.x = H, v.y = Y);
|
|
169
|
+
}
|
|
170
|
+
v.age += 1;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
var h = m.canvas.getContext("2d");
|
|
174
|
+
h.lineWidth = y, h.fillStyle = r, h.globalAlpha = 0.6;
|
|
175
|
+
function w() {
|
|
176
|
+
var v = "lighter";
|
|
177
|
+
h.globalCompositeOperation = "destination-in", h.fillRect(t.x, t.y, t.width, t.height), h.globalCompositeOperation = v, h.globalAlpha = b === 0 ? 0 : b * 0.9, n.forEach(function(C, L) {
|
|
178
|
+
C.length > 0 && (h.beginPath(), h.strokeStyle = i[L], C.forEach(function(p) {
|
|
179
|
+
h.moveTo(p.x, p.y), h.lineTo(p.xt, p.yt), p.x = p.xt, p.y = p.yt;
|
|
180
|
+
}), h.stroke());
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
var M = Date.now();
|
|
184
|
+
(function v() {
|
|
185
|
+
k = requestAnimationFrame(v);
|
|
186
|
+
var C = Date.now(), L = C - M;
|
|
187
|
+
L > S && (M = C - L % S, g(), w());
|
|
188
|
+
})();
|
|
189
|
+
}, dt = function(t, e, a, i) {
|
|
190
|
+
var n = {
|
|
191
|
+
south: A(i[0][1]),
|
|
192
|
+
north: A(i[1][1]),
|
|
193
|
+
east: A(i[1][0]),
|
|
194
|
+
west: A(i[0][0]),
|
|
195
|
+
width: e,
|
|
196
|
+
height: a
|
|
197
|
+
};
|
|
198
|
+
K(), nt(U, function(s) {
|
|
199
|
+
ft(s, vt(t, e, a), n, function(r, l) {
|
|
200
|
+
W.field = l, ut(r, l);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}, K = function() {
|
|
204
|
+
if (W.field && W.field.release(), k && cancelAnimationFrame(k), m.canvas) {
|
|
205
|
+
var t = m.canvas.getContext("2d");
|
|
206
|
+
t.clearRect(0, 0, m.canvas.width, m.canvas.height);
|
|
207
|
+
}
|
|
208
|
+
}, W = {
|
|
209
|
+
params: m,
|
|
210
|
+
start: dt,
|
|
211
|
+
stop: K,
|
|
212
|
+
createField: $,
|
|
213
|
+
interpolatePoint: X,
|
|
214
|
+
setData: tt,
|
|
215
|
+
setOptions: et
|
|
216
|
+
};
|
|
217
|
+
return W;
|
|
218
|
+
};
|
|
219
|
+
class mt {
|
|
220
|
+
constructor(d, o = {}) {
|
|
221
|
+
this.viewer = d, this.options = {
|
|
222
|
+
url: "",
|
|
223
|
+
// JSON 数据地址
|
|
224
|
+
lineWidth: 2,
|
|
225
|
+
velocityScale: 0.05,
|
|
226
|
+
maxVelocity: 0.7,
|
|
227
|
+
minVelocity: 0,
|
|
228
|
+
opacity: 0.97,
|
|
229
|
+
particleAge: 90,
|
|
230
|
+
frameRate: 15,
|
|
231
|
+
colorScale: null,
|
|
232
|
+
safetyHeight: 48e5,
|
|
233
|
+
// 默认安全高度
|
|
234
|
+
...o
|
|
235
|
+
}, this.windy = null, this.canvas = null, this.globalData = null, this.activeExtent = [0, -90, 360, 90], this.timer = null, this._resizeListener = this._onResize.bind(this), this._cameraMoveEndListener = this._onCameraMoveEnd.bind(this), this._cameraMoveStartListener = this._onCameraMoveStart.bind(this), this._initCanvas(), this._setupEventListeners(), this.options.url && this.loadData(this.options.url);
|
|
236
|
+
}
|
|
237
|
+
_initCanvas() {
|
|
238
|
+
this.canvas = document.createElement("canvas"), this.canvas.style.cssText = "position:absolute; top:0; left:0; pointer-events:none; z-index:100; display:none;", this.canvas.className = "cesium-windy-canvas", this.viewer.cesiumWidget.container.appendChild(this.canvas), this._resizeCanvas();
|
|
239
|
+
}
|
|
240
|
+
_resizeCanvas() {
|
|
241
|
+
const d = this.viewer.canvas.clientWidth, o = this.viewer.canvas.clientHeight;
|
|
242
|
+
this.canvas.width = d, this.canvas.height = o;
|
|
243
|
+
}
|
|
244
|
+
async loadData(d) {
|
|
245
|
+
try {
|
|
246
|
+
const f = await (await fetch(d)).json();
|
|
247
|
+
this.globalData = Object.freeze(f), this.updateWindyState();
|
|
248
|
+
} catch (o) {
|
|
249
|
+
console.error("[CesiumWindy] Data loading failed:", o);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
_setupEventListeners() {
|
|
253
|
+
this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartListener), this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndListener), window.addEventListener("resize", this._resizeListener);
|
|
254
|
+
}
|
|
255
|
+
_onCameraMoveStart() {
|
|
256
|
+
this.canvas && (this.canvas.style.display = "none"), this.windy && this.windy.stop();
|
|
257
|
+
}
|
|
258
|
+
_onCameraMoveEnd() {
|
|
259
|
+
this.timer && clearTimeout(this.timer), this.timer = setTimeout(() => {
|
|
260
|
+
this.updateWindyState();
|
|
261
|
+
}, 200);
|
|
262
|
+
}
|
|
263
|
+
_onResize() {
|
|
264
|
+
this._resizeCanvas(), this.updateWindyState();
|
|
265
|
+
}
|
|
266
|
+
// === 核心逻辑:从 Vue 移植过来的视图计算 ===
|
|
267
|
+
updateWindyState() {
|
|
268
|
+
if (!this.globalData || !this.viewer)
|
|
269
|
+
return;
|
|
270
|
+
const d = this.viewer.camera.positionCartographic.height;
|
|
271
|
+
let o = [0, -90, 360, 90], f = 360;
|
|
272
|
+
if (d > this.options.safetyHeight)
|
|
273
|
+
o = [0, -90, 360, 90], f = 360;
|
|
274
|
+
else {
|
|
275
|
+
const y = this.viewer.camera.computeViewRectangle(this.viewer.scene.globe.ellipsoid);
|
|
276
|
+
if (y) {
|
|
277
|
+
let E = x.Math.toDegrees(y.west), T = x.Math.toDegrees(y.south), _ = x.Math.toDegrees(y.east), S = x.Math.toDegrees(y.north);
|
|
278
|
+
const b = (_ - E + 360) % 360;
|
|
279
|
+
E > _ || b < 0.5 ? (o = [0, -90, 360, 90], f = 360) : (o = [
|
|
280
|
+
E - 2,
|
|
281
|
+
Math.max(-90, T - 2),
|
|
282
|
+
_ + 2,
|
|
283
|
+
Math.min(90, S + 2)
|
|
284
|
+
], o[0] < 0 && (o[0] += 360), o[2] < 0 && (o[2] += 360), f = b);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
this.activeExtent = o;
|
|
288
|
+
let u;
|
|
289
|
+
f > 120 ? u = 1 / 600 : f > 60 ? u = 1 / 500 : f > 20 ? u = 1 / 300 : u = 1 / 200, d > this.options.safetyHeight && u > 1 / 300 && (u = 1 / 300), this._renderWindy(u, o);
|
|
290
|
+
}
|
|
291
|
+
_renderWindy(d, o) {
|
|
292
|
+
const f = this.canvas.width, u = this.canvas.height;
|
|
293
|
+
this.windy || (this.windy = new yt({
|
|
294
|
+
canvas: this.canvas,
|
|
295
|
+
data: this.globalData,
|
|
296
|
+
map: this._getMapAdapter(),
|
|
297
|
+
particleMultiplier: d,
|
|
298
|
+
lineWidth: this.options.lineWidth,
|
|
299
|
+
velocityScale: this.options.velocityScale,
|
|
300
|
+
maxVelocity: this.options.maxVelocity,
|
|
301
|
+
minVelocity: this.options.minVelocity,
|
|
302
|
+
opacity: this.options.opacity,
|
|
303
|
+
frameRate: this.options.frameRate,
|
|
304
|
+
colorScale: this.options.colorScale
|
|
305
|
+
})), this.windy.setOptions({
|
|
306
|
+
particleMultiplier: d
|
|
307
|
+
}), this.canvas.style.display = "block", this.windy.start(
|
|
308
|
+
[[0, 0], [f, u]],
|
|
309
|
+
f,
|
|
310
|
+
u,
|
|
311
|
+
[[o[0], o[1]], [o[2], o[3]]]
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
// === 坐标适配器 ===
|
|
315
|
+
_getMapAdapter() {
|
|
316
|
+
const d = this;
|
|
317
|
+
return {
|
|
318
|
+
containerPointToLatLng: (o) => {
|
|
319
|
+
const f = d.viewer.camera.pickEllipsoid(
|
|
320
|
+
new x.Cartesian2(o.x, o.y),
|
|
321
|
+
d.viewer.scene.globe.ellipsoid
|
|
322
|
+
);
|
|
323
|
+
if (!f)
|
|
324
|
+
return { lng: NaN, lat: NaN };
|
|
325
|
+
const u = x.Cartographic.fromCartesian(f);
|
|
326
|
+
let y = x.Math.toDegrees(u.longitude);
|
|
327
|
+
const E = x.Math.toDegrees(u.latitude);
|
|
328
|
+
y < 0 && (y += 360);
|
|
329
|
+
const [T, _, S, b] = d.activeExtent;
|
|
330
|
+
if (T < S) {
|
|
331
|
+
if (y < T || y > S || E < _ || E > b)
|
|
332
|
+
return { lng: NaN, lat: NaN };
|
|
333
|
+
} else if (E < _ || E > b)
|
|
334
|
+
return { lng: NaN, lat: NaN };
|
|
335
|
+
return { lng: y, lat: E };
|
|
336
|
+
},
|
|
337
|
+
latLngToContainerPoint: (o) => {
|
|
338
|
+
let f = o.lng;
|
|
339
|
+
f > 180 && (f -= 360);
|
|
340
|
+
const u = x.Cartesian3.fromDegrees(f, o.lat);
|
|
341
|
+
try {
|
|
342
|
+
const y = d.viewer.scene.cartesianToCanvasCoordinates(u);
|
|
343
|
+
if (y)
|
|
344
|
+
return { x: y.x, y: y.y };
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
return { x: -1e3, y: -1e3 };
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
// 销毁方法
|
|
352
|
+
destroy() {
|
|
353
|
+
this.windy && this.windy.stop(), this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartListener), this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEndListener), window.removeEventListener("resize", this._resizeListener), this.canvas && this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
export {
|
|
357
|
+
mt as default
|
|
358
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(S,D){typeof exports=="object"&&typeof module<"u"?module.exports=D(require("cesium")):typeof define=="function"&&define.amd?define(["cesium"],D):(S=typeof globalThis<"u"?globalThis:S||self,S.CesiumOceanCurrentZKXT=D(S.Cesium))})(this,function(S){"use strict";function D(v){const u=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(v){for(const n in v)if(n!=="default"){const f=Object.getOwnPropertyDescriptor(v,n);Object.defineProperty(u,n,f.get?f:{enumerable:!0,get:()=>v[n]})}}return u.default=v,Object.freeze(u)}const x=D(S);var te=function(v){var u=v.minVelocity||0,n=v.maxVelocity||10,f=(v.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),m=v.particleAge||90,y=v.lineWidth||1,b=v.particleMultiplier||1/300,N=Math.pow(window.devicePixelRatio,1/3)||1.6,_=v.frameRate||15,T=1e3/_,L=.97,U=["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"];const O=v.colorScale||U;var ie=[NaN,NaN,null],I,P,X=v.data,R,G,z,j,F,k,K,H=!1,re=function(e){X=e},ne=function(e){e.hasOwnProperty("minVelocity")&&(u=e.minVelocity),e.hasOwnProperty("maxVelocity")&&(n=e.maxVelocity),e.hasOwnProperty("velocityScale")&&(f=(e.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),e.hasOwnProperty("particleAge")&&(m=e.particleAge),e.hasOwnProperty("lineWidth")&&(y=e.lineWidth),e.hasOwnProperty("particleMultiplier")&&(b=e.particleMultiplier),e.hasOwnProperty("opacity")&&(L=+e.opacity),e.hasOwnProperty("frameRate")&&(_=e.frameRate),T=1e3/_},oe=function(e,t,a,i,o,s){var r=1-e,l=1-t,d=r*l,g=e*l,c=r*t,w=e*t,M=a[0]*d+i[0]*g+o[0]*c+s[0]*w,h=a[1]*d+i[1]*g+o[1]*c+s[1]*w;return[M,h,Math.sqrt(M*M+h*h)]},se=function(e,t){var a=e.data,i=t.data;return{header:e.header,data:function(o){return[a[o],i[o]]},interpolate:oe}},le=function(e){var t=null,a=null;return e.forEach(function(i){switch(i.header.parameterCategory+","+i.header.parameterNumber){case"1,2":case"2,2":t=i;break;case"1,3":case"2,3":a=i;break}}),se(t,a)},ce=function(e,t){I=le(e);var a=I.header;G=a.lo1,z=a.la1,j=a.dx,F=a.dy,k=a.nx,K=a.ny,a.la2&&a.la1<a.la2?H=!0:H=!1,R=new Date(a.refTime),R.setHours(R.getHours()+a.forecastTime),P=[];for(var i=0,o=Math.floor(k*j)>=360,s=0;s<K;s++){for(var r=[],l=0;l<k;l++,i++)r[l]=I.data(i);o&&r.push(r[0]),P[s]=r}t({date:R,interpolate:Z})},Z=function(e,t){if(!P)return null;var a=he(e-G,360)/j,i;H?i=(t-z)/F:i=(z-t)/F;var o=Math.floor(a),s=o+1,r=Math.floor(i),l=r+1,d;if(d=P[r]){var g=d[o],c=d[s];if(A(g)&&A(c)&&(d=P[l])){var w=d[o],M=d[s];if(A(w)&&A(M))return I.interpolate(a-o,i-r,g,c,w,M)}}return null},A=function(e){return e!=null},he=function(e,t){return e-t*Math.floor(e/t)},ve=function(){return/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)},fe=function(e,t,a,i,o,s,r){var l=r[0]*s,d=r[1]*s,g=ue(e,t,a,i,o);return r[0]=g[0]*l+g[2]*d,r[1]=g[1]*l+g[3]*d,r},ue=function(e,t,a,i,o){var s=2*Math.PI,r=5,l=t<0?r:-r,d=a<0?r:-r,g=J(a,t+l),c=J(a+d,t),w=Math.cos(a/360*s);return[(g[0]-i)/l/w,(g[1]-o)/l/w,(c[0]-i)/d,(c[1]-o)/d]},$=function(e,t,a){function i(o,s){var r=e[Math.round(o)];return r&&r[Math.round(s)]||ie}i.release=function(){e=[]},i.randomize=function(o){var s,r,l=0;do s=Math.round(Math.floor(Math.random()*t.width)+t.x),r=Math.round(Math.floor(Math.random()*t.height)+t.y);while(i(s,r)[2]===null&&l++<30);return o.x=s,o.y=r,o},a(t,i)},de=function(e,t,a){var i=e[0],o=e[1],s=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],t),t-1);var l=Math.min(Math.ceil(o[1],a),a-1);return{x:s,y:r,xMax:t,yMax:l,width:t,height:a}},W=function(e){return e/180*Math.PI},me=function(e,t,a){var i=v.map.containerPointToLatLng({x:e,y:t});return[i.lng,i.lat]},J=function(e,t,a){var i=v.map.latLngToContainerPoint({lat:e,lng:t});return[i.x,i.y]},ye=function(e,t,a,i){var o={},s=(a.south-a.north)*(a.west-a.east),r=f*Math.pow(s,.4),l=[],d=t.x;function g(c){for(var w=[],M=t.y;M<=t.yMax;M+=2){var h=me(c,M);if(h){var C=h[0],E=h[1];if(isFinite(C)){var p=e.interpolate(C,E);p&&(p=fe(o,C,E,c,M,r,p),w[M+1]=w[M]=p)}}}l[c+1]=l[c]=w}(function c(){for(var w=Date.now();d<t.width;)if(g(d),d+=2,Date.now()-w>1e3){setTimeout(c,25);return}$(l,t,i)})()},Y,ge=function(e,t){function a(h,C){return O.indexFor=function(E){return Math.max(0,Math.min(O.length-1,Math.round((E-h)/(C-h)*(O.length-1))))},O}var i=a(u,n),o=i.map(function(){return[]}),s=Math.round(e.width*e.height*b);ve()&&(s*=N);for(var r=`rgba(0, 0, 0, ${L})`,l=[],d=0;d<s;d++)l.push(t.randomize({age:Math.floor(Math.random()*m)+0}));function g(){o.forEach(function(h){h.length=0}),l.forEach(function(h){h.age>m&&(t.randomize(h).age=0);var C=h.x,E=h.y,p=t(C,E),ee=p[2];if(ee===null)h.age=m;else{var B=C+p[0],q=E+p[1];t(B,q)[2]!==null?(h.xt=B,h.yt=q,o[i.indexFor(ee)].push(h)):(h.x=B,h.y=q)}h.age+=1})}var c=v.canvas.getContext("2d");c.lineWidth=y,c.fillStyle=r,c.globalAlpha=.6;function w(){var h="lighter";c.globalCompositeOperation="destination-in",c.fillRect(e.x,e.y,e.width,e.height),c.globalCompositeOperation=h,c.globalAlpha=L===0?0:L*.9,o.forEach(function(C,E){C.length>0&&(c.beginPath(),c.strokeStyle=i[E],C.forEach(function(p){c.moveTo(p.x,p.y),c.lineTo(p.xt,p.yt),p.x=p.xt,p.y=p.yt}),c.stroke())})}var M=Date.now();(function h(){Y=requestAnimationFrame(h);var C=Date.now(),E=C-M;E>T&&(M=C-E%T,g(),w())})()},pe=function(e,t,a,i){var o={south:W(i[0][1]),north:W(i[1][1]),east:W(i[1][0]),west:W(i[0][0]),width:t,height:a};Q(),ce(X,function(s){ye(s,de(e,t,a),o,function(r,l){V.field=l,ge(r,l)})})},Q=function(){if(V.field&&V.field.release(),Y&&cancelAnimationFrame(Y),v.canvas){var e=v.canvas.getContext("2d");e.clearRect(0,0,v.canvas.width,v.canvas.height)}},V={params:v,start:pe,stop:Q,createField:$,interpolatePoint:Z,setData:re,setOptions:ne};return V};class ae{constructor(u,n={}){this.viewer=u,this.options={url:"",lineWidth:2,velocityScale:.05,maxVelocity:.7,minVelocity:0,opacity:.97,particleAge:90,frameRate:15,colorScale:null,safetyHeight:48e5,...n},this.windy=null,this.canvas=null,this.globalData=null,this.activeExtent=[0,-90,360,90],this.timer=null,this._resizeListener=this._onResize.bind(this),this._cameraMoveEndListener=this._onCameraMoveEnd.bind(this),this._cameraMoveStartListener=this._onCameraMoveStart.bind(this),this._initCanvas(),this._setupEventListeners(),this.options.url&&this.loadData(this.options.url)}_initCanvas(){this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute; top:0; left:0; pointer-events:none; z-index:100; display:none;",this.canvas.className="cesium-windy-canvas",this.viewer.cesiumWidget.container.appendChild(this.canvas),this._resizeCanvas()}_resizeCanvas(){const u=this.viewer.canvas.clientWidth,n=this.viewer.canvas.clientHeight;this.canvas.width=u,this.canvas.height=n}async loadData(u){try{const f=await(await fetch(u)).json();this.globalData=Object.freeze(f),this.updateWindyState()}catch(n){console.error("[CesiumWindy] Data loading failed:",n)}}_setupEventListeners(){this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartListener),this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndListener),window.addEventListener("resize",this._resizeListener)}_onCameraMoveStart(){this.canvas&&(this.canvas.style.display="none"),this.windy&&this.windy.stop()}_onCameraMoveEnd(){this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.updateWindyState()},200)}_onResize(){this._resizeCanvas(),this.updateWindyState()}updateWindyState(){if(!this.globalData||!this.viewer)return;const u=this.viewer.camera.positionCartographic.height;let n=[0,-90,360,90],f=360;if(u>this.options.safetyHeight)n=[0,-90,360,90],f=360;else{const y=this.viewer.camera.computeViewRectangle(this.viewer.scene.globe.ellipsoid);if(y){let b=x.Math.toDegrees(y.west),N=x.Math.toDegrees(y.south),_=x.Math.toDegrees(y.east),T=x.Math.toDegrees(y.north);const L=(_-b+360)%360;b>_||L<.5?(n=[0,-90,360,90],f=360):(n=[b-2,Math.max(-90,N-2),_+2,Math.min(90,T+2)],n[0]<0&&(n[0]+=360),n[2]<0&&(n[2]+=360),f=L)}}this.activeExtent=n;let m;f>120?m=1/600:f>60?m=1/500:f>20?m=1/300:m=1/200,u>this.options.safetyHeight&&m>1/300&&(m=1/300),this._renderWindy(m,n)}_renderWindy(u,n){const f=this.canvas.width,m=this.canvas.height;this.windy||(this.windy=new te({canvas:this.canvas,data:this.globalData,map:this._getMapAdapter(),particleMultiplier:u,lineWidth:this.options.lineWidth,velocityScale:this.options.velocityScale,maxVelocity:this.options.maxVelocity,minVelocity:this.options.minVelocity,opacity:this.options.opacity,frameRate:this.options.frameRate,colorScale:this.options.colorScale})),this.windy.setOptions({particleMultiplier:u}),this.canvas.style.display="block",this.windy.start([[0,0],[f,m]],f,m,[[n[0],n[1]],[n[2],n[3]]])}_getMapAdapter(){const u=this;return{containerPointToLatLng:n=>{const f=u.viewer.camera.pickEllipsoid(new x.Cartesian2(n.x,n.y),u.viewer.scene.globe.ellipsoid);if(!f)return{lng:NaN,lat:NaN};const m=x.Cartographic.fromCartesian(f);let y=x.Math.toDegrees(m.longitude);const b=x.Math.toDegrees(m.latitude);y<0&&(y+=360);const[N,_,T,L]=u.activeExtent;if(N<T){if(y<N||y>T||b<_||b>L)return{lng:NaN,lat:NaN}}else if(b<_||b>L)return{lng:NaN,lat:NaN};return{lng:y,lat:b}},latLngToContainerPoint:n=>{let f=n.lng;f>180&&(f-=360);const m=x.Cartesian3.fromDegrees(f,n.lat);try{const y=u.viewer.scene.cartesianToCanvasCoordinates(m);if(y)return{x:y.x,y:y.y}}catch{}return{x:-1e3,y:-1e3}}}}destroy(){this.windy&&this.windy.stop(),this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartListener),this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEndListener),window.removeEventListener("resize",this._resizeListener),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}return ae});
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import * as x from "cesium";
|
|
2
|
+
var yt = function(m) {
|
|
3
|
+
var d = m.minVelocity || 0, o = m.maxVelocity || 10, f = (m.velocityScale || 5e-3) * (Math.pow(window.devicePixelRatio, 1 / 3) || 1), u = m.particleAge || 90, y = m.lineWidth || 1, E = m.particleMultiplier || 1 / 300, T = Math.pow(window.devicePixelRatio, 1 / 3) || 1.6, _ = m.frameRate || 15, S = 1e3 / _, b = 0.97, B = [
|
|
4
|
+
"rgb(36,104, 180)",
|
|
5
|
+
"rgb(60,157, 194)",
|
|
6
|
+
"rgb(128,205,193 )",
|
|
7
|
+
"rgb(151,218,168 )",
|
|
8
|
+
"rgb(198,231,181)",
|
|
9
|
+
"rgb(238,247,217)",
|
|
10
|
+
"rgb(255,238,159)",
|
|
11
|
+
"rgb(252,217,125)",
|
|
12
|
+
"rgb(255,182,100)",
|
|
13
|
+
"rgb(252,150,75)",
|
|
14
|
+
"rgb(250,112,52)",
|
|
15
|
+
"rgb(245,64,32)",
|
|
16
|
+
"rgb(237,45,28)",
|
|
17
|
+
"rgb(220,24,32)",
|
|
18
|
+
"rgb(180,0,35)"
|
|
19
|
+
];
|
|
20
|
+
const D = m.colorScale || B;
|
|
21
|
+
var Z = [NaN, NaN, null], I, N, U = m.data, P, q, O, V, z, F, G, j = !1, tt = function(t) {
|
|
22
|
+
U = t;
|
|
23
|
+
}, et = function(t) {
|
|
24
|
+
t.hasOwnProperty("minVelocity") && (d = t.minVelocity), t.hasOwnProperty("maxVelocity") && (o = t.maxVelocity), t.hasOwnProperty("velocityScale") && (f = (t.velocityScale || 5e-3) * (Math.pow(window.devicePixelRatio, 1 / 3) || 1)), t.hasOwnProperty("particleAge") && (u = t.particleAge), t.hasOwnProperty("lineWidth") && (y = t.lineWidth), t.hasOwnProperty("particleMultiplier") && (E = t.particleMultiplier), t.hasOwnProperty("opacity") && (b = +t.opacity), t.hasOwnProperty("frameRate") && (_ = t.frameRate), S = 1e3 / _;
|
|
25
|
+
}, at = function(t, e, a, i, n, s) {
|
|
26
|
+
var r = 1 - t, l = 1 - e, c = r * l, g = t * l, h = r * e, w = t * e, M = a[0] * c + i[0] * g + n[0] * h + s[0] * w, v = a[1] * c + i[1] * g + n[1] * h + s[1] * w;
|
|
27
|
+
return [M, v, Math.sqrt(M * M + v * v)];
|
|
28
|
+
}, it = function(t, e) {
|
|
29
|
+
var a = t.data, i = e.data;
|
|
30
|
+
return {
|
|
31
|
+
header: t.header,
|
|
32
|
+
data: function(n) {
|
|
33
|
+
return [a[n], i[n]];
|
|
34
|
+
},
|
|
35
|
+
interpolate: at
|
|
36
|
+
};
|
|
37
|
+
}, rt = function(t) {
|
|
38
|
+
var e = null, a = null;
|
|
39
|
+
return t.forEach(function(i) {
|
|
40
|
+
switch (i.header.parameterCategory + "," + i.header.parameterNumber) {
|
|
41
|
+
case "1,2":
|
|
42
|
+
case "2,2":
|
|
43
|
+
e = i;
|
|
44
|
+
break;
|
|
45
|
+
case "1,3":
|
|
46
|
+
case "2,3":
|
|
47
|
+
a = i;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}), it(e, a);
|
|
51
|
+
}, nt = function(t, e) {
|
|
52
|
+
I = rt(t);
|
|
53
|
+
var a = I.header;
|
|
54
|
+
q = a.lo1, O = a.la1, V = a.dx, z = a.dy, F = a.nx, G = a.ny, a.la2 && a.la1 < a.la2 ? j = !0 : j = !1, P = new Date(a.refTime), P.setHours(P.getHours() + a.forecastTime), N = [];
|
|
55
|
+
for (var i = 0, n = Math.floor(F * V) >= 360, s = 0; s < G; s++) {
|
|
56
|
+
for (var r = [], l = 0; l < F; l++, i++)
|
|
57
|
+
r[l] = I.data(i);
|
|
58
|
+
n && r.push(r[0]), N[s] = r;
|
|
59
|
+
}
|
|
60
|
+
e({
|
|
61
|
+
date: P,
|
|
62
|
+
interpolate: X
|
|
63
|
+
});
|
|
64
|
+
}, X = function(t, e) {
|
|
65
|
+
if (!N)
|
|
66
|
+
return null;
|
|
67
|
+
var a = ot(t - q, 360) / V, i;
|
|
68
|
+
j ? i = (e - O) / z : i = (O - e) / z;
|
|
69
|
+
var n = Math.floor(a), s = n + 1, r = Math.floor(i), l = r + 1, c;
|
|
70
|
+
if (c = N[r]) {
|
|
71
|
+
var g = c[n], h = c[s];
|
|
72
|
+
if (R(g) && R(h) && (c = N[l])) {
|
|
73
|
+
var w = c[n], M = c[s];
|
|
74
|
+
if (R(w) && R(M))
|
|
75
|
+
return I.interpolate(a - n, i - r, g, h, w, M);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}, R = function(t) {
|
|
80
|
+
return t != null;
|
|
81
|
+
}, ot = function(t, e) {
|
|
82
|
+
return t - e * Math.floor(t / e);
|
|
83
|
+
}, st = function() {
|
|
84
|
+
return /android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent);
|
|
85
|
+
}, lt = function(t, e, a, i, n, s, r) {
|
|
86
|
+
var l = r[0] * s, c = r[1] * s, g = ht(t, e, a, i, n);
|
|
87
|
+
return r[0] = g[0] * l + g[2] * c, r[1] = g[1] * l + g[3] * c, r;
|
|
88
|
+
}, ht = function(t, e, a, i, n) {
|
|
89
|
+
var s = 2 * Math.PI, r = 5, l = e < 0 ? r : -r, c = a < 0 ? r : -r, g = J(a, e + l), h = J(a + c, e), w = Math.cos(a / 360 * s);
|
|
90
|
+
return [
|
|
91
|
+
(g[0] - i) / l / w,
|
|
92
|
+
(g[1] - n) / l / w,
|
|
93
|
+
(h[0] - i) / c,
|
|
94
|
+
(h[1] - n) / c
|
|
95
|
+
];
|
|
96
|
+
}, $ = function(t, e, a) {
|
|
97
|
+
function i(n, s) {
|
|
98
|
+
var r = t[Math.round(n)];
|
|
99
|
+
return r && r[Math.round(s)] || Z;
|
|
100
|
+
}
|
|
101
|
+
i.release = function() {
|
|
102
|
+
t = [];
|
|
103
|
+
}, i.randomize = function(n) {
|
|
104
|
+
var s, r, l = 0;
|
|
105
|
+
do
|
|
106
|
+
s = Math.round(Math.floor(Math.random() * e.width) + e.x), r = Math.round(Math.floor(Math.random() * e.height) + e.y);
|
|
107
|
+
while (i(s, r)[2] === null && l++ < 30);
|
|
108
|
+
return n.x = s, n.y = r, n;
|
|
109
|
+
}, a(e, i);
|
|
110
|
+
}, vt = function(t, e, a) {
|
|
111
|
+
var i = t[0], n = t[1], s = Math.round(i[0]), r = Math.max(Math.floor(i[1], 0), 0);
|
|
112
|
+
Math.min(Math.ceil(n[0], e), e - 1);
|
|
113
|
+
var l = Math.min(Math.ceil(n[1], a), a - 1);
|
|
114
|
+
return { x: s, y: r, xMax: e, yMax: l, width: e, height: a };
|
|
115
|
+
}, A = function(t) {
|
|
116
|
+
return t / 180 * Math.PI;
|
|
117
|
+
}, ct = function(t, e, a) {
|
|
118
|
+
var i = m.map.containerPointToLatLng({ x: t, y: e });
|
|
119
|
+
return [i.lng, i.lat];
|
|
120
|
+
}, J = function(t, e, a) {
|
|
121
|
+
var i = m.map.latLngToContainerPoint({ lat: t, lng: e });
|
|
122
|
+
return [i.x, i.y];
|
|
123
|
+
}, ft = function(t, e, a, i) {
|
|
124
|
+
var n = {}, s = (a.south - a.north) * (a.west - a.east), r = f * Math.pow(s, 0.4), l = [], c = e.x;
|
|
125
|
+
function g(h) {
|
|
126
|
+
for (var w = [], M = e.y; M <= e.yMax; M += 2) {
|
|
127
|
+
var v = ct(h, M);
|
|
128
|
+
if (v) {
|
|
129
|
+
var C = v[0], L = v[1];
|
|
130
|
+
if (isFinite(C)) {
|
|
131
|
+
var p = t.interpolate(C, L);
|
|
132
|
+
p && (p = lt(n, C, L, h, M, r, p), w[M + 1] = w[M] = p);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
l[h + 1] = l[h] = w;
|
|
137
|
+
}
|
|
138
|
+
(function h() {
|
|
139
|
+
for (var w = Date.now(); c < e.width; )
|
|
140
|
+
if (g(c), c += 2, Date.now() - w > 1e3) {
|
|
141
|
+
setTimeout(h, 25);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
$(l, e, i);
|
|
145
|
+
})();
|
|
146
|
+
}, k, ut = function(t, e) {
|
|
147
|
+
function a(v, C) {
|
|
148
|
+
return D.indexFor = function(L) {
|
|
149
|
+
return Math.max(0, Math.min(D.length - 1, Math.round((L - v) / (C - v) * (D.length - 1))));
|
|
150
|
+
}, D;
|
|
151
|
+
}
|
|
152
|
+
var i = a(d, o), n = i.map(function() {
|
|
153
|
+
return [];
|
|
154
|
+
}), s = Math.round(t.width * t.height * E);
|
|
155
|
+
st() && (s *= T);
|
|
156
|
+
for (var r = `rgba(0, 0, 0, ${b})`, l = [], c = 0; c < s; c++)
|
|
157
|
+
l.push(e.randomize({ age: Math.floor(Math.random() * u) + 0 }));
|
|
158
|
+
function g() {
|
|
159
|
+
n.forEach(function(v) {
|
|
160
|
+
v.length = 0;
|
|
161
|
+
}), l.forEach(function(v) {
|
|
162
|
+
v.age > u && (e.randomize(v).age = 0);
|
|
163
|
+
var C = v.x, L = v.y, p = e(C, L), Q = p[2];
|
|
164
|
+
if (Q === null)
|
|
165
|
+
v.age = u;
|
|
166
|
+
else {
|
|
167
|
+
var H = C + p[0], Y = L + p[1];
|
|
168
|
+
e(H, Y)[2] !== null ? (v.xt = H, v.yt = Y, n[i.indexFor(Q)].push(v)) : (v.x = H, v.y = Y);
|
|
169
|
+
}
|
|
170
|
+
v.age += 1;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
var h = m.canvas.getContext("2d");
|
|
174
|
+
h.lineWidth = y, h.fillStyle = r, h.globalAlpha = 0.6;
|
|
175
|
+
function w() {
|
|
176
|
+
var v = "lighter";
|
|
177
|
+
h.globalCompositeOperation = "destination-in", h.fillRect(t.x, t.y, t.width, t.height), h.globalCompositeOperation = v, h.globalAlpha = b === 0 ? 0 : b * 0.9, n.forEach(function(C, L) {
|
|
178
|
+
C.length > 0 && (h.beginPath(), h.strokeStyle = i[L], C.forEach(function(p) {
|
|
179
|
+
h.moveTo(p.x, p.y), h.lineTo(p.xt, p.yt), p.x = p.xt, p.y = p.yt;
|
|
180
|
+
}), h.stroke());
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
var M = Date.now();
|
|
184
|
+
(function v() {
|
|
185
|
+
k = requestAnimationFrame(v);
|
|
186
|
+
var C = Date.now(), L = C - M;
|
|
187
|
+
L > S && (M = C - L % S, g(), w());
|
|
188
|
+
})();
|
|
189
|
+
}, dt = function(t, e, a, i) {
|
|
190
|
+
var n = {
|
|
191
|
+
south: A(i[0][1]),
|
|
192
|
+
north: A(i[1][1]),
|
|
193
|
+
east: A(i[1][0]),
|
|
194
|
+
west: A(i[0][0]),
|
|
195
|
+
width: e,
|
|
196
|
+
height: a
|
|
197
|
+
};
|
|
198
|
+
K(), nt(U, function(s) {
|
|
199
|
+
ft(s, vt(t, e, a), n, function(r, l) {
|
|
200
|
+
W.field = l, ut(r, l);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}, K = function() {
|
|
204
|
+
if (W.field && W.field.release(), k && cancelAnimationFrame(k), m.canvas) {
|
|
205
|
+
var t = m.canvas.getContext("2d");
|
|
206
|
+
t.clearRect(0, 0, m.canvas.width, m.canvas.height);
|
|
207
|
+
}
|
|
208
|
+
}, W = {
|
|
209
|
+
params: m,
|
|
210
|
+
start: dt,
|
|
211
|
+
stop: K,
|
|
212
|
+
createField: $,
|
|
213
|
+
interpolatePoint: X,
|
|
214
|
+
setData: tt,
|
|
215
|
+
setOptions: et
|
|
216
|
+
};
|
|
217
|
+
return W;
|
|
218
|
+
};
|
|
219
|
+
class mt {
|
|
220
|
+
constructor(d, o = {}) {
|
|
221
|
+
this.viewer = d, this.options = {
|
|
222
|
+
url: "",
|
|
223
|
+
// JSON 数据地址
|
|
224
|
+
lineWidth: 2,
|
|
225
|
+
velocityScale: 0.05,
|
|
226
|
+
maxVelocity: 0.7,
|
|
227
|
+
minVelocity: 0,
|
|
228
|
+
opacity: 0.97,
|
|
229
|
+
particleAge: 90,
|
|
230
|
+
frameRate: 15,
|
|
231
|
+
colorScale: null,
|
|
232
|
+
safetyHeight: 48e5,
|
|
233
|
+
// 默认安全高度
|
|
234
|
+
...o
|
|
235
|
+
}, this.windy = null, this.canvas = null, this.globalData = null, this.activeExtent = [0, -90, 360, 90], this.timer = null, this._resizeListener = this._onResize.bind(this), this._cameraMoveEndListener = this._onCameraMoveEnd.bind(this), this._cameraMoveStartListener = this._onCameraMoveStart.bind(this), this._initCanvas(), this._setupEventListeners(), this.options.url && this.loadData(this.options.url);
|
|
236
|
+
}
|
|
237
|
+
_initCanvas() {
|
|
238
|
+
this.canvas = document.createElement("canvas"), this.canvas.style.cssText = "position:absolute; top:0; left:0; pointer-events:none; z-index:100; display:none;", this.canvas.className = "cesium-windy-canvas", this.viewer.cesiumWidget.container.appendChild(this.canvas), this._resizeCanvas();
|
|
239
|
+
}
|
|
240
|
+
_resizeCanvas() {
|
|
241
|
+
const d = this.viewer.canvas.clientWidth, o = this.viewer.canvas.clientHeight;
|
|
242
|
+
this.canvas.width = d, this.canvas.height = o;
|
|
243
|
+
}
|
|
244
|
+
async loadData(d) {
|
|
245
|
+
try {
|
|
246
|
+
const f = await (await fetch(d)).json();
|
|
247
|
+
this.globalData = Object.freeze(f), this.updateWindyState();
|
|
248
|
+
} catch (o) {
|
|
249
|
+
console.error("[CesiumWindy] Data loading failed:", o);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
_setupEventListeners() {
|
|
253
|
+
this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartListener), this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndListener), window.addEventListener("resize", this._resizeListener);
|
|
254
|
+
}
|
|
255
|
+
_onCameraMoveStart() {
|
|
256
|
+
this.canvas && (this.canvas.style.display = "none"), this.windy && this.windy.stop();
|
|
257
|
+
}
|
|
258
|
+
_onCameraMoveEnd() {
|
|
259
|
+
this.timer && clearTimeout(this.timer), this.timer = setTimeout(() => {
|
|
260
|
+
this.updateWindyState();
|
|
261
|
+
}, 200);
|
|
262
|
+
}
|
|
263
|
+
_onResize() {
|
|
264
|
+
this._resizeCanvas(), this.updateWindyState();
|
|
265
|
+
}
|
|
266
|
+
// === 核心逻辑:从 Vue 移植过来的视图计算 ===
|
|
267
|
+
updateWindyState() {
|
|
268
|
+
if (!this.globalData || !this.viewer)
|
|
269
|
+
return;
|
|
270
|
+
const d = this.viewer.camera.positionCartographic.height;
|
|
271
|
+
let o = [0, -90, 360, 90], f = 360;
|
|
272
|
+
if (d > this.options.safetyHeight)
|
|
273
|
+
o = [0, -90, 360, 90], f = 360;
|
|
274
|
+
else {
|
|
275
|
+
const y = this.viewer.camera.computeViewRectangle(this.viewer.scene.globe.ellipsoid);
|
|
276
|
+
if (y) {
|
|
277
|
+
let E = x.Math.toDegrees(y.west), T = x.Math.toDegrees(y.south), _ = x.Math.toDegrees(y.east), S = x.Math.toDegrees(y.north);
|
|
278
|
+
const b = (_ - E + 360) % 360;
|
|
279
|
+
E > _ || b < 0.5 ? (o = [0, -90, 360, 90], f = 360) : (o = [
|
|
280
|
+
E - 2,
|
|
281
|
+
Math.max(-90, T - 2),
|
|
282
|
+
_ + 2,
|
|
283
|
+
Math.min(90, S + 2)
|
|
284
|
+
], o[0] < 0 && (o[0] += 360), o[2] < 0 && (o[2] += 360), f = b);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
this.activeExtent = o;
|
|
288
|
+
let u;
|
|
289
|
+
f > 120 ? u = 1 / 600 : f > 60 ? u = 1 / 500 : f > 20 ? u = 1 / 300 : u = 1 / 200, d > this.options.safetyHeight && u > 1 / 300 && (u = 1 / 300), this._renderWindy(u, o);
|
|
290
|
+
}
|
|
291
|
+
_renderWindy(d, o) {
|
|
292
|
+
const f = this.canvas.width, u = this.canvas.height;
|
|
293
|
+
this.windy || (this.windy = new yt({
|
|
294
|
+
canvas: this.canvas,
|
|
295
|
+
data: this.globalData,
|
|
296
|
+
map: this._getMapAdapter(),
|
|
297
|
+
particleMultiplier: d,
|
|
298
|
+
lineWidth: this.options.lineWidth,
|
|
299
|
+
velocityScale: this.options.velocityScale,
|
|
300
|
+
maxVelocity: this.options.maxVelocity,
|
|
301
|
+
minVelocity: this.options.minVelocity,
|
|
302
|
+
opacity: this.options.opacity,
|
|
303
|
+
frameRate: this.options.frameRate,
|
|
304
|
+
colorScale: this.options.colorScale
|
|
305
|
+
})), this.windy.setOptions({
|
|
306
|
+
particleMultiplier: d
|
|
307
|
+
}), this.canvas.style.display = "block", this.windy.start(
|
|
308
|
+
[[0, 0], [f, u]],
|
|
309
|
+
f,
|
|
310
|
+
u,
|
|
311
|
+
[[o[0], o[1]], [o[2], o[3]]]
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
// === 坐标适配器 ===
|
|
315
|
+
_getMapAdapter() {
|
|
316
|
+
const d = this;
|
|
317
|
+
return {
|
|
318
|
+
containerPointToLatLng: (o) => {
|
|
319
|
+
const f = d.viewer.camera.pickEllipsoid(
|
|
320
|
+
new x.Cartesian2(o.x, o.y),
|
|
321
|
+
d.viewer.scene.globe.ellipsoid
|
|
322
|
+
);
|
|
323
|
+
if (!f)
|
|
324
|
+
return { lng: NaN, lat: NaN };
|
|
325
|
+
const u = x.Cartographic.fromCartesian(f);
|
|
326
|
+
let y = x.Math.toDegrees(u.longitude);
|
|
327
|
+
const E = x.Math.toDegrees(u.latitude);
|
|
328
|
+
y < 0 && (y += 360);
|
|
329
|
+
const [T, _, S, b] = d.activeExtent;
|
|
330
|
+
if (T < S) {
|
|
331
|
+
if (y < T || y > S || E < _ || E > b)
|
|
332
|
+
return { lng: NaN, lat: NaN };
|
|
333
|
+
} else if (E < _ || E > b)
|
|
334
|
+
return { lng: NaN, lat: NaN };
|
|
335
|
+
return { lng: y, lat: E };
|
|
336
|
+
},
|
|
337
|
+
latLngToContainerPoint: (o) => {
|
|
338
|
+
let f = o.lng;
|
|
339
|
+
f > 180 && (f -= 360);
|
|
340
|
+
const u = x.Cartesian3.fromDegrees(f, o.lat);
|
|
341
|
+
try {
|
|
342
|
+
const y = d.viewer.scene.cartesianToCanvasCoordinates(u);
|
|
343
|
+
if (y)
|
|
344
|
+
return { x: y.x, y: y.y };
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
return { x: -1e3, y: -1e3 };
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
// 销毁方法
|
|
352
|
+
destroy() {
|
|
353
|
+
this.windy && this.windy.stop(), this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartListener), this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEndListener), window.removeEventListener("resize", this._resizeListener), this.canvas && this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
export {
|
|
357
|
+
mt as default
|
|
358
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(S,D){typeof exports=="object"&&typeof module<"u"?module.exports=D(require("cesium")):typeof define=="function"&&define.amd?define(["cesium"],D):(S=typeof globalThis<"u"?globalThis:S||self,S.CesiumOceanCurrentZKXT123=D(S.Cesium))})(this,function(S){"use strict";function D(v){const u=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(v){for(const n in v)if(n!=="default"){const f=Object.getOwnPropertyDescriptor(v,n);Object.defineProperty(u,n,f.get?f:{enumerable:!0,get:()=>v[n]})}}return u.default=v,Object.freeze(u)}const x=D(S);var te=function(v){var u=v.minVelocity||0,n=v.maxVelocity||10,f=(v.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),m=v.particleAge||90,y=v.lineWidth||1,b=v.particleMultiplier||1/300,N=Math.pow(window.devicePixelRatio,1/3)||1.6,_=v.frameRate||15,T=1e3/_,L=.97,U=["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"];const O=v.colorScale||U;var ie=[NaN,NaN,null],I,P,X=v.data,R,G,z,j,F,k,K,H=!1,re=function(e){X=e},ne=function(e){e.hasOwnProperty("minVelocity")&&(u=e.minVelocity),e.hasOwnProperty("maxVelocity")&&(n=e.maxVelocity),e.hasOwnProperty("velocityScale")&&(f=(e.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),e.hasOwnProperty("particleAge")&&(m=e.particleAge),e.hasOwnProperty("lineWidth")&&(y=e.lineWidth),e.hasOwnProperty("particleMultiplier")&&(b=e.particleMultiplier),e.hasOwnProperty("opacity")&&(L=+e.opacity),e.hasOwnProperty("frameRate")&&(_=e.frameRate),T=1e3/_},oe=function(e,t,a,i,o,s){var r=1-e,l=1-t,d=r*l,g=e*l,c=r*t,w=e*t,M=a[0]*d+i[0]*g+o[0]*c+s[0]*w,h=a[1]*d+i[1]*g+o[1]*c+s[1]*w;return[M,h,Math.sqrt(M*M+h*h)]},se=function(e,t){var a=e.data,i=t.data;return{header:e.header,data:function(o){return[a[o],i[o]]},interpolate:oe}},le=function(e){var t=null,a=null;return e.forEach(function(i){switch(i.header.parameterCategory+","+i.header.parameterNumber){case"1,2":case"2,2":t=i;break;case"1,3":case"2,3":a=i;break}}),se(t,a)},ce=function(e,t){I=le(e);var a=I.header;G=a.lo1,z=a.la1,j=a.dx,F=a.dy,k=a.nx,K=a.ny,a.la2&&a.la1<a.la2?H=!0:H=!1,R=new Date(a.refTime),R.setHours(R.getHours()+a.forecastTime),P=[];for(var i=0,o=Math.floor(k*j)>=360,s=0;s<K;s++){for(var r=[],l=0;l<k;l++,i++)r[l]=I.data(i);o&&r.push(r[0]),P[s]=r}t({date:R,interpolate:Z})},Z=function(e,t){if(!P)return null;var a=he(e-G,360)/j,i;H?i=(t-z)/F:i=(z-t)/F;var o=Math.floor(a),s=o+1,r=Math.floor(i),l=r+1,d;if(d=P[r]){var g=d[o],c=d[s];if(A(g)&&A(c)&&(d=P[l])){var w=d[o],M=d[s];if(A(w)&&A(M))return I.interpolate(a-o,i-r,g,c,w,M)}}return null},A=function(e){return e!=null},he=function(e,t){return e-t*Math.floor(e/t)},ve=function(){return/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)},fe=function(e,t,a,i,o,s,r){var l=r[0]*s,d=r[1]*s,g=ue(e,t,a,i,o);return r[0]=g[0]*l+g[2]*d,r[1]=g[1]*l+g[3]*d,r},ue=function(e,t,a,i,o){var s=2*Math.PI,r=5,l=t<0?r:-r,d=a<0?r:-r,g=J(a,t+l),c=J(a+d,t),w=Math.cos(a/360*s);return[(g[0]-i)/l/w,(g[1]-o)/l/w,(c[0]-i)/d,(c[1]-o)/d]},$=function(e,t,a){function i(o,s){var r=e[Math.round(o)];return r&&r[Math.round(s)]||ie}i.release=function(){e=[]},i.randomize=function(o){var s,r,l=0;do s=Math.round(Math.floor(Math.random()*t.width)+t.x),r=Math.round(Math.floor(Math.random()*t.height)+t.y);while(i(s,r)[2]===null&&l++<30);return o.x=s,o.y=r,o},a(t,i)},de=function(e,t,a){var i=e[0],o=e[1],s=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],t),t-1);var l=Math.min(Math.ceil(o[1],a),a-1);return{x:s,y:r,xMax:t,yMax:l,width:t,height:a}},W=function(e){return e/180*Math.PI},me=function(e,t,a){var i=v.map.containerPointToLatLng({x:e,y:t});return[i.lng,i.lat]},J=function(e,t,a){var i=v.map.latLngToContainerPoint({lat:e,lng:t});return[i.x,i.y]},ye=function(e,t,a,i){var o={},s=(a.south-a.north)*(a.west-a.east),r=f*Math.pow(s,.4),l=[],d=t.x;function g(c){for(var w=[],M=t.y;M<=t.yMax;M+=2){var h=me(c,M);if(h){var C=h[0],E=h[1];if(isFinite(C)){var p=e.interpolate(C,E);p&&(p=fe(o,C,E,c,M,r,p),w[M+1]=w[M]=p)}}}l[c+1]=l[c]=w}(function c(){for(var w=Date.now();d<t.width;)if(g(d),d+=2,Date.now()-w>1e3){setTimeout(c,25);return}$(l,t,i)})()},Y,ge=function(e,t){function a(h,C){return O.indexFor=function(E){return Math.max(0,Math.min(O.length-1,Math.round((E-h)/(C-h)*(O.length-1))))},O}var i=a(u,n),o=i.map(function(){return[]}),s=Math.round(e.width*e.height*b);ve()&&(s*=N);for(var r=`rgba(0, 0, 0, ${L})`,l=[],d=0;d<s;d++)l.push(t.randomize({age:Math.floor(Math.random()*m)+0}));function g(){o.forEach(function(h){h.length=0}),l.forEach(function(h){h.age>m&&(t.randomize(h).age=0);var C=h.x,E=h.y,p=t(C,E),ee=p[2];if(ee===null)h.age=m;else{var B=C+p[0],q=E+p[1];t(B,q)[2]!==null?(h.xt=B,h.yt=q,o[i.indexFor(ee)].push(h)):(h.x=B,h.y=q)}h.age+=1})}var c=v.canvas.getContext("2d");c.lineWidth=y,c.fillStyle=r,c.globalAlpha=.6;function w(){var h="lighter";c.globalCompositeOperation="destination-in",c.fillRect(e.x,e.y,e.width,e.height),c.globalCompositeOperation=h,c.globalAlpha=L===0?0:L*.9,o.forEach(function(C,E){C.length>0&&(c.beginPath(),c.strokeStyle=i[E],C.forEach(function(p){c.moveTo(p.x,p.y),c.lineTo(p.xt,p.yt),p.x=p.xt,p.y=p.yt}),c.stroke())})}var M=Date.now();(function h(){Y=requestAnimationFrame(h);var C=Date.now(),E=C-M;E>T&&(M=C-E%T,g(),w())})()},pe=function(e,t,a,i){var o={south:W(i[0][1]),north:W(i[1][1]),east:W(i[1][0]),west:W(i[0][0]),width:t,height:a};Q(),ce(X,function(s){ye(s,de(e,t,a),o,function(r,l){V.field=l,ge(r,l)})})},Q=function(){if(V.field&&V.field.release(),Y&&cancelAnimationFrame(Y),v.canvas){var e=v.canvas.getContext("2d");e.clearRect(0,0,v.canvas.width,v.canvas.height)}},V={params:v,start:pe,stop:Q,createField:$,interpolatePoint:Z,setData:re,setOptions:ne};return V};class ae{constructor(u,n={}){this.viewer=u,this.options={url:"",lineWidth:2,velocityScale:.05,maxVelocity:.7,minVelocity:0,opacity:.97,particleAge:90,frameRate:15,colorScale:null,safetyHeight:48e5,...n},this.windy=null,this.canvas=null,this.globalData=null,this.activeExtent=[0,-90,360,90],this.timer=null,this._resizeListener=this._onResize.bind(this),this._cameraMoveEndListener=this._onCameraMoveEnd.bind(this),this._cameraMoveStartListener=this._onCameraMoveStart.bind(this),this._initCanvas(),this._setupEventListeners(),this.options.url&&this.loadData(this.options.url)}_initCanvas(){this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute; top:0; left:0; pointer-events:none; z-index:100; display:none;",this.canvas.className="cesium-windy-canvas",this.viewer.cesiumWidget.container.appendChild(this.canvas),this._resizeCanvas()}_resizeCanvas(){const u=this.viewer.canvas.clientWidth,n=this.viewer.canvas.clientHeight;this.canvas.width=u,this.canvas.height=n}async loadData(u){try{const f=await(await fetch(u)).json();this.globalData=Object.freeze(f),this.updateWindyState()}catch(n){console.error("[CesiumWindy] Data loading failed:",n)}}_setupEventListeners(){this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartListener),this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndListener),window.addEventListener("resize",this._resizeListener)}_onCameraMoveStart(){this.canvas&&(this.canvas.style.display="none"),this.windy&&this.windy.stop()}_onCameraMoveEnd(){this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.updateWindyState()},200)}_onResize(){this._resizeCanvas(),this.updateWindyState()}updateWindyState(){if(!this.globalData||!this.viewer)return;const u=this.viewer.camera.positionCartographic.height;let n=[0,-90,360,90],f=360;if(u>this.options.safetyHeight)n=[0,-90,360,90],f=360;else{const y=this.viewer.camera.computeViewRectangle(this.viewer.scene.globe.ellipsoid);if(y){let b=x.Math.toDegrees(y.west),N=x.Math.toDegrees(y.south),_=x.Math.toDegrees(y.east),T=x.Math.toDegrees(y.north);const L=(_-b+360)%360;b>_||L<.5?(n=[0,-90,360,90],f=360):(n=[b-2,Math.max(-90,N-2),_+2,Math.min(90,T+2)],n[0]<0&&(n[0]+=360),n[2]<0&&(n[2]+=360),f=L)}}this.activeExtent=n;let m;f>120?m=1/600:f>60?m=1/500:f>20?m=1/300:m=1/200,u>this.options.safetyHeight&&m>1/300&&(m=1/300),this._renderWindy(m,n)}_renderWindy(u,n){const f=this.canvas.width,m=this.canvas.height;this.windy||(this.windy=new te({canvas:this.canvas,data:this.globalData,map:this._getMapAdapter(),particleMultiplier:u,lineWidth:this.options.lineWidth,velocityScale:this.options.velocityScale,maxVelocity:this.options.maxVelocity,minVelocity:this.options.minVelocity,opacity:this.options.opacity,frameRate:this.options.frameRate,colorScale:this.options.colorScale})),this.windy.setOptions({particleMultiplier:u}),this.canvas.style.display="block",this.windy.start([[0,0],[f,m]],f,m,[[n[0],n[1]],[n[2],n[3]]])}_getMapAdapter(){const u=this;return{containerPointToLatLng:n=>{const f=u.viewer.camera.pickEllipsoid(new x.Cartesian2(n.x,n.y),u.viewer.scene.globe.ellipsoid);if(!f)return{lng:NaN,lat:NaN};const m=x.Cartographic.fromCartesian(f);let y=x.Math.toDegrees(m.longitude);const b=x.Math.toDegrees(m.latitude);y<0&&(y+=360);const[N,_,T,L]=u.activeExtent;if(N<T){if(y<N||y>T||b<_||b>L)return{lng:NaN,lat:NaN}}else if(b<_||b>L)return{lng:NaN,lat:NaN};return{lng:y,lat:b}},latLngToContainerPoint:n=>{let f=n.lng;f>180&&(f-=360);const m=x.Cartesian3.fromDegrees(f,n.lat);try{const y=u.viewer.scene.cartesianToCanvasCoordinates(m);if(y)return{x:y.x,y:y.y}}catch{}return{x:-1e3,y:-1e3}}}}destroy(){this.windy&&this.windy.stop(),this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartListener),this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEndListener),window.removeEventListener("resize",this._resizeListener),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}return ae});
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import * as x from "cesium";
|
|
2
|
+
var yt = function(m) {
|
|
3
|
+
var d = m.minVelocity || 0, o = m.maxVelocity || 10, f = (m.velocityScale || 5e-3) * (Math.pow(window.devicePixelRatio, 1 / 3) || 1), u = m.particleAge || 90, y = m.lineWidth || 1, E = m.particleMultiplier || 1 / 300, T = Math.pow(window.devicePixelRatio, 1 / 3) || 1.6, _ = m.frameRate || 15, S = 1e3 / _, b = 0.97, B = [
|
|
4
|
+
"rgb(36,104, 180)",
|
|
5
|
+
"rgb(60,157, 194)",
|
|
6
|
+
"rgb(128,205,193 )",
|
|
7
|
+
"rgb(151,218,168 )",
|
|
8
|
+
"rgb(198,231,181)",
|
|
9
|
+
"rgb(238,247,217)",
|
|
10
|
+
"rgb(255,238,159)",
|
|
11
|
+
"rgb(252,217,125)",
|
|
12
|
+
"rgb(255,182,100)",
|
|
13
|
+
"rgb(252,150,75)",
|
|
14
|
+
"rgb(250,112,52)",
|
|
15
|
+
"rgb(245,64,32)",
|
|
16
|
+
"rgb(237,45,28)",
|
|
17
|
+
"rgb(220,24,32)",
|
|
18
|
+
"rgb(180,0,35)"
|
|
19
|
+
];
|
|
20
|
+
const D = m.colorScale || B;
|
|
21
|
+
var Z = [NaN, NaN, null], I, N, U = m.data, P, q, O, V, z, F, G, j = !1, tt = function(t) {
|
|
22
|
+
U = t;
|
|
23
|
+
}, et = function(t) {
|
|
24
|
+
t.hasOwnProperty("minVelocity") && (d = t.minVelocity), t.hasOwnProperty("maxVelocity") && (o = t.maxVelocity), t.hasOwnProperty("velocityScale") && (f = (t.velocityScale || 5e-3) * (Math.pow(window.devicePixelRatio, 1 / 3) || 1)), t.hasOwnProperty("particleAge") && (u = t.particleAge), t.hasOwnProperty("lineWidth") && (y = t.lineWidth), t.hasOwnProperty("particleMultiplier") && (E = t.particleMultiplier), t.hasOwnProperty("opacity") && (b = +t.opacity), t.hasOwnProperty("frameRate") && (_ = t.frameRate), S = 1e3 / _;
|
|
25
|
+
}, at = function(t, e, a, i, n, s) {
|
|
26
|
+
var r = 1 - t, l = 1 - e, c = r * l, g = t * l, h = r * e, w = t * e, M = a[0] * c + i[0] * g + n[0] * h + s[0] * w, v = a[1] * c + i[1] * g + n[1] * h + s[1] * w;
|
|
27
|
+
return [M, v, Math.sqrt(M * M + v * v)];
|
|
28
|
+
}, it = function(t, e) {
|
|
29
|
+
var a = t.data, i = e.data;
|
|
30
|
+
return {
|
|
31
|
+
header: t.header,
|
|
32
|
+
data: function(n) {
|
|
33
|
+
return [a[n], i[n]];
|
|
34
|
+
},
|
|
35
|
+
interpolate: at
|
|
36
|
+
};
|
|
37
|
+
}, rt = function(t) {
|
|
38
|
+
var e = null, a = null;
|
|
39
|
+
return t.forEach(function(i) {
|
|
40
|
+
switch (i.header.parameterCategory + "," + i.header.parameterNumber) {
|
|
41
|
+
case "1,2":
|
|
42
|
+
case "2,2":
|
|
43
|
+
e = i;
|
|
44
|
+
break;
|
|
45
|
+
case "1,3":
|
|
46
|
+
case "2,3":
|
|
47
|
+
a = i;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}), it(e, a);
|
|
51
|
+
}, nt = function(t, e) {
|
|
52
|
+
I = rt(t);
|
|
53
|
+
var a = I.header;
|
|
54
|
+
q = a.lo1, O = a.la1, V = a.dx, z = a.dy, F = a.nx, G = a.ny, a.la2 && a.la1 < a.la2 ? j = !0 : j = !1, P = new Date(a.refTime), P.setHours(P.getHours() + a.forecastTime), N = [];
|
|
55
|
+
for (var i = 0, n = Math.floor(F * V) >= 360, s = 0; s < G; s++) {
|
|
56
|
+
for (var r = [], l = 0; l < F; l++, i++)
|
|
57
|
+
r[l] = I.data(i);
|
|
58
|
+
n && r.push(r[0]), N[s] = r;
|
|
59
|
+
}
|
|
60
|
+
e({
|
|
61
|
+
date: P,
|
|
62
|
+
interpolate: X
|
|
63
|
+
});
|
|
64
|
+
}, X = function(t, e) {
|
|
65
|
+
if (!N)
|
|
66
|
+
return null;
|
|
67
|
+
var a = ot(t - q, 360) / V, i;
|
|
68
|
+
j ? i = (e - O) / z : i = (O - e) / z;
|
|
69
|
+
var n = Math.floor(a), s = n + 1, r = Math.floor(i), l = r + 1, c;
|
|
70
|
+
if (c = N[r]) {
|
|
71
|
+
var g = c[n], h = c[s];
|
|
72
|
+
if (R(g) && R(h) && (c = N[l])) {
|
|
73
|
+
var w = c[n], M = c[s];
|
|
74
|
+
if (R(w) && R(M))
|
|
75
|
+
return I.interpolate(a - n, i - r, g, h, w, M);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}, R = function(t) {
|
|
80
|
+
return t != null;
|
|
81
|
+
}, ot = function(t, e) {
|
|
82
|
+
return t - e * Math.floor(t / e);
|
|
83
|
+
}, st = function() {
|
|
84
|
+
return /android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent);
|
|
85
|
+
}, lt = function(t, e, a, i, n, s, r) {
|
|
86
|
+
var l = r[0] * s, c = r[1] * s, g = ht(t, e, a, i, n);
|
|
87
|
+
return r[0] = g[0] * l + g[2] * c, r[1] = g[1] * l + g[3] * c, r;
|
|
88
|
+
}, ht = function(t, e, a, i, n) {
|
|
89
|
+
var s = 2 * Math.PI, r = 5, l = e < 0 ? r : -r, c = a < 0 ? r : -r, g = J(a, e + l), h = J(a + c, e), w = Math.cos(a / 360 * s);
|
|
90
|
+
return [
|
|
91
|
+
(g[0] - i) / l / w,
|
|
92
|
+
(g[1] - n) / l / w,
|
|
93
|
+
(h[0] - i) / c,
|
|
94
|
+
(h[1] - n) / c
|
|
95
|
+
];
|
|
96
|
+
}, $ = function(t, e, a) {
|
|
97
|
+
function i(n, s) {
|
|
98
|
+
var r = t[Math.round(n)];
|
|
99
|
+
return r && r[Math.round(s)] || Z;
|
|
100
|
+
}
|
|
101
|
+
i.release = function() {
|
|
102
|
+
t = [];
|
|
103
|
+
}, i.randomize = function(n) {
|
|
104
|
+
var s, r, l = 0;
|
|
105
|
+
do
|
|
106
|
+
s = Math.round(Math.floor(Math.random() * e.width) + e.x), r = Math.round(Math.floor(Math.random() * e.height) + e.y);
|
|
107
|
+
while (i(s, r)[2] === null && l++ < 30);
|
|
108
|
+
return n.x = s, n.y = r, n;
|
|
109
|
+
}, a(e, i);
|
|
110
|
+
}, vt = function(t, e, a) {
|
|
111
|
+
var i = t[0], n = t[1], s = Math.round(i[0]), r = Math.max(Math.floor(i[1], 0), 0);
|
|
112
|
+
Math.min(Math.ceil(n[0], e), e - 1);
|
|
113
|
+
var l = Math.min(Math.ceil(n[1], a), a - 1);
|
|
114
|
+
return { x: s, y: r, xMax: e, yMax: l, width: e, height: a };
|
|
115
|
+
}, A = function(t) {
|
|
116
|
+
return t / 180 * Math.PI;
|
|
117
|
+
}, ct = function(t, e, a) {
|
|
118
|
+
var i = m.map.containerPointToLatLng({ x: t, y: e });
|
|
119
|
+
return [i.lng, i.lat];
|
|
120
|
+
}, J = function(t, e, a) {
|
|
121
|
+
var i = m.map.latLngToContainerPoint({ lat: t, lng: e });
|
|
122
|
+
return [i.x, i.y];
|
|
123
|
+
}, ft = function(t, e, a, i) {
|
|
124
|
+
var n = {}, s = (a.south - a.north) * (a.west - a.east), r = f * Math.pow(s, 0.4), l = [], c = e.x;
|
|
125
|
+
function g(h) {
|
|
126
|
+
for (var w = [], M = e.y; M <= e.yMax; M += 2) {
|
|
127
|
+
var v = ct(h, M);
|
|
128
|
+
if (v) {
|
|
129
|
+
var C = v[0], L = v[1];
|
|
130
|
+
if (isFinite(C)) {
|
|
131
|
+
var p = t.interpolate(C, L);
|
|
132
|
+
p && (p = lt(n, C, L, h, M, r, p), w[M + 1] = w[M] = p);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
l[h + 1] = l[h] = w;
|
|
137
|
+
}
|
|
138
|
+
(function h() {
|
|
139
|
+
for (var w = Date.now(); c < e.width; )
|
|
140
|
+
if (g(c), c += 2, Date.now() - w > 1e3) {
|
|
141
|
+
setTimeout(h, 25);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
$(l, e, i);
|
|
145
|
+
})();
|
|
146
|
+
}, k, ut = function(t, e) {
|
|
147
|
+
function a(v, C) {
|
|
148
|
+
return D.indexFor = function(L) {
|
|
149
|
+
return Math.max(0, Math.min(D.length - 1, Math.round((L - v) / (C - v) * (D.length - 1))));
|
|
150
|
+
}, D;
|
|
151
|
+
}
|
|
152
|
+
var i = a(d, o), n = i.map(function() {
|
|
153
|
+
return [];
|
|
154
|
+
}), s = Math.round(t.width * t.height * E);
|
|
155
|
+
st() && (s *= T);
|
|
156
|
+
for (var r = `rgba(0, 0, 0, ${b})`, l = [], c = 0; c < s; c++)
|
|
157
|
+
l.push(e.randomize({ age: Math.floor(Math.random() * u) + 0 }));
|
|
158
|
+
function g() {
|
|
159
|
+
n.forEach(function(v) {
|
|
160
|
+
v.length = 0;
|
|
161
|
+
}), l.forEach(function(v) {
|
|
162
|
+
v.age > u && (e.randomize(v).age = 0);
|
|
163
|
+
var C = v.x, L = v.y, p = e(C, L), Q = p[2];
|
|
164
|
+
if (Q === null)
|
|
165
|
+
v.age = u;
|
|
166
|
+
else {
|
|
167
|
+
var H = C + p[0], Y = L + p[1];
|
|
168
|
+
e(H, Y)[2] !== null ? (v.xt = H, v.yt = Y, n[i.indexFor(Q)].push(v)) : (v.x = H, v.y = Y);
|
|
169
|
+
}
|
|
170
|
+
v.age += 1;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
var h = m.canvas.getContext("2d");
|
|
174
|
+
h.lineWidth = y, h.fillStyle = r, h.globalAlpha = 0.6;
|
|
175
|
+
function w() {
|
|
176
|
+
var v = "lighter";
|
|
177
|
+
h.globalCompositeOperation = "destination-in", h.fillRect(t.x, t.y, t.width, t.height), h.globalCompositeOperation = v, h.globalAlpha = b === 0 ? 0 : b * 0.9, n.forEach(function(C, L) {
|
|
178
|
+
C.length > 0 && (h.beginPath(), h.strokeStyle = i[L], C.forEach(function(p) {
|
|
179
|
+
h.moveTo(p.x, p.y), h.lineTo(p.xt, p.yt), p.x = p.xt, p.y = p.yt;
|
|
180
|
+
}), h.stroke());
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
var M = Date.now();
|
|
184
|
+
(function v() {
|
|
185
|
+
k = requestAnimationFrame(v);
|
|
186
|
+
var C = Date.now(), L = C - M;
|
|
187
|
+
L > S && (M = C - L % S, g(), w());
|
|
188
|
+
})();
|
|
189
|
+
}, dt = function(t, e, a, i) {
|
|
190
|
+
var n = {
|
|
191
|
+
south: A(i[0][1]),
|
|
192
|
+
north: A(i[1][1]),
|
|
193
|
+
east: A(i[1][0]),
|
|
194
|
+
west: A(i[0][0]),
|
|
195
|
+
width: e,
|
|
196
|
+
height: a
|
|
197
|
+
};
|
|
198
|
+
K(), nt(U, function(s) {
|
|
199
|
+
ft(s, vt(t, e, a), n, function(r, l) {
|
|
200
|
+
W.field = l, ut(r, l);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}, K = function() {
|
|
204
|
+
if (W.field && W.field.release(), k && cancelAnimationFrame(k), m.canvas) {
|
|
205
|
+
var t = m.canvas.getContext("2d");
|
|
206
|
+
t.clearRect(0, 0, m.canvas.width, m.canvas.height);
|
|
207
|
+
}
|
|
208
|
+
}, W = {
|
|
209
|
+
params: m,
|
|
210
|
+
start: dt,
|
|
211
|
+
stop: K,
|
|
212
|
+
createField: $,
|
|
213
|
+
interpolatePoint: X,
|
|
214
|
+
setData: tt,
|
|
215
|
+
setOptions: et
|
|
216
|
+
};
|
|
217
|
+
return W;
|
|
218
|
+
};
|
|
219
|
+
class mt {
|
|
220
|
+
constructor(d, o = {}) {
|
|
221
|
+
this.viewer = d, this.options = {
|
|
222
|
+
url: "",
|
|
223
|
+
// JSON 数据地址
|
|
224
|
+
lineWidth: 2,
|
|
225
|
+
velocityScale: 0.05,
|
|
226
|
+
maxVelocity: 0.7,
|
|
227
|
+
minVelocity: 0,
|
|
228
|
+
opacity: 0.97,
|
|
229
|
+
particleAge: 90,
|
|
230
|
+
frameRate: 15,
|
|
231
|
+
colorScale: null,
|
|
232
|
+
safetyHeight: 48e5,
|
|
233
|
+
// 默认安全高度
|
|
234
|
+
...o
|
|
235
|
+
}, this.windy = null, this.canvas = null, this.globalData = null, this.activeExtent = [0, -90, 360, 90], this.timer = null, this._resizeListener = this._onResize.bind(this), this._cameraMoveEndListener = this._onCameraMoveEnd.bind(this), this._cameraMoveStartListener = this._onCameraMoveStart.bind(this), this._initCanvas(), this._setupEventListeners(), this.options.url && this.loadData(this.options.url);
|
|
236
|
+
}
|
|
237
|
+
_initCanvas() {
|
|
238
|
+
this.canvas = document.createElement("canvas"), this.canvas.style.cssText = "position:absolute; top:0; left:0; pointer-events:none; z-index:100; display:none;", this.canvas.className = "cesium-windy-canvas", this.viewer.cesiumWidget.container.appendChild(this.canvas), this._resizeCanvas();
|
|
239
|
+
}
|
|
240
|
+
_resizeCanvas() {
|
|
241
|
+
const d = this.viewer.canvas.clientWidth, o = this.viewer.canvas.clientHeight;
|
|
242
|
+
this.canvas.width = d, this.canvas.height = o;
|
|
243
|
+
}
|
|
244
|
+
async loadData(d) {
|
|
245
|
+
try {
|
|
246
|
+
const f = await (await fetch(d)).json();
|
|
247
|
+
this.globalData = Object.freeze(f), this.updateWindyState();
|
|
248
|
+
} catch (o) {
|
|
249
|
+
console.error("[CesiumWindy] Data loading failed:", o);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
_setupEventListeners() {
|
|
253
|
+
this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartListener), this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndListener), window.addEventListener("resize", this._resizeListener);
|
|
254
|
+
}
|
|
255
|
+
_onCameraMoveStart() {
|
|
256
|
+
this.canvas && (this.canvas.style.display = "none"), this.windy && this.windy.stop();
|
|
257
|
+
}
|
|
258
|
+
_onCameraMoveEnd() {
|
|
259
|
+
this.timer && clearTimeout(this.timer), this.timer = setTimeout(() => {
|
|
260
|
+
this.updateWindyState();
|
|
261
|
+
}, 200);
|
|
262
|
+
}
|
|
263
|
+
_onResize() {
|
|
264
|
+
this._resizeCanvas(), this.updateWindyState();
|
|
265
|
+
}
|
|
266
|
+
// === 核心逻辑:从 Vue 移植过来的视图计算 ===
|
|
267
|
+
updateWindyState() {
|
|
268
|
+
if (!this.globalData || !this.viewer)
|
|
269
|
+
return;
|
|
270
|
+
const d = this.viewer.camera.positionCartographic.height;
|
|
271
|
+
let o = [0, -90, 360, 90], f = 360;
|
|
272
|
+
if (d > this.options.safetyHeight)
|
|
273
|
+
o = [0, -90, 360, 90], f = 360;
|
|
274
|
+
else {
|
|
275
|
+
const y = this.viewer.camera.computeViewRectangle(this.viewer.scene.globe.ellipsoid);
|
|
276
|
+
if (y) {
|
|
277
|
+
let E = x.Math.toDegrees(y.west), T = x.Math.toDegrees(y.south), _ = x.Math.toDegrees(y.east), S = x.Math.toDegrees(y.north);
|
|
278
|
+
const b = (_ - E + 360) % 360;
|
|
279
|
+
E > _ || b < 0.5 ? (o = [0, -90, 360, 90], f = 360) : (o = [
|
|
280
|
+
E - 2,
|
|
281
|
+
Math.max(-90, T - 2),
|
|
282
|
+
_ + 2,
|
|
283
|
+
Math.min(90, S + 2)
|
|
284
|
+
], o[0] < 0 && (o[0] += 360), o[2] < 0 && (o[2] += 360), f = b);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
this.activeExtent = o;
|
|
288
|
+
let u;
|
|
289
|
+
f > 120 ? u = 1 / 600 : f > 60 ? u = 1 / 500 : f > 20 ? u = 1 / 300 : u = 1 / 200, d > this.options.safetyHeight && u > 1 / 300 && (u = 1 / 300), this._renderWindy(u, o);
|
|
290
|
+
}
|
|
291
|
+
_renderWindy(d, o) {
|
|
292
|
+
const f = this.canvas.width, u = this.canvas.height;
|
|
293
|
+
this.windy || (this.windy = new yt({
|
|
294
|
+
canvas: this.canvas,
|
|
295
|
+
data: this.globalData,
|
|
296
|
+
map: this._getMapAdapter(),
|
|
297
|
+
particleMultiplier: d,
|
|
298
|
+
lineWidth: this.options.lineWidth,
|
|
299
|
+
velocityScale: this.options.velocityScale,
|
|
300
|
+
maxVelocity: this.options.maxVelocity,
|
|
301
|
+
minVelocity: this.options.minVelocity,
|
|
302
|
+
opacity: this.options.opacity,
|
|
303
|
+
frameRate: this.options.frameRate,
|
|
304
|
+
colorScale: this.options.colorScale
|
|
305
|
+
})), this.windy.setOptions({
|
|
306
|
+
particleMultiplier: d
|
|
307
|
+
}), this.canvas.style.display = "block", this.windy.start(
|
|
308
|
+
[[0, 0], [f, u]],
|
|
309
|
+
f,
|
|
310
|
+
u,
|
|
311
|
+
[[o[0], o[1]], [o[2], o[3]]]
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
// === 坐标适配器 ===
|
|
315
|
+
_getMapAdapter() {
|
|
316
|
+
const d = this;
|
|
317
|
+
return {
|
|
318
|
+
containerPointToLatLng: (o) => {
|
|
319
|
+
const f = d.viewer.camera.pickEllipsoid(
|
|
320
|
+
new x.Cartesian2(o.x, o.y),
|
|
321
|
+
d.viewer.scene.globe.ellipsoid
|
|
322
|
+
);
|
|
323
|
+
if (!f)
|
|
324
|
+
return { lng: NaN, lat: NaN };
|
|
325
|
+
const u = x.Cartographic.fromCartesian(f);
|
|
326
|
+
let y = x.Math.toDegrees(u.longitude);
|
|
327
|
+
const E = x.Math.toDegrees(u.latitude);
|
|
328
|
+
y < 0 && (y += 360);
|
|
329
|
+
const [T, _, S, b] = d.activeExtent;
|
|
330
|
+
if (T < S) {
|
|
331
|
+
if (y < T || y > S || E < _ || E > b)
|
|
332
|
+
return { lng: NaN, lat: NaN };
|
|
333
|
+
} else if (E < _ || E > b)
|
|
334
|
+
return { lng: NaN, lat: NaN };
|
|
335
|
+
return { lng: y, lat: E };
|
|
336
|
+
},
|
|
337
|
+
latLngToContainerPoint: (o) => {
|
|
338
|
+
let f = o.lng;
|
|
339
|
+
f > 180 && (f -= 360);
|
|
340
|
+
const u = x.Cartesian3.fromDegrees(f, o.lat);
|
|
341
|
+
try {
|
|
342
|
+
const y = d.viewer.scene.cartesianToCanvasCoordinates(u);
|
|
343
|
+
if (y)
|
|
344
|
+
return { x: y.x, y: y.y };
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
return { x: -1e3, y: -1e3 };
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
// 销毁方法
|
|
352
|
+
destroy() {
|
|
353
|
+
this.windy && this.windy.stop(), this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartListener), this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEndListener), window.removeEventListener("resize", this._resizeListener), this.canvas && this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
export {
|
|
357
|
+
mt as default
|
|
358
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(T,D){typeof exports=="object"&&typeof module<"u"?module.exports=D(require("cesium")):typeof define=="function"&&define.amd?define(["cesium"],D):(T=typeof globalThis<"u"?globalThis:T||self,T.CesiumWindyLayer=D(T.Cesium))})(this,function(T){"use strict";function D(v){const u=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(v){for(const n in v)if(n!=="default"){const f=Object.getOwnPropertyDescriptor(v,n);Object.defineProperty(u,n,f.get?f:{enumerable:!0,get:()=>v[n]})}}return u.default=v,Object.freeze(u)}const x=D(T);var te=function(v){var u=v.minVelocity||0,n=v.maxVelocity||10,f=(v.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),m=v.particleAge||90,y=v.lineWidth||1,b=v.particleMultiplier||1/300,N=Math.pow(window.devicePixelRatio,1/3)||1.6,_=v.frameRate||15,S=1e3/_,L=.97,U=["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"];const I=v.colorScale||U;var ie=[NaN,NaN,null],O,P,G=v.data,R,X,z,j,F,k,$,H=!1,re=function(e){G=e},ne=function(e){e.hasOwnProperty("minVelocity")&&(u=e.minVelocity),e.hasOwnProperty("maxVelocity")&&(n=e.maxVelocity),e.hasOwnProperty("velocityScale")&&(f=(e.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),e.hasOwnProperty("particleAge")&&(m=e.particleAge),e.hasOwnProperty("lineWidth")&&(y=e.lineWidth),e.hasOwnProperty("particleMultiplier")&&(b=e.particleMultiplier),e.hasOwnProperty("opacity")&&(L=+e.opacity),e.hasOwnProperty("frameRate")&&(_=e.frameRate),S=1e3/_},oe=function(e,t,a,i,o,s){var r=1-e,l=1-t,d=r*l,g=e*l,c=r*t,w=e*t,M=a[0]*d+i[0]*g+o[0]*c+s[0]*w,h=a[1]*d+i[1]*g+o[1]*c+s[1]*w;return[M,h,Math.sqrt(M*M+h*h)]},se=function(e,t){var a=e.data,i=t.data;return{header:e.header,data:function(o){return[a[o],i[o]]},interpolate:oe}},le=function(e){var t=null,a=null;return e.forEach(function(i){switch(i.header.parameterCategory+","+i.header.parameterNumber){case"1,2":case"2,2":t=i;break;case"1,3":case"2,3":a=i;break}}),se(t,a)},ce=function(e,t){O=le(e);var a=O.header;X=a.lo1,z=a.la1,j=a.dx,F=a.dy,k=a.nx,$=a.ny,a.la2&&a.la1<a.la2?H=!0:H=!1,R=new Date(a.refTime),R.setHours(R.getHours()+a.forecastTime),P=[];for(var i=0,o=Math.floor(k*j)>=360,s=0;s<$;s++){for(var r=[],l=0;l<k;l++,i++)r[l]=O.data(i);o&&r.push(r[0]),P[s]=r}t({date:R,interpolate:J})},J=function(e,t){if(!P)return null;var a=he(e-X,360)/j,i;H?i=(t-z)/F:i=(z-t)/F;var o=Math.floor(a),s=o+1,r=Math.floor(i),l=r+1,d;if(d=P[r]){var g=d[o],c=d[s];if(A(g)&&A(c)&&(d=P[l])){var w=d[o],M=d[s];if(A(w)&&A(M))return O.interpolate(a-o,i-r,g,c,w,M)}}return null},A=function(e){return e!=null},he=function(e,t){return e-t*Math.floor(e/t)},ve=function(){return/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)},fe=function(e,t,a,i,o,s,r){var l=r[0]*s,d=r[1]*s,g=ue(e,t,a,i,o);return r[0]=g[0]*l+g[2]*d,r[1]=g[1]*l+g[3]*d,r},ue=function(e,t,a,i,o){var s=2*Math.PI,r=5,l=t<0?r:-r,d=a<0?r:-r,g=Q(a,t+l),c=Q(a+d,t),w=Math.cos(a/360*s);return[(g[0]-i)/l/w,(g[1]-o)/l/w,(c[0]-i)/d,(c[1]-o)/d]},K=function(e,t,a){function i(o,s){var r=e[Math.round(o)];return r&&r[Math.round(s)]||ie}i.release=function(){e=[]},i.randomize=function(o){var s,r,l=0;do s=Math.round(Math.floor(Math.random()*t.width)+t.x),r=Math.round(Math.floor(Math.random()*t.height)+t.y);while(i(s,r)[2]===null&&l++<30);return o.x=s,o.y=r,o},a(t,i)},de=function(e,t,a){var i=e[0],o=e[1],s=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],t),t-1);var l=Math.min(Math.ceil(o[1],a),a-1);return{x:s,y:r,xMax:t,yMax:l,width:t,height:a}},W=function(e){return e/180*Math.PI},me=function(e,t,a){var i=v.map.containerPointToLatLng({x:e,y:t});return[i.lng,i.lat]},Q=function(e,t,a){var i=v.map.latLngToContainerPoint({lat:e,lng:t});return[i.x,i.y]},ye=function(e,t,a,i){var o={},s=(a.south-a.north)*(a.west-a.east),r=f*Math.pow(s,.4),l=[],d=t.x;function g(c){for(var w=[],M=t.y;M<=t.yMax;M+=2){var h=me(c,M);if(h){var C=h[0],E=h[1];if(isFinite(C)){var p=e.interpolate(C,E);p&&(p=fe(o,C,E,c,M,r,p),w[M+1]=w[M]=p)}}}l[c+1]=l[c]=w}(function c(){for(var w=Date.now();d<t.width;)if(g(d),d+=2,Date.now()-w>1e3){setTimeout(c,25);return}K(l,t,i)})()},Y,ge=function(e,t){function a(h,C){return I.indexFor=function(E){return Math.max(0,Math.min(I.length-1,Math.round((E-h)/(C-h)*(I.length-1))))},I}var i=a(u,n),o=i.map(function(){return[]}),s=Math.round(e.width*e.height*b);ve()&&(s*=N);for(var r=`rgba(0, 0, 0, ${L})`,l=[],d=0;d<s;d++)l.push(t.randomize({age:Math.floor(Math.random()*m)+0}));function g(){o.forEach(function(h){h.length=0}),l.forEach(function(h){h.age>m&&(t.randomize(h).age=0);var C=h.x,E=h.y,p=t(C,E),ee=p[2];if(ee===null)h.age=m;else{var B=C+p[0],q=E+p[1];t(B,q)[2]!==null?(h.xt=B,h.yt=q,o[i.indexFor(ee)].push(h)):(h.x=B,h.y=q)}h.age+=1})}var c=v.canvas.getContext("2d");c.lineWidth=y,c.fillStyle=r,c.globalAlpha=.6;function w(){var h="lighter";c.globalCompositeOperation="destination-in",c.fillRect(e.x,e.y,e.width,e.height),c.globalCompositeOperation=h,c.globalAlpha=L===0?0:L*.9,o.forEach(function(C,E){C.length>0&&(c.beginPath(),c.strokeStyle=i[E],C.forEach(function(p){c.moveTo(p.x,p.y),c.lineTo(p.xt,p.yt),p.x=p.xt,p.y=p.yt}),c.stroke())})}var M=Date.now();(function h(){Y=requestAnimationFrame(h);var C=Date.now(),E=C-M;E>S&&(M=C-E%S,g(),w())})()},pe=function(e,t,a,i){var o={south:W(i[0][1]),north:W(i[1][1]),east:W(i[1][0]),west:W(i[0][0]),width:t,height:a};Z(),ce(G,function(s){ye(s,de(e,t,a),o,function(r,l){V.field=l,ge(r,l)})})},Z=function(){if(V.field&&V.field.release(),Y&&cancelAnimationFrame(Y),v.canvas){var e=v.canvas.getContext("2d");e.clearRect(0,0,v.canvas.width,v.canvas.height)}},V={params:v,start:pe,stop:Z,createField:K,interpolatePoint:J,setData:re,setOptions:ne};return V};class ae{constructor(u,n={}){this.viewer=u,this.options={url:"",lineWidth:2,velocityScale:.05,maxVelocity:.7,minVelocity:0,opacity:.97,particleAge:90,frameRate:15,colorScale:null,safetyHeight:48e5,...n},this.windy=null,this.canvas=null,this.globalData=null,this.activeExtent=[0,-90,360,90],this.timer=null,this._resizeListener=this._onResize.bind(this),this._cameraMoveEndListener=this._onCameraMoveEnd.bind(this),this._cameraMoveStartListener=this._onCameraMoveStart.bind(this),this._initCanvas(),this._setupEventListeners(),this.options.url&&this.loadData(this.options.url)}_initCanvas(){this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute; top:0; left:0; pointer-events:none; z-index:100; display:none;",this.canvas.className="cesium-windy-canvas",this.viewer.cesiumWidget.container.appendChild(this.canvas),this._resizeCanvas()}_resizeCanvas(){const u=this.viewer.canvas.clientWidth,n=this.viewer.canvas.clientHeight;this.canvas.width=u,this.canvas.height=n}async loadData(u){try{const f=await(await fetch(u)).json();this.globalData=Object.freeze(f),this.updateWindyState()}catch(n){console.error("[CesiumWindy] Data loading failed:",n)}}_setupEventListeners(){this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartListener),this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndListener),window.addEventListener("resize",this._resizeListener)}_onCameraMoveStart(){this.canvas&&(this.canvas.style.display="none"),this.windy&&this.windy.stop()}_onCameraMoveEnd(){this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.updateWindyState()},200)}_onResize(){this._resizeCanvas(),this.updateWindyState()}updateWindyState(){if(!this.globalData||!this.viewer)return;const u=this.viewer.camera.positionCartographic.height;let n=[0,-90,360,90],f=360;if(u>this.options.safetyHeight)n=[0,-90,360,90],f=360;else{const y=this.viewer.camera.computeViewRectangle(this.viewer.scene.globe.ellipsoid);if(y){let b=x.Math.toDegrees(y.west),N=x.Math.toDegrees(y.south),_=x.Math.toDegrees(y.east),S=x.Math.toDegrees(y.north);const L=(_-b+360)%360;b>_||L<.5?(n=[0,-90,360,90],f=360):(n=[b-2,Math.max(-90,N-2),_+2,Math.min(90,S+2)],n[0]<0&&(n[0]+=360),n[2]<0&&(n[2]+=360),f=L)}}this.activeExtent=n;let m;f>120?m=1/600:f>60?m=1/500:f>20?m=1/300:m=1/200,u>this.options.safetyHeight&&m>1/300&&(m=1/300),this._renderWindy(m,n)}_renderWindy(u,n){const f=this.canvas.width,m=this.canvas.height;this.windy||(this.windy=new te({canvas:this.canvas,data:this.globalData,map:this._getMapAdapter(),particleMultiplier:u,lineWidth:this.options.lineWidth,velocityScale:this.options.velocityScale,maxVelocity:this.options.maxVelocity,minVelocity:this.options.minVelocity,opacity:this.options.opacity,frameRate:this.options.frameRate,colorScale:this.options.colorScale})),this.windy.setOptions({particleMultiplier:u}),this.canvas.style.display="block",this.windy.start([[0,0],[f,m]],f,m,[[n[0],n[1]],[n[2],n[3]]])}_getMapAdapter(){const u=this;return{containerPointToLatLng:n=>{const f=u.viewer.camera.pickEllipsoid(new x.Cartesian2(n.x,n.y),u.viewer.scene.globe.ellipsoid);if(!f)return{lng:NaN,lat:NaN};const m=x.Cartographic.fromCartesian(f);let y=x.Math.toDegrees(m.longitude);const b=x.Math.toDegrees(m.latitude);y<0&&(y+=360);const[N,_,S,L]=u.activeExtent;if(N<S){if(y<N||y>S||b<_||b>L)return{lng:NaN,lat:NaN}}else if(b<_||b>L)return{lng:NaN,lat:NaN};return{lng:y,lat:b}},latLngToContainerPoint:n=>{let f=n.lng;f>180&&(f-=360);const m=x.Cartesian3.fromDegrees(f,n.lat);try{const y=u.viewer.scene.cartesianToCanvasCoordinates(m);if(y)return{x:y.x,y:y.y}}catch{}return{x:-1e3,y:-1e3}}}}destroy(){this.windy&&this.windy.stop(),this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartListener),this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEndListener),window.removeEventListener("resize",this._resizeListener),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}return ae});
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cesium-ocean-current-zkxt123",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Ocean current visualization",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"main": "./dist/cesium-ocean-current-zkxt123.umd.js",
|
|
10
|
+
"module": "./dist/cesium-ocean-current-zkxt123.es.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/cesium-ocean-current-zkxt123.es.js",
|
|
14
|
+
"require": "./dist/cesium-ocean-current-zkxt123.umd.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "vite",
|
|
19
|
+
"build": "vite build",
|
|
20
|
+
"preview": "vite preview"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"cesium",
|
|
24
|
+
"windy",
|
|
25
|
+
"ocean current",
|
|
26
|
+
"visualization"
|
|
27
|
+
],
|
|
28
|
+
"author": "bobo_chen",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"cesium": "^1.90.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"vite": "^4.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|