mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-01 08:12:32 +00:00
progress
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import GPXMapLayers from '$lib/components/GPXMapLayers.svelte';
|
||||
import GPXMapLayers from '$lib/components/gpx-layer/GPXMapLayers.svelte';
|
||||
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||
import FileList from '$lib/components/FileList.svelte';
|
||||
import GPXData from '$lib/components/GPXData.svelte';
|
||||
|
@@ -231,16 +231,16 @@
|
||||
|
||||
$: if (chart && $settings) {
|
||||
let gpxFiles = new GPXFiles(get(fileOrder).filter((f) => $selectedFiles.has(f)));
|
||||
let data = gpxFiles.getTrackPointsAndStatistics();
|
||||
|
||||
// update data
|
||||
let trackPointsAndStatistics = gpxFiles.getTrackPointsAndStatistics();
|
||||
chart.data.datasets[0] = {
|
||||
label: $_('quantities.elevation'),
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
data: data.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(trackPointsAndStatistics.statistics.distance[index]),
|
||||
x: getConvertedDistance(data.point_statistics.distance[index]),
|
||||
y: point.ele ? getConvertedElevation(point.ele) : 0,
|
||||
slope: trackPointsAndStatistics.statistics.slope[index],
|
||||
slope: data.point_statistics.slope[index],
|
||||
surface: point.getSurface(),
|
||||
coordinates: point.getCoordinates()
|
||||
};
|
||||
@@ -251,10 +251,10 @@
|
||||
};
|
||||
chart.data.datasets[1] = {
|
||||
label: datasets.speed.getLabel(),
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
data: data.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(trackPointsAndStatistics.statistics.distance[index]),
|
||||
y: getConvertedVelocity(trackPointsAndStatistics.statistics.speed[index])
|
||||
x: getConvertedDistance(data.point_statistics.distance[index]),
|
||||
y: getConvertedVelocity(data.point_statistics.speed[index])
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
@@ -263,9 +263,9 @@
|
||||
};
|
||||
chart.data.datasets[2] = {
|
||||
label: datasets.hr.getLabel(),
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
data: data.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(trackPointsAndStatistics.statistics.distance[index]),
|
||||
x: getConvertedDistance(data.point_statistics.distance[index]),
|
||||
y: point.getHeartRate()
|
||||
};
|
||||
}),
|
||||
@@ -275,9 +275,9 @@
|
||||
};
|
||||
chart.data.datasets[3] = {
|
||||
label: datasets.cad.getLabel(),
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
data: data.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(trackPointsAndStatistics.statistics.distance[index]),
|
||||
x: getConvertedDistance(data.point_statistics.distance[index]),
|
||||
y: point.getCadence()
|
||||
};
|
||||
}),
|
||||
@@ -287,9 +287,9 @@
|
||||
};
|
||||
chart.data.datasets[4] = {
|
||||
label: datasets.atemp.getLabel(),
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
data: data.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(trackPointsAndStatistics.statistics.distance[index]),
|
||||
x: getConvertedDistance(data.point_statistics.distance[index]),
|
||||
y: getConvertedTemperature(point.getTemperature())
|
||||
};
|
||||
}),
|
||||
@@ -299,9 +299,9 @@
|
||||
};
|
||||
chart.data.datasets[5] = {
|
||||
label: datasets.power.getLabel(),
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
data: data.points.map((point, index) => {
|
||||
return {
|
||||
x: getConvertedDistance(trackPointsAndStatistics.statistics.distance[index]),
|
||||
x: getConvertedDistance(data.point_statistics.distance[index]),
|
||||
y: point.getPower()
|
||||
};
|
||||
}),
|
||||
@@ -310,7 +310,7 @@
|
||||
hidden: true
|
||||
};
|
||||
chart.options.scales.x['min'] = 0;
|
||||
chart.options.scales.x['max'] = getConvertedDistance(gpxFiles.statistics.distance.total);
|
||||
chart.options.scales.x['max'] = getConvertedDistance(data.statistics.distance.total);
|
||||
|
||||
// update units
|
||||
chart.options.scales.x.title.text = `${$_('quantities.distance')} (${getDistanceUnits()})`;
|
||||
|
@@ -3,9 +3,9 @@
|
||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||
import WithUnits from '$lib/components/WithUnits.svelte';
|
||||
|
||||
import { GPXStatistics } from 'gpx';
|
||||
import { GPXFiles, GPXStatistics } from 'gpx';
|
||||
|
||||
import { getFileStore, selectedFiles, settings } from '$lib/stores';
|
||||
import { selectedFiles, settings } from '$lib/stores';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
import { MoveDownRight, MoveUpRight, Ruler, Timer, Zap } from 'lucide-svelte';
|
||||
@@ -15,10 +15,7 @@
|
||||
let gpxData: GPXStatistics = new GPXStatistics();
|
||||
|
||||
function updateGPXData() {
|
||||
gpxData = new GPXStatistics();
|
||||
$selectedFiles.forEach((file) => {
|
||||
gpxData.mergeWith(file.statistics);
|
||||
});
|
||||
gpxData = new GPXFiles(Array.from(get(selectedFiles))).getStatistics();
|
||||
}
|
||||
|
||||
$: if ($selectedFiles) {
|
||||
@@ -47,24 +44,25 @@
|
||||
<Tooltip>
|
||||
<span slot="data" class="flex flex-row items-center">
|
||||
<Zap size="18" class="mr-1" />
|
||||
<WithUnits value={gpxData.speed.moving} type="speed" showUnits={false} /> /
|
||||
<WithUnits value={gpxData.speed.total} type="speed" />
|
||||
<WithUnits value={gpxData.speed.total} type="speed" showUnits={false} />
|
||||
<span class="mx-1">/</span>
|
||||
<WithUnits value={gpxData.speed.moving} type="speed" />
|
||||
</span>
|
||||
<span slot="tooltip"
|
||||
>{$settings.velocityUnits === 'speed' ? $_('quantities.speed') : $_('quantities.pace')} ({$_(
|
||||
'quantities.moving'
|
||||
)} / {$_('quantities.total')})</span
|
||||
'quantities.total'
|
||||
)} / {$_('quantities.moving')})</span
|
||||
>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<span slot="data" class="flex flex-row items-center">
|
||||
<Timer size="18" class="mr-1" />
|
||||
<WithUnits value={gpxData.time.moving} type="time" />
|
||||
<span class="mx-1">/</span>
|
||||
<WithUnits value={gpxData.time.total} type="time" />
|
||||
<span class="mx-1">/</span>
|
||||
<WithUnits value={gpxData.time.moving} type="time" />
|
||||
</span>
|
||||
<span slot="tooltip"
|
||||
>{$_('quantities.time')} ({$_('quantities.moving')} / {$_('quantities.total')})</span
|
||||
>{$_('quantities.time')} ({$_('quantities.total')} / {$_('quantities.moving')})</span
|
||||
>
|
||||
</Tooltip>
|
||||
</Card.Content>
|
||||
|
@@ -1,201 +0,0 @@
|
||||
<script context="module" lang="ts">
|
||||
let id = 0;
|
||||
function getLayerId() {
|
||||
return `gpx-${id++}`;
|
||||
}
|
||||
|
||||
let defaultWeight = 6;
|
||||
let defaultOpacity = 1;
|
||||
|
||||
const colors = [
|
||||
'#ff0000',
|
||||
'#0000ff',
|
||||
'#46e646',
|
||||
'#00ccff',
|
||||
'#ff9900',
|
||||
'#ff00ff',
|
||||
'#ffff32',
|
||||
'#288228',
|
||||
'#9933ff',
|
||||
'#50f0be',
|
||||
'#8c645a'
|
||||
];
|
||||
|
||||
const colorCount: { [key: string]: number } = {};
|
||||
for (let color of colors) {
|
||||
colorCount[color] = 0;
|
||||
}
|
||||
|
||||
// Get the color with the least amount of uses
|
||||
function getColor() {
|
||||
let color = colors.reduce((a, b) => (colorCount[a] <= colorCount[b] ? a : b));
|
||||
colorCount[color]++;
|
||||
return color;
|
||||
}
|
||||
|
||||
function decrementColor(color: string) {
|
||||
colorCount[color]--;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { GPXFile } from 'gpx';
|
||||
import { map, selectedFiles, selectFiles, files } from '$lib/stores';
|
||||
import { get, type Writable } from 'svelte/store';
|
||||
|
||||
export let file: Writable<GPXFile>;
|
||||
|
||||
let layerId = getLayerId();
|
||||
let layerColor = getColor();
|
||||
|
||||
file.update((f) => {
|
||||
Object.defineProperty(f, 'layerId', {
|
||||
value: layerId,
|
||||
writable: false
|
||||
});
|
||||
return f;
|
||||
});
|
||||
|
||||
function selectOnClick(e: any) {
|
||||
if (e.originalEvent.shiftKey) {
|
||||
get(selectFiles).addSelect(get(file));
|
||||
} else {
|
||||
get(selectFiles).select(get(file));
|
||||
}
|
||||
}
|
||||
|
||||
function toPointerCursor() {
|
||||
if ($map) {
|
||||
$map.getCanvas().style.cursor = 'pointer';
|
||||
}
|
||||
}
|
||||
|
||||
function toDefaultCursor() {
|
||||
if ($map) {
|
||||
$map.getCanvas().style.cursor = '';
|
||||
}
|
||||
}
|
||||
|
||||
function extendGeoJSON(data: any) {
|
||||
for (let feature of data.features) {
|
||||
if (!feature.properties.color) {
|
||||
feature.properties.color = layerColor;
|
||||
}
|
||||
if (!feature.properties.weight) {
|
||||
feature.properties.weight = defaultWeight;
|
||||
}
|
||||
if (!feature.properties.opacity) {
|
||||
feature.properties.opacity = defaultOpacity;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function addGPXLayer() {
|
||||
if ($map) {
|
||||
if (!$map.getSource(layerId)) {
|
||||
let data = extendGeoJSON($file.toGeoJSON());
|
||||
|
||||
$map.addSource(layerId, {
|
||||
type: 'geojson',
|
||||
data
|
||||
});
|
||||
}
|
||||
if (!$map.getLayer(layerId)) {
|
||||
$map.addLayer({
|
||||
id: layerId,
|
||||
type: 'line',
|
||||
source: layerId,
|
||||
layout: {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round'
|
||||
},
|
||||
paint: {
|
||||
'line-color': ['get', 'color'],
|
||||
'line-width': ['get', 'weight'],
|
||||
'line-opacity': ['get', 'opacity']
|
||||
}
|
||||
});
|
||||
|
||||
$map.on('click', layerId, selectOnClick);
|
||||
$map.on('mouseenter', layerId, toPointerCursor);
|
||||
$map.on('mouseleave', layerId, toDefaultCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($selectedFiles.has(get(file))) {
|
||||
if ($map) {
|
||||
$map.moveLayer(layerId);
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($map) {
|
||||
let source = $map.getSource(layerId);
|
||||
if (source) {
|
||||
source.setData(extendGeoJSON($file.toGeoJSON()));
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
addGPXLayer();
|
||||
if ($map) {
|
||||
if ($files.length == 1) {
|
||||
$map.fitBounds(
|
||||
[get(file).statistics.bounds.southWest, get(file).statistics.bounds.northEast],
|
||||
{
|
||||
padding: 60,
|
||||
linear: true,
|
||||
easing: () => 1
|
||||
}
|
||||
);
|
||||
} else {
|
||||
let mapBounds = $map.getBounds();
|
||||
if (
|
||||
mapBounds.contains(get(file).statistics.bounds.southWest) &&
|
||||
mapBounds.contains(get(file).statistics.bounds.northEast) &&
|
||||
mapBounds.contains([
|
||||
get(file).statistics.bounds.southWest.lon,
|
||||
get(file).statistics.bounds.northEast.lat
|
||||
]) &&
|
||||
mapBounds.contains([
|
||||
get(file).statistics.bounds.northEast.lon,
|
||||
get(file).statistics.bounds.southWest.lat
|
||||
])
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$map.fitBounds(
|
||||
$map
|
||||
.getBounds()
|
||||
.extend([
|
||||
get(file).statistics.bounds.southWest.lon,
|
||||
get(file).statistics.bounds.southWest.lat,
|
||||
get(file).statistics.bounds.northEast.lon,
|
||||
get(file).statistics.bounds.northEast.lat
|
||||
]),
|
||||
{
|
||||
padding: 60
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$map.on('style.load', addGPXLayer);
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if ($map) {
|
||||
$map.off('click', layerId, selectOnClick);
|
||||
$map.off('mouseenter', layerId, toPointerCursor);
|
||||
$map.off('mouseleave', layerId, toDefaultCursor);
|
||||
$map.off('style.load', addGPXLayer);
|
||||
|
||||
$map.removeLayer(layerId);
|
||||
$map.removeSource(layerId);
|
||||
}
|
||||
decrementColor(layerColor);
|
||||
});
|
||||
</script>
|
@@ -1,9 +0,0 @@
|
||||
<script lang="ts">
|
||||
import GPXMapLayer from './GPXMapLayer.svelte';
|
||||
|
||||
import { files } from '$lib/stores';
|
||||
</script>
|
||||
|
||||
{#each $files as file}
|
||||
<GPXMapLayer {file} />
|
||||
{/each}
|
29
website/src/lib/components/gpx-layer/GPXMapLayers.svelte
Normal file
29
website/src/lib/components/gpx-layer/GPXMapLayers.svelte
Normal file
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { map, files, selectedFiles, getFileStore } from '$lib/stores';
|
||||
import type { GPXFile } from 'gpx';
|
||||
import { GPXMapLayer } from './GPXMapLayers';
|
||||
import { get, type Writable } from 'svelte/store';
|
||||
|
||||
let gpxLayers: Map<Writable<GPXFile>, GPXMapLayer> = new Map();
|
||||
|
||||
$: if ($map) {
|
||||
gpxLayers.forEach((layer, file) => {
|
||||
if (!get(files).includes(file)) {
|
||||
layer.remove();
|
||||
gpxLayers.delete(file);
|
||||
}
|
||||
});
|
||||
$files.forEach((file) => {
|
||||
if (!gpxLayers.has(file)) {
|
||||
gpxLayers.set(file, new GPXMapLayer(get(map), file));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$: $selectedFiles.forEach((file) => {
|
||||
let fileStore = getFileStore(file);
|
||||
if (gpxLayers.has(fileStore)) {
|
||||
gpxLayers.get(fileStore)?.moveToFront();
|
||||
}
|
||||
});
|
||||
</script>
|
158
website/src/lib/components/gpx-layer/GPXMapLayers.ts
Normal file
158
website/src/lib/components/gpx-layer/GPXMapLayers.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import type { GPXFile } from "gpx";
|
||||
import { map, selectFiles } from "$lib/stores";
|
||||
import { get, type Writable } from "svelte/store";
|
||||
import type mapboxgl from "mapbox-gl";
|
||||
|
||||
let id = 0;
|
||||
function getLayerId() {
|
||||
return `gpx-${id++}`;
|
||||
}
|
||||
|
||||
let defaultWeight = 6;
|
||||
let defaultOpacity = 1;
|
||||
|
||||
const colors = [
|
||||
'#ff0000',
|
||||
'#0000ff',
|
||||
'#46e646',
|
||||
'#00ccff',
|
||||
'#ff9900',
|
||||
'#ff00ff',
|
||||
'#ffff32',
|
||||
'#288228',
|
||||
'#9933ff',
|
||||
'#50f0be',
|
||||
'#8c645a'
|
||||
];
|
||||
|
||||
const colorCount: { [key: string]: number } = {};
|
||||
for (let color of colors) {
|
||||
colorCount[color] = 0;
|
||||
}
|
||||
|
||||
// Get the color with the least amount of uses
|
||||
function getColor() {
|
||||
let color = colors.reduce((a, b) => (colorCount[a] <= colorCount[b] ? a : b));
|
||||
colorCount[color]++;
|
||||
return color;
|
||||
}
|
||||
|
||||
function decrementColor(color: string) {
|
||||
colorCount[color]--;
|
||||
}
|
||||
|
||||
export class GPXMapLayer {
|
||||
map: mapboxgl.Map;
|
||||
file: Writable<GPXFile>;
|
||||
layerId: string;
|
||||
layerColor: string;
|
||||
unsubscribe: () => void;
|
||||
|
||||
constructor(map: mapboxgl.Map, file: Writable<GPXFile>) {
|
||||
this.map = map;
|
||||
this.file = file;
|
||||
this.layerId = getLayerId();
|
||||
this.layerColor = getColor();
|
||||
this.unsubscribe = file.subscribe(this.updateData.bind(this));
|
||||
|
||||
get(this.file)._data = {
|
||||
layerId: this.layerId,
|
||||
layerColor: this.layerColor
|
||||
};
|
||||
|
||||
this.add();
|
||||
this.map.on('style.load', this.add.bind(this));
|
||||
}
|
||||
|
||||
add() {
|
||||
if (!this.map.getSource(this.layerId)) {
|
||||
let data = this.getGeoJSON();
|
||||
|
||||
this.map.addSource(this.layerId, {
|
||||
type: 'geojson',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.map.getLayer(this.layerId)) {
|
||||
this.map.addLayer({
|
||||
id: this.layerId,
|
||||
type: 'line',
|
||||
source: this.layerId,
|
||||
layout: {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round'
|
||||
},
|
||||
paint: {
|
||||
'line-color': ['get', 'color'],
|
||||
'line-width': ['get', 'weight'],
|
||||
'line-opacity': ['get', 'opacity']
|
||||
}
|
||||
});
|
||||
|
||||
this.map.on('click', this.layerId, this.selectOnClick.bind(this));
|
||||
this.map.on('mouseenter', this.layerId, toPointerCursor);
|
||||
this.map.on('mouseleave', this.layerId, toDefaultCursor);
|
||||
}
|
||||
}
|
||||
|
||||
updateData() {
|
||||
let source = this.map.getSource(this.layerId);
|
||||
if (source) {
|
||||
source.setData(this.getGeoJSON());
|
||||
}
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.map.off('click', this.layerId, this.selectOnClick.bind(this));
|
||||
this.map.off('mouseenter', this.layerId, toPointerCursor);
|
||||
this.map.off('mouseleave', this.layerId, toDefaultCursor);
|
||||
this.map.off('style.load', this.add.bind(this));
|
||||
|
||||
this.map.removeLayer(this.layerId);
|
||||
this.map.removeSource(this.layerId);
|
||||
|
||||
this.unsubscribe();
|
||||
|
||||
decrementColor(this.layerColor);
|
||||
}
|
||||
|
||||
moveToFront() {
|
||||
this.map.moveLayer(this.layerId);
|
||||
}
|
||||
|
||||
selectOnClick(e: any) {
|
||||
if (e.originalEvent.shiftKey) {
|
||||
get(selectFiles).addSelect(get(this.file));
|
||||
} else {
|
||||
get(selectFiles).select(get(this.file));
|
||||
}
|
||||
}
|
||||
|
||||
getGeoJSON(): GeoJSON.FeatureCollection {
|
||||
let data = get(this.file).toGeoJSON();
|
||||
for (let feature of data.features) {
|
||||
if (!feature.properties) {
|
||||
feature.properties = {};
|
||||
}
|
||||
if (!feature.properties.color) {
|
||||
feature.properties.color = this.layerColor;
|
||||
}
|
||||
if (!feature.properties.weight) {
|
||||
feature.properties.weight = defaultWeight;
|
||||
}
|
||||
if (!feature.properties.opacity) {
|
||||
feature.properties.opacity = defaultOpacity;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
function toPointerCursor() {
|
||||
get(map).getCanvas().style.cursor = 'pointer';
|
||||
}
|
||||
|
||||
function toDefaultCursor() {
|
||||
get(map).getCanvas().style.cursor = '';
|
||||
}
|
@@ -106,7 +106,7 @@
|
||||
$map.off('move', toggleMarkersForZoomLevelAndBounds);
|
||||
$map.off('click', extendFile);
|
||||
if (file) {
|
||||
$map.off('mouseover', file.layerId, showInsertableMarker);
|
||||
$map.off('mouseover', file._data.layerId, showInsertableMarker);
|
||||
}
|
||||
if (insertableMarker) {
|
||||
insertableMarker.remove();
|
||||
@@ -115,7 +115,7 @@
|
||||
kdbush = null;
|
||||
}
|
||||
|
||||
$: if ($selectedFiles.size == 1 && $map) {
|
||||
$: if ($selectedFiles.size == 1) {
|
||||
let selectedFile = $selectedFiles.values().next().value;
|
||||
|
||||
if (selectedFile !== file) {
|
||||
@@ -124,6 +124,9 @@
|
||||
} else {
|
||||
// update markers
|
||||
}
|
||||
} else {
|
||||
clean();
|
||||
file = null;
|
||||
}
|
||||
|
||||
$: if ($map && file) {
|
||||
@@ -140,7 +143,7 @@
|
||||
$map.on('zoom', toggleMarkersForZoomLevelAndBounds);
|
||||
$map.on('move', toggleMarkersForZoomLevelAndBounds);
|
||||
$map.on('click', extendFile);
|
||||
$map.on('mouseover', file.layerId, showInsertableMarker);
|
||||
$map.on('mouseover', file._data.layerId, showInsertableMarker);
|
||||
|
||||
let points = file.getTrackPoints();
|
||||
|
||||
@@ -152,8 +155,6 @@
|
||||
kdbush.finish();
|
||||
end = performance.now();
|
||||
console.log('Time to create kdbush: ' + (end - start) + 'ms');
|
||||
} else {
|
||||
clean();
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
|
@@ -68,10 +68,32 @@ export function triggerFileInput() {
|
||||
}
|
||||
|
||||
export async function loadFiles(list: FileList) {
|
||||
let bounds = new mapboxgl.LngLatBounds();
|
||||
let mapBounds = new mapboxgl.LngLatBounds([180, 90, -180, -90]);
|
||||
if (get(files).length > 0) {
|
||||
mapBounds = get(map)?.getBounds() ?? mapBounds;
|
||||
bounds.extend(mapBounds);
|
||||
}
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let file = await loadFile(list[i]);
|
||||
if (i == 0 && file) {
|
||||
get(selectFiles).select(get(file));
|
||||
if (file) {
|
||||
if (i == 0) {
|
||||
get(selectFiles).select(get(file));
|
||||
}
|
||||
|
||||
let fileBounds = get(file).getStatistics().bounds;
|
||||
bounds.extend(fileBounds.southWest);
|
||||
bounds.extend(fileBounds.northEast);
|
||||
bounds.extend([fileBounds.southWest.lon, fileBounds.northEast.lat]);
|
||||
bounds.extend([fileBounds.northEast.lon, fileBounds.southWest.lat]);
|
||||
|
||||
if (!mapBounds.contains(bounds.getSouthWest()) || !mapBounds.contains(bounds.getNorthEast()) || !mapBounds.contains(bounds.getSouthEast()) || !mapBounds.contains(bounds.getNorthWest())) {
|
||||
get(map)?.fitBounds(bounds, {
|
||||
padding: 80,
|
||||
linear: true,
|
||||
easing: () => 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user