@things-factory/weather 9.0.0-beta.52 → 9.0.0-beta.56
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/client/ol-components/wind-data-tile-layer.ts +485 -0
- package/client/ol-components/wind-rasterized-layer.ts +437 -0
- package/client/pages/weather-page.ts +149 -144
- package/config/config.development.js +3 -0
- package/config/config.production.js +3 -0
- package/dist-client/ol-components/wind-data-tile-layer.d.ts +59 -0
- package/dist-client/ol-components/wind-data-tile-layer.js +414 -0
- package/dist-client/ol-components/wind-data-tile-layer.js.map +1 -0
- package/dist-client/ol-components/wind-rasterized-layer.d.ts +59 -0
- package/dist-client/ol-components/wind-rasterized-layer.js +363 -0
- package/dist-client/ol-components/wind-rasterized-layer.js.map +1 -0
- package/dist-client/pages/weather-page.d.ts +7 -2
- package/dist-client/pages/weather-page.js +145 -125
- package/dist-client/pages/weather-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/open-meteo-adapter.js +3 -1
- package/dist-server/controllers/open-meteo-adapter.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/server/controllers/open-meteo-adapter.ts +3 -1
- package/client/ol-components/webgl-image-static.ts +0 -244
- package/client/ol-components/wind.ts +0 -120
|
@@ -8,25 +8,11 @@ import TileLayer from 'ol/layer/Tile.js';
|
|
|
8
8
|
import { fromLonLat } from 'ol/proj.js';
|
|
9
9
|
import 'ol/ol.css';
|
|
10
10
|
import { MVT } from 'ol/format';
|
|
11
|
-
import { DEVICE_PIXEL_RATIO } from 'ol/has.js';
|
|
12
|
-
import Flow from 'ol/layer/Flow.js';
|
|
13
|
-
import ImageLayer from 'ol/layer/Image';
|
|
14
|
-
import WebGLImageStatic from '../ol-components/webgl-image-static';
|
|
15
11
|
import { VectorTile, XYZ } from 'ol/source';
|
|
16
|
-
import VectorSource from 'ol/source/Vector';
|
|
17
|
-
import colormap from 'colormap';
|
|
18
|
-
import Heatmap from 'ol/layer/Heatmap.js';
|
|
19
|
-
import Feature from 'ol/Feature.js';
|
|
20
|
-
import Point from 'ol/geom/Point.js';
|
|
21
|
-
import { Stroke, Style } from 'ol/style.js';
|
|
22
|
-
import wind from '../ol-components/wind.js';
|
|
23
12
|
import VectorTileLayer from 'ol/layer/VectorTile';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
alpha: 0.3,
|
|
28
|
-
format: 'rgba'
|
|
29
|
-
});
|
|
13
|
+
import { Style, Stroke } from 'ol/style';
|
|
14
|
+
import { TemperatureLayer, PrecipitationLayer, initializeWorkerSystem } from '@hyperviz/weather';
|
|
15
|
+
import { WindDataTileLayer } from '../ol-components/wind-data-tile-layer.js';
|
|
30
16
|
let WeatherPage = class WeatherPage extends PageView {
|
|
31
17
|
static get styles() {
|
|
32
18
|
return css `
|
|
@@ -98,6 +84,8 @@ let WeatherPage = class WeatherPage extends PageView {
|
|
|
98
84
|
constructor() {
|
|
99
85
|
super();
|
|
100
86
|
this.activeType = 'temperature';
|
|
87
|
+
this.map = null;
|
|
88
|
+
this.weatherLayer = null;
|
|
101
89
|
}
|
|
102
90
|
render() {
|
|
103
91
|
return html `
|
|
@@ -111,12 +99,6 @@ let WeatherPage = class WeatherPage extends PageView {
|
|
|
111
99
|
>
|
|
112
100
|
온도
|
|
113
101
|
</button>
|
|
114
|
-
<button
|
|
115
|
-
class="weather-btn ${this.activeType === 'humidity' ? 'active' : ''}"
|
|
116
|
-
@click=${() => this._changeWeatherType('humidity')}
|
|
117
|
-
>
|
|
118
|
-
습도
|
|
119
|
-
</button>
|
|
120
102
|
<button
|
|
121
103
|
class="weather-btn ${this.activeType === 'wind' ? 'active' : ''}"
|
|
122
104
|
@click=${() => this._changeWeatherType('wind')}
|
|
@@ -136,28 +118,32 @@ let WeatherPage = class WeatherPage extends PageView {
|
|
|
136
118
|
}
|
|
137
119
|
connectedCallback() {
|
|
138
120
|
super.connectedCallback();
|
|
121
|
+
initializeWorkerSystem();
|
|
139
122
|
requestAnimationFrame(() => {
|
|
140
123
|
this._initMap();
|
|
141
124
|
});
|
|
142
125
|
}
|
|
143
126
|
disconnectedCallback() {
|
|
144
127
|
super.disconnectedCallback();
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
128
|
+
if (this.weatherLayer) {
|
|
129
|
+
try {
|
|
130
|
+
this.weatherLayer.removeFromMap();
|
|
131
|
+
this.weatherLayer.dispose();
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
console.error('Error disposing weather layer:', e);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (this.map) {
|
|
138
|
+
this.map.dispose();
|
|
139
|
+
}
|
|
148
140
|
this.map = null;
|
|
149
141
|
this.weatherLayer = null;
|
|
150
142
|
}
|
|
151
143
|
_initMap() {
|
|
152
144
|
const lightOSM = new TileLayer({
|
|
153
145
|
source: new XYZ({
|
|
154
|
-
// url: 'https://{a-c}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png',
|
|
155
|
-
// url: 'https://{a-c}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',
|
|
156
146
|
url: 'https://{a-c}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',
|
|
157
|
-
// url: 'https://{a-c}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',
|
|
158
|
-
// url: 'https://{a-c}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png'
|
|
159
|
-
// url: 'https://api.maptiler.com/maps/toner-lines/{z}/{x}/{y}.png?key=uHikv5CybbRm7cDLjRca'
|
|
160
|
-
// attributions: '© MapTiler'
|
|
161
147
|
attributions: '© OpenStreetMap contributors, © CartoDB'
|
|
162
148
|
}),
|
|
163
149
|
background: 'transparent',
|
|
@@ -166,7 +152,6 @@ let WeatherPage = class WeatherPage extends PageView {
|
|
|
166
152
|
const labelOSM = new TileLayer({
|
|
167
153
|
source: new XYZ({
|
|
168
154
|
url: 'https://{a-c}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}{r}.png'
|
|
169
|
-
// url: 'https://{a-c}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}{r}.png'
|
|
170
155
|
}),
|
|
171
156
|
background: 'transparent',
|
|
172
157
|
opacity: 1
|
|
@@ -190,118 +175,157 @@ let WeatherPage = class WeatherPage extends PageView {
|
|
|
190
175
|
})
|
|
191
176
|
})
|
|
192
177
|
});
|
|
193
|
-
console.log('🛠 벡터 타일 레이어:', outlineLayer, outlineLayer.getSource());
|
|
194
|
-
/* heatmap */
|
|
195
|
-
const generateHeatmapData = () => {
|
|
196
|
-
const features = [];
|
|
197
|
-
for (let i = 0; i < 20000; i++) {
|
|
198
|
-
// 더 많은 데이터 포인트 생성
|
|
199
|
-
const lon = Math.random() * 360 - 180; // 전 세계 경도 (-180 ~ 180)
|
|
200
|
-
const lat = Math.random() * 170 - 85; // 전 세계 위도 (-85 ~ 85)
|
|
201
|
-
const weight = Math.random() * 1; // 가중치 (0 ~ 2)
|
|
202
|
-
const feature = new Feature({
|
|
203
|
-
geometry: new Point(fromLonLat([lon, lat])),
|
|
204
|
-
weight: weight
|
|
205
|
-
});
|
|
206
|
-
features.push(feature);
|
|
207
|
-
}
|
|
208
|
-
return features;
|
|
209
|
-
};
|
|
210
|
-
const vectorSource = new VectorSource({
|
|
211
|
-
features: generateHeatmapData()
|
|
212
|
-
});
|
|
213
|
-
const heatmapLayer = new Heatmap({
|
|
214
|
-
source: vectorSource,
|
|
215
|
-
blur: 60, // 흐림 정도 증가
|
|
216
|
-
radius: 60, // 점의 반경 증가
|
|
217
|
-
weight: feature => feature.get('weight'), // 가중치 적용
|
|
218
|
-
gradient: colors.map(c => `rgba(${c.join(',')})`), // 색상 적용
|
|
219
|
-
opacity: 0.8
|
|
220
|
-
});
|
|
221
178
|
this.map = new Map({
|
|
222
179
|
target: this.renderRoot.querySelector('#map'),
|
|
223
|
-
pixelRatio: Math.min(
|
|
224
|
-
layers: [lightOSM,
|
|
180
|
+
pixelRatio: Math.min(window.devicePixelRatio, 2),
|
|
181
|
+
layers: [lightOSM, outlineLayer, labelOSM],
|
|
225
182
|
view: new View({
|
|
226
|
-
center: fromLonLat([
|
|
227
|
-
zoom:
|
|
183
|
+
center: fromLonLat([126.9779692, 37.5662952]),
|
|
184
|
+
zoom: 5
|
|
228
185
|
})
|
|
229
186
|
});
|
|
230
187
|
this._addWeatherLayer();
|
|
231
|
-
// this._addWindLayer()
|
|
232
|
-
}
|
|
233
|
-
_addWindLayer() {
|
|
234
|
-
if (this.windLayer) {
|
|
235
|
-
this.map.removeLayer(this.windLayer);
|
|
236
|
-
console.log('🚨 기존 날씨 레이어 제거');
|
|
237
|
-
}
|
|
238
|
-
const maxSpeed = 20;
|
|
239
|
-
const colorStops = [];
|
|
240
|
-
for (let i = 0; i < colors.length; ++i) {
|
|
241
|
-
colorStops.push((i * maxSpeed) / (colors.length - 1));
|
|
242
|
-
colorStops.push(colors[i]);
|
|
243
|
-
}
|
|
244
|
-
this.windLayer = new Flow({
|
|
245
|
-
source: wind,
|
|
246
|
-
maxSpeed,
|
|
247
|
-
particles: 20000,
|
|
248
|
-
style: {
|
|
249
|
-
color: ['interpolate', ['linear'], ['get', 'speed'], ...colorStops]
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
this.map.addLayer(this.windLayer);
|
|
253
188
|
}
|
|
254
189
|
_addWeatherLayer() {
|
|
255
|
-
if (this.
|
|
256
|
-
|
|
257
|
-
console.log('🚨 기존 날씨 레이어 제거');
|
|
258
|
-
}
|
|
259
|
-
// 날씨 타입별 최적 설정
|
|
260
|
-
let opacity, blendMode;
|
|
190
|
+
if (!this.map)
|
|
191
|
+
return;
|
|
261
192
|
switch (this.activeType) {
|
|
262
193
|
case 'temperature':
|
|
263
|
-
|
|
264
|
-
blendMode = 'normal';
|
|
265
|
-
break;
|
|
266
|
-
case 'humidity':
|
|
267
|
-
opacity = 0.65;
|
|
268
|
-
blendMode = 'multiply';
|
|
194
|
+
this.weatherLayer = new TemperatureLayer();
|
|
269
195
|
break;
|
|
270
196
|
case 'wind':
|
|
271
|
-
|
|
272
|
-
blendMode = 'screen';
|
|
197
|
+
this.weatherLayer = new WindDataTileLayer();
|
|
273
198
|
break;
|
|
274
199
|
case 'precipitation':
|
|
275
|
-
|
|
276
|
-
blendMode = 'color-dodge';
|
|
200
|
+
this.weatherLayer = new PrecipitationLayer();
|
|
277
201
|
break;
|
|
278
202
|
default:
|
|
279
|
-
|
|
280
|
-
|
|
203
|
+
this.weatherLayer = new TemperatureLayer();
|
|
204
|
+
}
|
|
205
|
+
if (this.weatherLayer) {
|
|
206
|
+
this.weatherLayer.addToMap(this.map);
|
|
281
207
|
}
|
|
282
|
-
this.weatherLayer = new ImageLayer({
|
|
283
|
-
source: new WebGLImageStatic({
|
|
284
|
-
url: `/weather/map/${this.activeType}.png?refresh=${Date.now()}`, // 캐시 방지
|
|
285
|
-
// 올바른 지구 투영 비율 사용
|
|
286
|
-
imageExtent: [-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892],
|
|
287
|
-
interpolation: true,
|
|
288
|
-
projection: 'EPSG:3857'
|
|
289
|
-
// opacity: opacity,
|
|
290
|
-
// blendMode: blendMode
|
|
291
|
-
}),
|
|
292
|
-
opacity // WebGLImageStatic에서 투명도 처리
|
|
293
|
-
});
|
|
294
|
-
this.map.getLayers().insertAt(1, this.weatherLayer);
|
|
295
|
-
console.log('🚨 날씨 레이어 추가', this.map.getLayers());
|
|
296
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* 날씨 레이어를 변경하고 새 레이어를 맵에 추가
|
|
211
|
+
*/
|
|
297
212
|
_changeWeatherType(type) {
|
|
298
213
|
if (this.activeType === type)
|
|
299
214
|
return;
|
|
215
|
+
// 현재 활성 타입 저장
|
|
216
|
+
const previousType = this.activeType;
|
|
217
|
+
// 새로운 타입으로 변경
|
|
300
218
|
this.activeType = type;
|
|
301
|
-
|
|
219
|
+
console.log(`날씨 타입 변경 시작: ${previousType} -> ${type}`);
|
|
220
|
+
// 이전 레이어가 있을 경우 처리
|
|
221
|
+
if (this.map && this.weatherLayer) {
|
|
222
|
+
// 맵 참조 저장
|
|
223
|
+
const mapRef = this.map;
|
|
224
|
+
// 이전 레이어 참조 저장
|
|
225
|
+
const oldLayer = this.weatherLayer;
|
|
226
|
+
// 렌더링 참조 제거
|
|
227
|
+
this.weatherLayer = null;
|
|
228
|
+
// 이전 레이어 제거 처리
|
|
229
|
+
try {
|
|
230
|
+
console.log(`이전 레이어(${previousType}) 제거 시작`);
|
|
231
|
+
// 1. 레이어 시각적으로 즉시 숨김 (특히 WindDataTileLayer 경우 중요)
|
|
232
|
+
if (previousType === 'wind') {
|
|
233
|
+
if (oldLayer['layer'] && typeof oldLayer['layer'].setVisible === 'function') {
|
|
234
|
+
oldLayer['layer'].setVisible(false);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// 2. 컴포넌트에서 참조 제거 (렌더링 사이클에서 제외)
|
|
238
|
+
this.weatherLayer = null;
|
|
239
|
+
// 3. 비동기 처리: 렌더링 사이클이 완료된 후 실행
|
|
240
|
+
requestAnimationFrame(() => {
|
|
241
|
+
setTimeout(() => {
|
|
242
|
+
try {
|
|
243
|
+
// 레이어 참조가 남아있을 경우에만 제거 시도
|
|
244
|
+
if (oldLayer) {
|
|
245
|
+
oldLayer.removeFromMap();
|
|
246
|
+
// 약간의 지연 후 자원 해제
|
|
247
|
+
setTimeout(() => {
|
|
248
|
+
try {
|
|
249
|
+
oldLayer.dispose();
|
|
250
|
+
console.log(`이전 레이어(${previousType}) 완전히 제거됨`);
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
console.warn('레이어 리소스 해제 중 오류:', e);
|
|
254
|
+
}
|
|
255
|
+
// 새 레이어 생성 시작
|
|
256
|
+
this._addNewLayer(type, mapRef);
|
|
257
|
+
}, 50); // dispose 지연
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// 레이어 참조가 없는 경우 즉시 새 레이어 생성
|
|
261
|
+
this._addNewLayer(type, mapRef);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch (e) {
|
|
265
|
+
console.error('레이어 제거 중 오류 발생:', e);
|
|
266
|
+
// 오류 발생해도 새 레이어 생성 시도
|
|
267
|
+
this._addNewLayer(type, mapRef);
|
|
268
|
+
}
|
|
269
|
+
}, 100); // 레이어 제거 지연
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
console.error('레이어 전환 중 오류:', e);
|
|
274
|
+
// 에러 상태에서도 새 레이어 추가 시도
|
|
275
|
+
this._addNewLayer(type, mapRef);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// 기존 레이어가 없으면 바로 새 레이어 추가
|
|
280
|
+
this._addWeatherLayer();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 새 레이어를 안전하게 추가하는 헬퍼 메소드
|
|
285
|
+
*/
|
|
286
|
+
_addNewLayer(type, mapRef) {
|
|
287
|
+
// 타입이 바뀌지 않았는지 확인
|
|
288
|
+
if (this.activeType !== type) {
|
|
289
|
+
console.log(`타입이 변경되어 레이어 생성 취소: ${this.activeType}로 변경됨`);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
console.log(`새 레이어(${type}) 생성 시작`);
|
|
293
|
+
try {
|
|
294
|
+
// 맵 참조 확인
|
|
295
|
+
if (!this.map && mapRef) {
|
|
296
|
+
this.map = mapRef;
|
|
297
|
+
}
|
|
298
|
+
if (this.map) {
|
|
299
|
+
// 새 레이어 생성 및 맵에 추가
|
|
300
|
+
this._addWeatherLayer();
|
|
301
|
+
console.log(`새 레이어(${type}) 생성 완료`);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
console.error('맵 참조 없음: 레이어를 추가할 수 없습니다');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
console.error('새 레이어 생성 중 오류:', e);
|
|
309
|
+
}
|
|
302
310
|
}
|
|
303
311
|
_refreshWeatherMap() {
|
|
304
|
-
this.
|
|
312
|
+
if (this.weatherLayer) {
|
|
313
|
+
try {
|
|
314
|
+
// 타입에 따라 적절한 메서드 호출
|
|
315
|
+
if (this.activeType === 'wind') {
|
|
316
|
+
;
|
|
317
|
+
this.weatherLayer.updateLayer();
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
// @hyperviz/weather 레이어
|
|
321
|
+
;
|
|
322
|
+
this.weatherLayer.setWeatherData([]);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
catch (e) {
|
|
326
|
+
console.error('Error refreshing weather layer:', e);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
305
329
|
}
|
|
306
330
|
};
|
|
307
331
|
__decorate([
|
|
@@ -316,10 +340,6 @@ __decorate([
|
|
|
316
340
|
state(),
|
|
317
341
|
__metadata("design:type", Object)
|
|
318
342
|
], WeatherPage.prototype, "weatherLayer", void 0);
|
|
319
|
-
__decorate([
|
|
320
|
-
state(),
|
|
321
|
-
__metadata("design:type", Object)
|
|
322
|
-
], WeatherPage.prototype, "windLayer", void 0);
|
|
323
343
|
WeatherPage = __decorate([
|
|
324
344
|
customElement('weather-page'),
|
|
325
345
|
__metadata("design:paramtypes", [])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"weather-page.js","sourceRoot":"","sources":["../../client/pages/weather-page.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { PageView } from '@operato/shell'\n\nimport Map from 'ol/Map.js'\nimport View from 'ol/View.js'\nimport TileLayer from 'ol/layer/Tile.js'\nimport { fromLonLat } from 'ol/proj.js'\nimport 'ol/ol.css'\nimport { MVT } from 'ol/format'\nimport { DEVICE_PIXEL_RATIO } from 'ol/has.js'\nimport Flow from 'ol/layer/Flow.js'\n\nimport ImageLayer from 'ol/layer/Image'\nimport WebGLImageStatic from '../ol-components/webgl-image-static'\nimport { VectorTile, XYZ } from 'ol/source'\nimport VectorSource from 'ol/source/Vector'\nimport colormap from 'colormap'\n\nimport Heatmap from 'ol/layer/Heatmap.js'\nimport Feature from 'ol/Feature.js'\nimport Point from 'ol/geom/Point.js'\nimport { Stroke, Style } from 'ol/style.js'\n\nimport wind from '../ol-components/wind.js'\nimport VectorTileLayer from 'ol/layer/VectorTile'\n\nconst colors = colormap({\n colormap: 'jet',\n nshades: 10,\n alpha: 0.3,\n format: 'rgba'\n})\n\n@customElement('weather-page')\nexport class WeatherPage extends PageView {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .map-container {\n flex: 1;\n display: flex;\n position: relative;\n background-color: #f9f9f9;\n overflow: hidden;\n }\n\n #map {\n flex: 1;\n }\n\n .controls {\n position: absolute;\n top: 10px;\n right: 10px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n background: rgba(255, 255, 255, 0.8);\n padding: 15px;\n border-radius: 4px;\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n z-index: 10;\n }\n\n .weather-btn {\n cursor: pointer;\n padding: 8px 12px;\n background-color: #f0f0f0;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-weight: bold;\n transition: all 0.3s;\n }\n\n .weather-btn.active {\n background-color: #4281f5;\n color: white;\n border-color: #2d5ed9;\n }\n\n .refresh-btn {\n margin-top: 10px;\n cursor: pointer;\n padding: 8px 12px;\n background-color: #00c851;\n color: white;\n border: none;\n border-radius: 4px;\n font-weight: bold;\n transition: all 0.3s;\n }\n\n .refresh-btn:hover {\n background-color: #00a651;\n }\n `\n }\n\n @property({ type: String }) private activeType = 'temperature'\n @state() private map: any\n @state() private weatherLayer: any\n @state() private windLayer: any\n\n constructor() {\n super()\n }\n\n render() {\n return html`\n <div class=\"map-container\">\n <div id=\"map\"></div>\n\n <div class=\"controls\">\n <button\n class=\"weather-btn ${this.activeType === 'temperature' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('temperature')}\n >\n 온도\n </button>\n <button\n class=\"weather-btn ${this.activeType === 'humidity' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('humidity')}\n >\n 습도\n </button>\n <button\n class=\"weather-btn ${this.activeType === 'wind' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('wind')}\n >\n 바람\n </button>\n <button\n class=\"weather-btn ${this.activeType === 'precipitation' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('precipitation')}\n >\n 강수량\n </button>\n <button class=\"refresh-btn\" @click=${this._refreshWeatherMap}>새로고침</button>\n </div>\n </div>\n `\n }\n\n connectedCallback(): void {\n super.connectedCallback()\n\n requestAnimationFrame(() => {\n this._initMap()\n })\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback()\n\n this.map.removeLayer(this.weatherLayer)\n this.weatherLayer.dispose()\n this.map.dispose()\n\n this.map = null\n this.weatherLayer = null\n }\n\n private _initMap() {\n const lightOSM = new TileLayer({\n source: new XYZ({\n // url: 'https://{a-c}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png',\n // url: 'https://{a-c}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',\n url: 'https://{a-c}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',\n // url: 'https://{a-c}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',\n // url: 'https://{a-c}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png'\n // url: 'https://api.maptiler.com/maps/toner-lines/{z}/{x}/{y}.png?key=uHikv5CybbRm7cDLjRca'\n // attributions: '© MapTiler'\n attributions: '© OpenStreetMap contributors, © CartoDB'\n }),\n background: 'transparent',\n opacity: 1\n })\n\n const labelOSM = new TileLayer({\n source: new XYZ({\n url: 'https://{a-c}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}{r}.png'\n // url: 'https://{a-c}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}{r}.png'\n }),\n background: 'transparent',\n opacity: 1\n })\n\n const vectorTile = new VectorTile({\n format: new MVT({\n layerName: 'countries',\n layers: ['countries']\n }),\n url: `/geo/tiles/{z}/{x}/{y}.mvt`,\n maxZoom: 10,\n projection: 'EPSG:3857'\n })\n\n const outlineLayer = new VectorTileLayer({\n source: vectorTile,\n style: new Style({\n stroke: new Stroke({\n color: '#858585',\n // color: '#484848',\n width: 1\n })\n })\n })\n\n console.log('🛠 벡터 타일 레이어:', outlineLayer, outlineLayer.getSource())\n\n /* heatmap */\n\n const generateHeatmapData = () => {\n const features: Feature[] = []\n for (let i = 0; i < 20000; i++) {\n // 더 많은 데이터 포인트 생성\n const lon = Math.random() * 360 - 180 // 전 세계 경도 (-180 ~ 180)\n const lat = Math.random() * 170 - 85 // 전 세계 위도 (-85 ~ 85)\n\n const weight = Math.random() * 1 // 가중치 (0 ~ 2)\n\n const feature = new Feature({\n geometry: new Point(fromLonLat([lon, lat])),\n weight: weight\n })\n features.push(feature)\n }\n return features\n }\n\n const vectorSource = new VectorSource({\n features: generateHeatmapData()\n })\n\n const heatmapLayer = new Heatmap({\n source: vectorSource,\n blur: 60, // 흐림 정도 증가\n radius: 60, // 점의 반경 증가\n weight: feature => feature.get('weight'), // 가중치 적용\n gradient: colors.map(c => `rgba(${c.join(',')})`), // 색상 적용\n opacity: 0.8\n })\n\n this.map = new Map({\n target: this.renderRoot.querySelector('#map') as HTMLElement,\n pixelRatio: Math.min(DEVICE_PIXEL_RATIO, 2),\n layers: [lightOSM, /*heatmapLayer, */ outlineLayer, labelOSM],\n view: new View({\n center: fromLonLat([127.5, 36.5]),\n zoom: 7.5\n })\n })\n\n this._addWeatherLayer()\n // this._addWindLayer()\n }\n\n private _addWindLayer() {\n if (this.windLayer) {\n this.map.removeLayer(this.windLayer)\n console.log('🚨 기존 날씨 레이어 제거')\n }\n\n const maxSpeed = 20\n\n const colorStops: (number | [number, number, number, number])[] = []\n for (let i = 0; i < colors.length; ++i) {\n colorStops.push((i * maxSpeed) / (colors.length - 1))\n colorStops.push(colors[i])\n }\n\n this.windLayer = new Flow({\n source: wind,\n maxSpeed,\n particles: 20000,\n style: {\n color: ['interpolate', ['linear'], ['get', 'speed'], ...colorStops]\n }\n })\n\n this.map.addLayer(this.windLayer)\n }\n\n private _addWeatherLayer() {\n if (this.weatherLayer) {\n this.map.removeLayer(this.weatherLayer)\n console.log('🚨 기존 날씨 레이어 제거')\n }\n\n // 날씨 타입별 최적 설정\n let opacity, blendMode\n\n switch (this.activeType) {\n case 'temperature':\n opacity = 0.75\n blendMode = 'normal'\n break\n case 'humidity':\n opacity = 0.65\n blendMode = 'multiply'\n break\n case 'wind':\n opacity = 0.8\n blendMode = 'screen'\n break\n case 'precipitation':\n opacity = 0.7\n blendMode = 'color-dodge'\n break\n default:\n opacity = 0.7\n blendMode = 'normal'\n }\n\n this.weatherLayer = new ImageLayer({\n source: new WebGLImageStatic({\n url: `/weather/map/${this.activeType}.png?refresh=${Date.now()}`, // 캐시 방지\n // 올바른 지구 투영 비율 사용\n imageExtent: [-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892],\n interpolation: true,\n projection: 'EPSG:3857'\n // opacity: opacity,\n // blendMode: blendMode\n }),\n opacity // WebGLImageStatic에서 투명도 처리\n })\n\n this.map.getLayers().insertAt(1, this.weatherLayer)\n\n console.log('🚨 날씨 레이어 추가', this.map.getLayers())\n }\n\n private _changeWeatherType(type: string) {\n if (this.activeType === type) return\n this.activeType = type\n this._addWeatherLayer()\n }\n\n private _refreshWeatherMap() {\n this._addWeatherLayer()\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"weather-page.js","sourceRoot":"","sources":["../../client/pages/weather-page.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { PageView } from '@operato/shell'\n\nimport Map from 'ol/Map.js'\nimport View from 'ol/View.js'\nimport TileLayer from 'ol/layer/Tile.js'\nimport { fromLonLat } from 'ol/proj.js'\nimport 'ol/ol.css'\nimport { MVT } from 'ol/format'\nimport { VectorTile, XYZ } from 'ol/source'\nimport VectorTileLayer from 'ol/layer/VectorTile'\nimport { Style, Stroke } from 'ol/style'\n\nimport { BaseWeatherLayer, TemperatureLayer, PrecipitationLayer, initializeWorkerSystem } from '@hyperviz/weather'\n\nimport { WindDataTileLayer } from '../ol-components/wind-data-tile-layer.js'\n\n// 통합 날씨 레이어 타입 (BaseWeatherLayer와 WindDataTileLayer 모두 포함)\ntype WeatherLayerType = BaseWeatherLayer | WindDataTileLayer\n\n@customElement('weather-page')\nexport class WeatherPage extends PageView {\n static get styles() {\n return css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .map-container {\n flex: 1;\n display: flex;\n position: relative;\n background-color: #f9f9f9;\n overflow: hidden;\n }\n\n #map {\n flex: 1;\n }\n\n .controls {\n position: absolute;\n top: 10px;\n right: 10px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n background: rgba(255, 255, 255, 0.8);\n padding: 15px;\n border-radius: 4px;\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n z-index: 10;\n }\n\n .weather-btn {\n cursor: pointer;\n padding: 8px 12px;\n background-color: #f0f0f0;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-weight: bold;\n transition: all 0.3s;\n }\n\n .weather-btn.active {\n background-color: #4281f5;\n color: white;\n border-color: #2d5ed9;\n }\n\n .refresh-btn {\n margin-top: 10px;\n cursor: pointer;\n padding: 8px 12px;\n background-color: #00c851;\n color: white;\n border: none;\n border-radius: 4px;\n font-weight: bold;\n transition: all 0.3s;\n }\n\n .refresh-btn:hover {\n background-color: #00a651;\n }\n `\n }\n\n @property({ type: String }) private activeType = 'temperature'\n @state() private map: Map | null = null\n @state() private weatherLayer: WeatherLayerType | null = null\n\n constructor() {\n super()\n }\n\n render() {\n return html`\n <div class=\"map-container\">\n <div id=\"map\"></div>\n\n <div class=\"controls\">\n <button\n class=\"weather-btn ${this.activeType === 'temperature' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('temperature')}\n >\n 온도\n </button>\n <button\n class=\"weather-btn ${this.activeType === 'wind' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('wind')}\n >\n 바람\n </button>\n <button\n class=\"weather-btn ${this.activeType === 'precipitation' ? 'active' : ''}\"\n @click=${() => this._changeWeatherType('precipitation')}\n >\n 강수량\n </button>\n <button class=\"refresh-btn\" @click=${this._refreshWeatherMap}>새로고침</button>\n </div>\n </div>\n `\n }\n\n connectedCallback(): void {\n super.connectedCallback()\n initializeWorkerSystem()\n requestAnimationFrame(() => {\n this._initMap()\n })\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback()\n if (this.weatherLayer) {\n try {\n this.weatherLayer.removeFromMap()\n this.weatherLayer.dispose()\n } catch (e) {\n console.error('Error disposing weather layer:', e)\n }\n }\n if (this.map) {\n this.map.dispose()\n }\n this.map = null\n this.weatherLayer = null\n }\n\n private _initMap() {\n const lightOSM = new TileLayer({\n source: new XYZ({\n url: 'https://{a-c}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',\n attributions: '© OpenStreetMap contributors, © CartoDB'\n }),\n background: 'transparent',\n opacity: 1\n })\n\n const labelOSM = new TileLayer({\n source: new XYZ({\n url: 'https://{a-c}.basemaps.cartocdn.com/dark_only_labels/{z}/{x}/{y}{r}.png'\n }),\n background: 'transparent',\n opacity: 1\n })\n\n const vectorTile = new VectorTile({\n format: new MVT({\n layerName: 'countries',\n layers: ['countries']\n }),\n url: `/geo/tiles/{z}/{x}/{y}.mvt`,\n maxZoom: 10,\n projection: 'EPSG:3857'\n })\n\n const outlineLayer = new VectorTileLayer({\n source: vectorTile,\n style: new Style({\n stroke: new Stroke({\n color: '#858585',\n // color: '#484848',\n width: 1\n })\n })\n })\n\n this.map = new Map({\n target: this.renderRoot.querySelector('#map') as HTMLElement,\n pixelRatio: Math.min(window.devicePixelRatio, 2),\n layers: [lightOSM, outlineLayer, labelOSM],\n view: new View({\n center: fromLonLat([126.9779692, 37.5662952]),\n zoom: 5\n })\n })\n\n this._addWeatherLayer()\n }\n\n private _addWeatherLayer() {\n if (!this.map) return\n\n switch (this.activeType) {\n case 'temperature':\n this.weatherLayer = new TemperatureLayer()\n break\n case 'wind':\n this.weatherLayer = new WindDataTileLayer()\n break\n case 'precipitation':\n this.weatherLayer = new PrecipitationLayer()\n break\n default:\n this.weatherLayer = new TemperatureLayer()\n }\n\n if (this.weatherLayer) {\n this.weatherLayer.addToMap(this.map)\n }\n }\n\n /**\n * 날씨 레이어를 변경하고 새 레이어를 맵에 추가\n */\n private _changeWeatherType(type: string) {\n if (this.activeType === type) return\n\n // 현재 활성 타입 저장\n const previousType = this.activeType\n // 새로운 타입으로 변경\n this.activeType = type\n\n console.log(`날씨 타입 변경 시작: ${previousType} -> ${type}`)\n\n // 이전 레이어가 있을 경우 처리\n if (this.map && this.weatherLayer) {\n // 맵 참조 저장\n const mapRef = this.map\n\n // 이전 레이어 참조 저장\n const oldLayer = this.weatherLayer\n // 렌더링 참조 제거\n this.weatherLayer = null\n\n // 이전 레이어 제거 처리\n try {\n console.log(`이전 레이어(${previousType}) 제거 시작`)\n\n // 1. 레이어 시각적으로 즉시 숨김 (특히 WindDataTileLayer 경우 중요)\n if (previousType === 'wind') {\n if (oldLayer['layer'] && typeof oldLayer['layer'].setVisible === 'function') {\n oldLayer['layer'].setVisible(false)\n }\n }\n\n // 2. 컴포넌트에서 참조 제거 (렌더링 사이클에서 제외)\n this.weatherLayer = null\n\n // 3. 비동기 처리: 렌더링 사이클이 완료된 후 실행\n requestAnimationFrame(() => {\n setTimeout(() => {\n try {\n // 레이어 참조가 남아있을 경우에만 제거 시도\n if (oldLayer) {\n oldLayer.removeFromMap()\n\n // 약간의 지연 후 자원 해제\n setTimeout(() => {\n try {\n oldLayer.dispose()\n console.log(`이전 레이어(${previousType}) 완전히 제거됨`)\n } catch (e) {\n console.warn('레이어 리소스 해제 중 오류:', e)\n }\n\n // 새 레이어 생성 시작\n this._addNewLayer(type, mapRef)\n }, 50) // dispose 지연\n } else {\n // 레이어 참조가 없는 경우 즉시 새 레이어 생성\n this._addNewLayer(type, mapRef)\n }\n } catch (e) {\n console.error('레이어 제거 중 오류 발생:', e)\n // 오류 발생해도 새 레이어 생성 시도\n this._addNewLayer(type, mapRef)\n }\n }, 100) // 레이어 제거 지연\n })\n } catch (e) {\n console.error('레이어 전환 중 오류:', e)\n // 에러 상태에서도 새 레이어 추가 시도\n this._addNewLayer(type, mapRef)\n }\n } else {\n // 기존 레이어가 없으면 바로 새 레이어 추가\n this._addWeatherLayer()\n }\n }\n\n /**\n * 새 레이어를 안전하게 추가하는 헬퍼 메소드\n */\n private _addNewLayer(type: string, mapRef: Map | null): void {\n // 타입이 바뀌지 않았는지 확인\n if (this.activeType !== type) {\n console.log(`타입이 변경되어 레이어 생성 취소: ${this.activeType}로 변경됨`)\n return\n }\n\n console.log(`새 레이어(${type}) 생성 시작`)\n\n try {\n // 맵 참조 확인\n if (!this.map && mapRef) {\n this.map = mapRef\n }\n\n if (this.map) {\n // 새 레이어 생성 및 맵에 추가\n this._addWeatherLayer()\n console.log(`새 레이어(${type}) 생성 완료`)\n } else {\n console.error('맵 참조 없음: 레이어를 추가할 수 없습니다')\n }\n } catch (e) {\n console.error('새 레이어 생성 중 오류:', e)\n }\n }\n\n private _refreshWeatherMap() {\n if (this.weatherLayer) {\n try {\n // 타입에 따라 적절한 메서드 호출\n if (this.activeType === 'wind') {\n ;(this.weatherLayer as WindDataTileLayer).updateLayer()\n } else {\n // @hyperviz/weather 레이어\n ;(this.weatherLayer as BaseWeatherLayer).setWeatherData([])\n }\n } catch (e) {\n console.error('Error refreshing weather layer:', e)\n }\n }\n }\n}\n"]}
|