mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-02 00:32:33 +00:00
zoom on elevation profile, closes #54
This commit is contained in:
20
website/package-lock.json
generated
20
website/package-lock.json
generated
@@ -14,6 +14,7 @@
|
|||||||
"@types/mapbox__sphericalmercator": "^1.2.3",
|
"@types/mapbox__sphericalmercator": "^1.2.3",
|
||||||
"bits-ui": "^0.21.12",
|
"bits-ui": "^0.21.12",
|
||||||
"chart.js": "^4.4.3",
|
"chart.js": "^4.4.3",
|
||||||
|
"chartjs-plugin-zoom": "^2.0.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dexie": "^4.0.7",
|
"dexie": "^4.0.7",
|
||||||
"gpx": "file:../gpx",
|
"gpx": "file:../gpx",
|
||||||
@@ -2686,6 +2687,17 @@
|
|||||||
"pnpm": ">=8"
|
"pnpm": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chartjs-plugin-zoom": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-ogOmLu6e+Q7E1XWOCOz9YwybMslz9qNfGV2a+qjfmqJYpsw5ZMoRHZBUyW+NGhkpQ5PwwPA/+rikHpBZb7PZuA==",
|
||||||
|
"dependencies": {
|
||||||
|
"hammerjs": "^2.0.8"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"chart.js": ">=3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cheap-ruler": {
|
"node_modules/cheap-ruler": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-3.0.2.tgz",
|
||||||
@@ -3958,6 +3970,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz",
|
||||||
"integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA=="
|
"integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/hammerjs": {
|
||||||
|
"version": "2.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
|
||||||
|
"integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hard-rejection": {
|
"node_modules/hard-rejection": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
|
||||||
|
@@ -53,6 +53,7 @@
|
|||||||
"@types/mapbox__sphericalmercator": "^1.2.3",
|
"@types/mapbox__sphericalmercator": "^1.2.3",
|
||||||
"bits-ui": "^0.21.12",
|
"bits-ui": "^0.21.12",
|
||||||
"chart.js": "^4.4.3",
|
"chart.js": "^4.4.3",
|
||||||
|
"chartjs-plugin-zoom": "^2.0.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dexie": "^4.0.7",
|
"dexie": "^4.0.7",
|
||||||
"gpx": "file:../gpx",
|
"gpx": "file:../gpx",
|
||||||
@@ -69,4 +70,4 @@
|
|||||||
"tailwind-merge": "^2.3.0",
|
"tailwind-merge": "^2.3.0",
|
||||||
"tailwind-variants": "^0.2.1"
|
"tailwind-variants": "^0.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
import * as ToggleGroup from '$lib/components/ui/toggle-group';
|
import * as ToggleGroup from '$lib/components/ui/toggle-group';
|
||||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
|
import zoomPlugin from 'chartjs-plugin-zoom';
|
||||||
import mapboxgl from 'mapbox-gl';
|
import mapboxgl from 'mapbox-gl';
|
||||||
import { map } from '$lib/stores';
|
import { map } from '$lib/stores';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
@@ -68,11 +69,13 @@
|
|||||||
let overlay: HTMLCanvasElement;
|
let overlay: HTMLCanvasElement;
|
||||||
let chart: Chart;
|
let chart: Chart;
|
||||||
|
|
||||||
|
Chart.register(zoomPlugin);
|
||||||
Chart.defaults.font.family =
|
Chart.defaults.font.family =
|
||||||
'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'; // Tailwind CSS font
|
'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'; // Tailwind CSS font
|
||||||
|
|
||||||
let marker: mapboxgl.Marker | null = null;
|
let marker: mapboxgl.Marker | null = null;
|
||||||
let dragging = false;
|
let dragging = false;
|
||||||
|
let panning = false;
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
animation: false,
|
animation: false,
|
||||||
@@ -119,7 +122,7 @@
|
|||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
enabled: () => !dragging,
|
enabled: () => !dragging && !panning,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
title: function () {
|
title: function () {
|
||||||
return '';
|
return '';
|
||||||
@@ -177,6 +180,48 @@
|
|||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
zoom: {
|
||||||
|
pan: {
|
||||||
|
enabled: true,
|
||||||
|
mode: 'x',
|
||||||
|
modifierKey: 'shift',
|
||||||
|
onPanStart: function () {
|
||||||
|
// hide tooltip
|
||||||
|
panning = true;
|
||||||
|
$slicedGPXStatistics = undefined;
|
||||||
|
},
|
||||||
|
onPanComplete: function () {
|
||||||
|
panning = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
zoom: {
|
||||||
|
wheel: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
|
mode: 'x',
|
||||||
|
onZoomStart: function ({ chart, event }: { chart: Chart; event: any }) {
|
||||||
|
if (
|
||||||
|
event.deltaY < 0 &&
|
||||||
|
Math.abs(
|
||||||
|
chart.getInitialScaleBounds().x.max / chart.options.plugins.zoom.limits.x.minRange -
|
||||||
|
chart.getZoomLevel()
|
||||||
|
) < 0.01
|
||||||
|
) {
|
||||||
|
// Disable wheel pan if zoomed in to the max, and zooming in
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$slicedGPXStatistics = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
limits: {
|
||||||
|
x: {
|
||||||
|
min: 'original',
|
||||||
|
max: 'original',
|
||||||
|
minRange: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stacked: false,
|
stacked: false,
|
||||||
@@ -313,6 +358,10 @@
|
|||||||
|
|
||||||
let dragStarted = false;
|
let dragStarted = false;
|
||||||
function onMouseDown(evt) {
|
function onMouseDown(evt) {
|
||||||
|
if (evt.shiftKey) {
|
||||||
|
// Panning interaction
|
||||||
|
return;
|
||||||
|
}
|
||||||
dragStarted = true;
|
dragStarted = true;
|
||||||
canvas.style.cursor = 'col-resize';
|
canvas.style.cursor = 'col-resize';
|
||||||
startIndex = getIndex(evt);
|
startIndex = getIndex(evt);
|
||||||
|
@@ -65,9 +65,12 @@ The size of the elevation profile can be adjusted by dragging the separator betw
|
|||||||
### Interactive statistics
|
### Interactive statistics
|
||||||
|
|
||||||
When hovering over the elevation profile, a tooltip will show statistics at the cursor position.
|
When hovering over the elevation profile, a tooltip will show statistics at the cursor position.
|
||||||
|
|
||||||
To get the statistics for a specific section of the elevation profile, you can drag a selection rectangle on the profile.
|
To get the statistics for a specific section of the elevation profile, you can drag a selection rectangle on the profile.
|
||||||
Click on the profile to reset the selection.
|
Click on the profile to reset the selection.
|
||||||
|
|
||||||
|
You can also use the mouse wheel to zoom in and out on the elevation profile, and pan by dragging the profile while holding the <kbd>Shift</kbd> key.
|
||||||
|
|
||||||
### Additional data
|
### Additional data
|
||||||
|
|
||||||
Using the buttons on the right of the elevation profile, you can optionally color the elevation profile by:
|
Using the buttons on the right of the elevation profile, you can optionally color the elevation profile by:
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
export const prerender = true;
|
export const prerender = true;
|
||||||
|
export const ssr = false;
|
||||||
|
|
||||||
import { languages } from '$lib/languages';
|
import { languages } from '$lib/languages';
|
||||||
import { register, init } from 'svelte-i18n';
|
import { register, init } from 'svelte-i18n';
|
||||||
|
Reference in New Issue
Block a user