From e428f555809960aa80f1b8fe60910629a7c95894 Mon Sep 17 00:00:00 2001 From: Vasilisk9812 Date: Wed, 2 Jul 2025 20:44:12 +0900 Subject: [PATCH] Pre timeControl --- package-lock.json | 15 ++ package.json | 1 + src/routes/TimeLine.svelte | 215 ---------------------------- src/routes/WindVisualisation.svelte | 76 +++++++++- 4 files changed, 85 insertions(+), 222 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc9ed4d..153df77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "js-cookie": "^3.0.5", "leaflet": "^1.9.4", "leaflet-heatmap": "^1.0.0", + "leaflet-timedimension": "^1.1.1", "leaflet-velocity": "^2.1.4", "leaflet.heat": "^0.2.0" }, @@ -1078,6 +1079,11 @@ "@types/estree": "^1.0.6" } }, + "node_modules/iso8601-js-period": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/iso8601-js-period/-/iso8601-js-period-0.2.1.tgz", + "integrity": "sha512-iDyz2TQFBd5WhCZjruOwHj01JkQGu7YbVLCVdpA7lCGEcBzE3ffCPAhLh/M8TAp//kCixPpYN4XU54WHCxvD2Q==" + }, "node_modules/js-cookie": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", @@ -1109,6 +1115,15 @@ "leaflet": "*" } }, + "node_modules/leaflet-timedimension": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/leaflet-timedimension/-/leaflet-timedimension-1.1.1.tgz", + "integrity": "sha512-ejXldN94veRsWka1vpC+4rbH+2+3d3ztn2xYx4jcXtjYDrKC/sNnoqCmyH2UEYIy51PI2851aI2k8uGdOEbhlw==", + "dependencies": { + "iso8601-js-period": "^0.2.1", + "leaflet": "~0.7.4 || ~1" + } + }, "node_modules/leaflet-velocity": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/leaflet-velocity/-/leaflet-velocity-2.1.4.tgz", diff --git a/package.json b/package.json index 5a20907..1730ef5 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "js-cookie": "^3.0.5", "leaflet": "^1.9.4", "leaflet-heatmap": "^1.0.0", + "leaflet-timedimension": "^1.1.1", "leaflet-velocity": "^2.1.4", "leaflet.heat": "^0.2.0" } diff --git a/src/routes/TimeLine.svelte b/src/routes/TimeLine.svelte index 94dddeb..e69de29 100644 --- a/src/routes/TimeLine.svelte +++ b/src/routes/TimeLine.svelte @@ -1,215 +0,0 @@ - - - -
-
- - - - - - -
- {formatTime(currentHour)} -
-
- - dispatchTimeUpdate()} - class="timeline-slider" - /> - -
- {#each Array(Math.floor(totalHours / updateInterval) + 1) as _, i} -
{ - currentHour = i * updateInterval; - dispatchTimeUpdate(); - }} - > - {i * updateInterval % 24 === 0 ? `День ${Math.floor(i * updateInterval / 24) + 1}` : ''} -
- {/each} -
-
- - \ No newline at end of file diff --git a/src/routes/WindVisualisation.svelte b/src/routes/WindVisualisation.svelte index 713cde8..007b417 100644 --- a/src/routes/WindVisualisation.svelte +++ b/src/routes/WindVisualisation.svelte @@ -5,10 +5,13 @@ import 'leaflet-velocity/dist/leaflet-velocity.css'; import 'leaflet-velocity/dist/leaflet-velocity'; import 'leaflet.heat'; + import 'leaflet-timedimension'; export let map; // принимаем карту из родительского компонента export let windData; + let timeDimension; + let timeDimensionControl; let velocityLayer; let heatLayer; let legend; @@ -18,6 +21,22 @@ let showVectors = true; let layerControl; + // Преобразование testVelo.json в формат timeData + const prepareTimeData = (windData) => { + if (!windData || windData.length < 2) return {}; + + // Используем дату из header или текущую дату, если не указана + const refTime = windData[0]?.header?.refTime || new Date().toISOString(); + + return { + [refTime]: { + u: windData[0].data, // U-компонента (первый объект в массиве) + v: windData[1].data // V-компонента (второй объект) + } + }; + }; + + // Функция для нормализации данных тепловой карты const prepareHeatData = (windData) => { if (!windData || windData.length < 2) { @@ -55,9 +74,9 @@ // Вычисляем координаты для текущей точки const y = Math.floor(i / nx); const x = i % nx; - const lat = la1 - y * dy; - const lng = lo1 + x * dx; - + let lat = la1 - y * dy; + let lng = lo1 + x * dx; + if (lng >= 180) lng -= 360; heatData.push([lat, lng, speed]); maxSpeed = Math.max(maxSpeed, speed); } @@ -82,9 +101,9 @@ try { return L.heatLayer(data, { - radius: 20, // Увеличьте радиус для глобальной карты - blur: 15, - maxZoom: 10, + radius: 8, // Увеличьте радиус для глобальной карты + blur: 20, + // maxZoom: 10, minOpacity: 0.7, gradient: { 0.1: 'blue', @@ -189,7 +208,50 @@ }; onMount(() => { - updateLayers(); + if (!map) return; + + // 1. Настройка TimeDimension (добавьте эти строки в начале) + // L.TimeDimension.Util.setProxy('https://your-proxy.com/?url='); // Для загрузки больших данных + L.TimeDimension.Util.setCacheLimit(10); // Лимит кэшированных кадров + + // 1. Подготовка данных + const timeData = prepareTimeData(windData); + const firstTime = Object.keys(timeData)[0]; + + // Инициализация TimeDimension + timeDimension = new L.TimeDimension({ + period: "PT1H", // Интервал 1 час + timeInterval: '${firstTime}/${firstTime}', + }); + + // Добавляем контролы времени + timeDimensionControl = new L.Control.TimeDimension({ + timeDimension, + position: 'bottomleft', + // autoPlay: true, + playerOptions: { + // transitionTime: 1000, + loop: false, + minBufferReady: -1 + } + }); + map.addControl(timeDimensionControl); + + // 4. Создание слоев + const velocityLayer = L.timeDimension.layer.windVelocity({ + displayValues: true, + data: timeData, + displayOptions: { + velocityType: 'Wind Speed', + position: 'bottomleft' + } + }).addTo(map); + + // 5. Тепловая карта (адаптируйте под ваш формат) + const heatLayer = L.timeDimension.layer.heat({ + radius: 15, + data: prepareTimeHeatData(timeData) + }).addTo(map); }); onDestroy(() => {