mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-11-04 13:31:13 +00:00
statistics
This commit is contained in:
@@ -7,23 +7,26 @@
|
|||||||
|
|
||||||
import { i18n } from '$lib/i18n.svelte';
|
import { i18n } from '$lib/i18n.svelte';
|
||||||
import type { GPXStatistics } from 'gpx';
|
import type { GPXStatistics } from 'gpx';
|
||||||
import type { Writable } from 'svelte/store';
|
import type { Readable } from 'svelte/store';
|
||||||
import { settings } from '$lib/db';
|
import { settings } from '$lib/logic/settings';
|
||||||
|
|
||||||
export let gpxStatistics: Writable<GPXStatistics>;
|
|
||||||
export let slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined>;
|
|
||||||
export let orientation: 'horizontal' | 'vertical';
|
|
||||||
export let panelSize: number;
|
|
||||||
|
|
||||||
const { velocityUnits } = settings;
|
const { velocityUnits } = settings;
|
||||||
|
|
||||||
let statistics: GPXStatistics;
|
let {
|
||||||
|
gpxStatistics,
|
||||||
|
slicedGPXStatistics,
|
||||||
|
orientation,
|
||||||
|
panelSize,
|
||||||
|
}: {
|
||||||
|
gpxStatistics: Readable<GPXStatistics>;
|
||||||
|
slicedGPXStatistics: Readable<[GPXStatistics, number, number] | undefined>;
|
||||||
|
orientation: 'horizontal' | 'vertical';
|
||||||
|
panelSize: number;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
$: if ($slicedGPXStatistics !== undefined) {
|
let statistics = $derived(
|
||||||
statistics = $slicedGPXStatistics[0];
|
$slicedGPXStatistics !== undefined ? $slicedGPXStatistics[0] : $gpxStatistics
|
||||||
} else {
|
);
|
||||||
statistics = $gpxStatistics;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Card.Root
|
<Card.Root
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
} from './file-list';
|
} from './file-list';
|
||||||
import { i18n } from '$lib/i18n.svelte';
|
import { i18n } from '$lib/i18n.svelte';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import type { GPXFileWithStatistics } from '$lib/logic/statistics';
|
import type { GPXFileWithStatistics } from '$lib/logic/statistics-tree';
|
||||||
import { selection } from '$lib/logic/selection';
|
import { selection } from '$lib/logic/selection';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
type ListItem,
|
type ListItem,
|
||||||
} from './file-list';
|
} from './file-list';
|
||||||
import { isMac } from '$lib/utils';
|
import { isMac } from '$lib/utils';
|
||||||
import type { GPXFileWithStatistics } from '$lib/logic/statistics';
|
import type { GPXFileWithStatistics } from '$lib/logic/statistics-tree';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import { getFileIds, moveItems } from '$lib/logic/file-actions';
|
import { getFileIds, moveItems } from '$lib/logic/file-actions';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import type { Readable } from 'svelte/store';
|
import type { Readable } from 'svelte/store';
|
||||||
import { ListFileItem } from './file-list';
|
import { ListFileItem } from './file-list';
|
||||||
import type { GPXFileWithStatistics } from '$lib/logic/statistics';
|
import type { GPXFileWithStatistics } from '$lib/logic/statistics-tree';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
file,
|
file,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
import { selectedWaypoint } from '$lib/components/toolbar/tools/waypoint/waypoint';
|
import { selectedWaypoint } from '$lib/components/toolbar/tools/waypoint/waypoint';
|
||||||
import { MapPin, Square } from 'lucide-static';
|
import { MapPin, Square } from 'lucide-static';
|
||||||
import { getSymbolKey, symbols } from '$lib/assets/symbols';
|
import { getSymbolKey, symbols } from '$lib/assets/symbols';
|
||||||
import type { GPXFileWithStatistics } from '$lib/logic/statistics';
|
import type { GPXFileWithStatistics } from '$lib/logic/statistics-tree';
|
||||||
import { selection } from '$lib/logic/selection';
|
import { selection } from '$lib/logic/selection';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import { currentTool, Tool } from '$lib/components/toolbar/tools';
|
import { currentTool, Tool } from '$lib/components/toolbar/tools';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
ListTrackSegmentItem,
|
ListTrackSegmentItem,
|
||||||
} from '$lib/components/file-list/file-list';
|
} from '$lib/components/file-list/file-list';
|
||||||
import { getClosestLinePoint, resetCursor, setGrabbingCursor } from '$lib/utils';
|
import { getClosestLinePoint, resetCursor, setGrabbingCursor } from '$lib/utils';
|
||||||
import type { GPXFileWithStatistics } from '$lib/logic/statistics';
|
import type { GPXFileWithStatistics } from '$lib/logic/statistics-tree';
|
||||||
|
|
||||||
// const { streetViewSource } = settings;
|
// const { streetViewSource } = settings;
|
||||||
export const canChangeStart = writable(false);
|
export const canChangeStart = writable(false);
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import { updateAnchorPoints } from '$lib/components/toolbar/tools/routing/Simpli
|
|||||||
import { db, type Database } from '$lib/db';
|
import { db, type Database } from '$lib/db';
|
||||||
import { liveQuery } from 'dexie';
|
import { liveQuery } from 'dexie';
|
||||||
import { GPXFile } from 'gpx';
|
import { GPXFile } from 'gpx';
|
||||||
import { GPXStatisticsTree, type GPXFileWithStatistics } from '$lib/logic/statistics';
|
import { GPXStatisticsTree, type GPXFileWithStatistics } from '$lib/logic/statistics-tree';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import { get, writable, type Subscriber, type Writable } from 'svelte/store';
|
import { get, writable, type Subscriber, type Writable } from 'svelte/store';
|
||||||
|
|
||||||
// Observe a single file from the database, and maintain its statistics
|
// Observe a single file from the database, and maintain its statistics
|
||||||
class GPXFileState {
|
export class GPXFileState {
|
||||||
private _file: Writable<GPXFileWithStatistics | undefined>;
|
private _file: Writable<GPXFileWithStatistics | undefined>;
|
||||||
private _subscription: { unsubscribe: () => void } | undefined;
|
private _subscription: { unsubscribe: () => void } | undefined;
|
||||||
|
|
||||||
@@ -119,6 +119,10 @@ export class GPXFileStateCollection {
|
|||||||
return get(this._files).size;
|
return get(this._files).size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFileState(fileId: string): GPXFileState | undefined {
|
||||||
|
return get(this._files).get(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
getFile(fileId: string): GPXFile | undefined {
|
getFile(fileId: string): GPXFile | undefined {
|
||||||
let fileState = get(this._files).get(fileId);
|
let fileState = get(this._files).get(fileId);
|
||||||
return fileState?.file;
|
return fileState?.file;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
import { fileStateCollection } from '$lib/logic/file-state';
|
import { fileStateCollection } from '$lib/logic/file-state';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import type { GPXFile } from 'gpx';
|
import type { GPXFile } from 'gpx';
|
||||||
import { get, writable, type Writable } from 'svelte/store';
|
import { get, writable, type Readable, type Writable } from 'svelte/store';
|
||||||
import { SelectionTreeType } from '$lib/logic/selection-tree';
|
import { SelectionTreeType } from '$lib/logic/selection-tree';
|
||||||
|
|
||||||
export class Selection {
|
export class Selection {
|
||||||
@@ -203,11 +203,11 @@ export class Selection {
|
|||||||
this._cut.set(false);
|
this._cut.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
get copied(): ListItem[] | undefined {
|
get copied(): Readable<ListItem[] | undefined> {
|
||||||
return this._copied;
|
return this._copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
get cut(): boolean {
|
get cut(): Readable<boolean> {
|
||||||
return this._cut;
|
return this._cut;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ export function applyToOrderedItemsFromFile(
|
|||||||
callback: (fileId: string, level: ListLevel | undefined, items: ListItem[]) => void,
|
callback: (fileId: string, level: ListLevel | undefined, items: ListItem[]) => void,
|
||||||
reverse: boolean = true
|
reverse: boolean = true
|
||||||
) {
|
) {
|
||||||
settings.fileOrder.value.forEach((fileId) => {
|
get(settings.fileOrder).forEach((fileId) => {
|
||||||
let level: ListLevel | undefined = undefined;
|
let level: ListLevel | undefined = undefined;
|
||||||
let items: ListItem[] = [];
|
let items: ListItem[] = [];
|
||||||
selectedItems.forEach((item) => {
|
selectedItems.forEach((item) => {
|
||||||
|
|||||||
46
website/src/lib/logic/statistics-tree.ts
Normal file
46
website/src/lib/logic/statistics-tree.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { ListItem, ListLevel } from '$lib/components/file-list/file-list';
|
||||||
|
import { GPXFile, GPXStatistics, type Track } from 'gpx';
|
||||||
|
|
||||||
|
export class GPXStatisticsTree {
|
||||||
|
level: ListLevel;
|
||||||
|
statistics: {
|
||||||
|
[key: string]: GPXStatisticsTree | GPXStatistics;
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
constructor(element: GPXFile | Track) {
|
||||||
|
if (element instanceof GPXFile) {
|
||||||
|
this.level = ListLevel.FILE;
|
||||||
|
element.children.forEach((child, index) => {
|
||||||
|
this.statistics[index] = new GPXStatisticsTree(child);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.level = ListLevel.TRACK;
|
||||||
|
element.children.forEach((child, index) => {
|
||||||
|
this.statistics[index] = child.getStatistics();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatisticsFor(item: ListItem): GPXStatistics {
|
||||||
|
let statistics = new GPXStatistics();
|
||||||
|
let id = item.getIdAtLevel(this.level);
|
||||||
|
if (id === undefined || id === 'waypoints') {
|
||||||
|
Object.keys(this.statistics).forEach((key) => {
|
||||||
|
if (this.statistics[key] instanceof GPXStatistics) {
|
||||||
|
statistics.mergeWith(this.statistics[key]);
|
||||||
|
} else {
|
||||||
|
statistics.mergeWith(this.statistics[key].getStatisticsFor(item));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let child = this.statistics[id];
|
||||||
|
if (child instanceof GPXStatistics) {
|
||||||
|
statistics.mergeWith(child);
|
||||||
|
} else if (child !== undefined) {
|
||||||
|
statistics.mergeWith(child.getStatisticsFor(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return statistics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type GPXFileWithStatistics = { file: GPXFile; statistics: GPXStatisticsTree };
|
||||||
@@ -1,46 +1,80 @@
|
|||||||
import { ListItem, ListLevel } from '$lib/components/file-list/file-list';
|
import { selection } from '$lib/logic/selection';
|
||||||
import { GPXFile, GPXStatistics, type Track } from 'gpx';
|
import { GPXStatistics } from 'gpx';
|
||||||
|
import { fileStateCollection, GPXFileState } from '$lib/logic/file-state';
|
||||||
|
import {
|
||||||
|
ListFileItem,
|
||||||
|
ListWaypointItem,
|
||||||
|
ListWaypointsItem,
|
||||||
|
} from '$lib/components/file-list/file-list';
|
||||||
|
import { get, writable, type Writable } from 'svelte/store';
|
||||||
|
|
||||||
export class GPXStatisticsTree {
|
export class SelectedGPXStatistics {
|
||||||
level: ListLevel;
|
private _statistics: Writable<GPXStatistics>;
|
||||||
statistics: {
|
private _files: Map<
|
||||||
[key: string]: GPXStatisticsTree | GPXStatistics;
|
string,
|
||||||
} = {};
|
{
|
||||||
|
file: GPXFileState;
|
||||||
constructor(element: GPXFile | Track) {
|
unsubscribe: () => void;
|
||||||
if (element instanceof GPXFile) {
|
|
||||||
this.level = ListLevel.FILE;
|
|
||||||
element.children.forEach((child, index) => {
|
|
||||||
this.statistics[index] = new GPXStatisticsTree(child);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.level = ListLevel.TRACK;
|
|
||||||
element.children.forEach((child, index) => {
|
|
||||||
this.statistics[index] = child.getStatistics();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._statistics = writable(new GPXStatistics());
|
||||||
|
this._files = new Map();
|
||||||
|
selection.subscribe(() => this.update());
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatisticsFor(item: ListItem): GPXStatistics {
|
subscribe(run: (value: GPXStatistics) => void, invalidate?: (value?: GPXStatistics) => void) {
|
||||||
|
return this._statistics.subscribe(run, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
let statistics = new GPXStatistics();
|
let statistics = new GPXStatistics();
|
||||||
let id = item.getIdAtLevel(this.level);
|
selection.applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
||||||
if (id === undefined || id === 'waypoints') {
|
let stats = fileStateCollection.getStatistics(fileId);
|
||||||
Object.keys(this.statistics).forEach((key) => {
|
if (stats) {
|
||||||
if (this.statistics[key] instanceof GPXStatistics) {
|
let first = true;
|
||||||
statistics.mergeWith(this.statistics[key]);
|
items.forEach((item) => {
|
||||||
} else {
|
if (
|
||||||
statistics.mergeWith(this.statistics[key].getStatisticsFor(item));
|
!(item instanceof ListWaypointItem || item instanceof ListWaypointsItem) ||
|
||||||
|
first
|
||||||
|
) {
|
||||||
|
statistics.mergeWith(stats.getStatisticsFor(item));
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._files.has(fileId)) {
|
||||||
|
let file = fileStateCollection.getFileState(fileId);
|
||||||
|
if (file) {
|
||||||
|
let first = true;
|
||||||
|
let unsubscribe = file.subscribe(() => {
|
||||||
|
if (first) first = false;
|
||||||
|
else this.update();
|
||||||
|
});
|
||||||
|
this._files.set(fileId, { file, unsubscribe });
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
} else {
|
}, false);
|
||||||
let child = this.statistics[id];
|
this._statistics.set(statistics);
|
||||||
if (child instanceof GPXStatistics) {
|
for (let [fileId, entry] of this._files) {
|
||||||
statistics.mergeWith(child);
|
if (
|
||||||
} else if (child !== undefined) {
|
!get(fileStateCollection).has(fileId) ||
|
||||||
statistics.mergeWith(child.getStatisticsFor(item));
|
!get(selection).hasAnyChildren(new ListFileItem(fileId))
|
||||||
|
) {
|
||||||
|
entry.unsubscribe();
|
||||||
|
this._files.delete(fileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return statistics;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export type GPXFileWithStatistics = { file: GPXFile; statistics: GPXStatisticsTree };
|
|
||||||
|
export const gpxStatistics = new SelectedGPXStatistics();
|
||||||
|
|
||||||
|
export const slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined> =
|
||||||
|
writable(undefined);
|
||||||
|
|
||||||
|
gpxStatistics.subscribe(() => {
|
||||||
|
slicedGPXStatistics.set(undefined);
|
||||||
|
});
|
||||||
|
|||||||
@@ -22,64 +22,6 @@
|
|||||||
// export const embedding = writable(false);
|
// export const embedding = writable(false);
|
||||||
// export const selectFiles = writable<{ [key: string]: (fileId?: string) => void }>({});
|
// export const selectFiles = writable<{ [key: string]: (fileId?: string) => void }>({});
|
||||||
|
|
||||||
// export const gpxStatistics: Writable<GPXStatistics> = writable(new GPXStatistics());
|
|
||||||
// export const slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined> =
|
|
||||||
// writable(undefined);
|
|
||||||
|
|
||||||
// export function updateGPXData() {
|
|
||||||
// let statistics = new GPXStatistics();
|
|
||||||
// applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
|
||||||
// let stats = getStatistics(fileId);
|
|
||||||
// if (stats) {
|
|
||||||
// let first = true;
|
|
||||||
// items.forEach((item) => {
|
|
||||||
// if (
|
|
||||||
// !(item instanceof ListWaypointItem || item instanceof ListWaypointsItem) ||
|
|
||||||
// first
|
|
||||||
// ) {
|
|
||||||
// statistics.mergeWith(stats.getStatisticsFor(item));
|
|
||||||
// first = false;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }, false);
|
|
||||||
// gpxStatistics.set(statistics);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let unsubscribes: Map<string, () => void> = new Map();
|
|
||||||
// selection.subscribe(($selection) => {
|
|
||||||
// // Maintain up-to-date statistics for the current selection
|
|
||||||
// updateGPXData();
|
|
||||||
|
|
||||||
// while (unsubscribes.size > 0) {
|
|
||||||
// let [fileId, unsubscribe] = unsubscribes.entries().next().value;
|
|
||||||
// unsubscribe();
|
|
||||||
// unsubscribes.delete(fileId);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $selection.forEach((item) => {
|
|
||||||
// let fileId = item.getFileId();
|
|
||||||
// if (!unsubscribes.has(fileId)) {
|
|
||||||
// let fileObserver = get(fileObservers).get(fileId);
|
|
||||||
// if (fileObserver) {
|
|
||||||
// let first = true;
|
|
||||||
// unsubscribes.set(
|
|
||||||
// fileId,
|
|
||||||
// fileObserver.subscribe(() => {
|
|
||||||
// if (first) first = false;
|
|
||||||
// else updateGPXData();
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// gpxStatistics.subscribe(() => {
|
|
||||||
// slicedGPXStatistics.set(undefined);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// export const gpxLayers: Map<string, GPXLayer> = new Map();
|
|
||||||
// export const routingControls: Map<string, RoutingControls> = new Map();
|
// export const routingControls: Map<string, RoutingControls> = new Map();
|
||||||
|
|
||||||
// export function selectFileWhenLoaded(fileId: string) {
|
// export function selectFileWhenLoaded(fileId: string) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import GPXLayers from '$lib/components/map/gpx-layer/GPXLayers.svelte';
|
import GPXLayers from '$lib/components/map/gpx-layer/GPXLayers.svelte';
|
||||||
// import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
// import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||||
// import FileList from '$lib/components/file-list/FileList.svelte';
|
// import FileList from '$lib/components/file-list/FileList.svelte';
|
||||||
// import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
||||||
import Map from '$lib/components/map/Map.svelte';
|
import Map from '$lib/components/map/Map.svelte';
|
||||||
import Menu from '$lib/components/Menu.svelte';
|
import Menu from '$lib/components/Menu.svelte';
|
||||||
// import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
|
// import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
// import CoordinatesPopup from '$lib/components/map/CoordinatesPopup.svelte';
|
// import CoordinatesPopup from '$lib/components/map/CoordinatesPopup.svelte';
|
||||||
import Resizer from '$lib/components/Resizer.svelte';
|
import Resizer from '$lib/components/Resizer.svelte';
|
||||||
import { Toaster } from '$lib/components/ui/sonner';
|
import { Toaster } from '$lib/components/ui/sonner';
|
||||||
// import { gpxStatistics, loadFiles, slicedGPXStatistics } from '$lib/stores';
|
|
||||||
// import { onMount } from 'svelte';
|
// import { onMount } from 'svelte';
|
||||||
// import { page } from '$app/state';
|
// import { page } from '$app/state';
|
||||||
import { languages } from '$lib/languages';
|
import { languages } from '$lib/languages';
|
||||||
@@ -23,6 +22,7 @@
|
|||||||
import { loadFiles } from '$lib/logic/file-actions';
|
import { loadFiles } from '$lib/logic/file-actions';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
|
import { gpxStatistics, slicedGPXStatistics } from '$lib/logic/statistics';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
treeFileView,
|
treeFileView,
|
||||||
@@ -127,12 +127,12 @@
|
|||||||
class="{$elevationProfile ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"
|
class="{$elevationProfile ? '' : 'h-10'} flex flex-row gap-2 px-2 sm:px-4"
|
||||||
style={$elevationProfile ? `height: ${$bottomPanelSize}px` : ''}
|
style={$elevationProfile ? `height: ${$bottomPanelSize}px` : ''}
|
||||||
>
|
>
|
||||||
<!-- <GPXStatistics
|
<GPXStatistics
|
||||||
{gpxStatistics}
|
{gpxStatistics}
|
||||||
{slicedGPXStatistics}
|
{slicedGPXStatistics}
|
||||||
panelSize={$bottomPanelSize}
|
panelSize={$bottomPanelSize}
|
||||||
orientation={$elevationProfile ? 'vertical' : 'horizontal'}
|
orientation={$elevationProfile ? 'vertical' : 'horizontal'}
|
||||||
/> -->
|
/>
|
||||||
<!-- {#if $elevationProfile}
|
<!-- {#if $elevationProfile}
|
||||||
<ElevationProfile
|
<ElevationProfile
|
||||||
{gpxStatistics}
|
{gpxStatistics}
|
||||||
|
|||||||
Reference in New Issue
Block a user