finished embedding

This commit is contained in:
vcoppe
2024-07-12 18:08:27 +02:00
parent 5419088eaf
commit 24a5daaf9a
13 changed files with 194 additions and 62 deletions

View File

@@ -14,7 +14,9 @@
import { PUBLIC_MAPBOX_TOKEN } from '$env/static/public';
export let accessToken = PUBLIC_MAPBOX_TOKEN;
export let geolocate = true;
export let geocoder = true;
export let hash = true;
mapboxgl.accessToken = accessToken;
@@ -35,7 +37,7 @@
container: 'map',
style: { version: 8, sources: {}, layers: [] },
projection: { name: 'mercator' },
hash: true,
hash: hash,
language: get(locale),
attributionControl: false,
logoPosition: 'bottom-right',
@@ -66,16 +68,18 @@
);
}
newMap.addControl(
new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
fitBoundsOptions,
trackUserLocation: true,
showUserHeading: true
})
);
if (geolocate) {
newMap.addControl(
new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
fitBoundsOptions,
trackUserLocation: true,
showUserHeading: true
})
);
}
newMap.addControl(scaleControl);

View File

@@ -74,6 +74,11 @@
@apply hover:underline;
}
:global(.markdown li > a) {
@apply text-blue-500;
@apply hover:underline;
}
:global(.markdown kbd) {
@apply p-1;
@apply rounded-md;

View File

@@ -9,3 +9,10 @@
>
<slot />
</div>
<style lang="postcss">
div :global(a) {
@apply text-blue-500;
@apply hover:underline;
}
</style>

View File

@@ -18,14 +18,25 @@
$embedding = true;
const { currentBasemap, distanceUnits, velocityUnits, temperatureUnits, fileOrder } = settings;
const {
currentBasemap,
distanceUnits,
velocityUnits,
temperatureUnits,
fileOrder,
distanceMarkers,
directionMarkers
} = settings;
export let options: EmbeddingOptions;
export let hash: string;
let prevUnits = {
distance: '',
velocity: '',
temperature: ''
let prevSettings = {
distanceMarkers: false,
directionMarkers: false,
distanceUnits: 'metric',
velocityUnits: 'speed',
temperatureUnits: 'celsius'
};
function applyOptions() {
@@ -97,29 +108,39 @@
return $selection;
});
map.subscribe(($map) => {
if ($map) {
$map.fitBounds(
[
bounds.southWest.lon,
bounds.southWest.lat,
bounds.northEast.lon,
bounds.northEast.lat
],
{
padding: 80,
linear: true,
easing: () => 1
}
);
}
});
if (hash.length === 0) {
map.subscribe(($map) => {
if ($map) {
$map.fitBounds(
[
bounds.southWest.lon,
bounds.southWest.lat,
bounds.northEast.lon,
bounds.northEast.lat
],
{
padding: 80,
linear: true,
easing: () => 1
}
);
}
});
}
});
if (options.basemap !== $currentBasemap && allowedEmbeddingBasemaps.includes(options.basemap)) {
$currentBasemap = options.basemap;
}
if (options.distanceMarkers !== $distanceMarkers) {
$distanceMarkers = options.distanceMarkers;
}
if (options.directionMarkers !== $directionMarkers) {
$directionMarkers = options.directionMarkers;
}
if (options.distanceUnits !== $distanceUnits) {
$distanceUnits = options.distanceUnits;
}
@@ -134,9 +155,11 @@
}
onMount(() => {
prevUnits.distance = $distanceUnits;
prevUnits.velocity = $velocityUnits;
prevUnits.temperature = $temperatureUnits;
prevSettings.distanceMarkers = $distanceMarkers;
prevSettings.directionMarkers = $directionMarkers;
prevSettings.distanceUnits = $distanceUnits;
prevSettings.velocityUnits = $velocityUnits;
prevSettings.temperatureUnits = $temperatureUnits;
});
$: if (options) {
@@ -144,16 +167,24 @@
}
onDestroy(() => {
if ($distanceUnits !== prevUnits.distance) {
$distanceUnits = prevUnits.distance;
if ($distanceMarkers !== prevSettings.distanceMarkers) {
$distanceMarkers = prevSettings.distanceMarkers;
}
if ($velocityUnits !== prevUnits.velocity) {
$velocityUnits = prevUnits.velocity;
if ($directionMarkers !== prevSettings.directionMarkers) {
$directionMarkers = prevSettings.directionMarkers;
}
if ($temperatureUnits !== prevUnits.temperature) {
$temperatureUnits = prevUnits.temperature;
if ($distanceUnits !== prevSettings.distanceUnits) {
$distanceUnits = prevSettings.distanceUnits;
}
if ($velocityUnits !== prevSettings.velocityUnits) {
$velocityUnits = prevSettings.velocityUnits;
}
if ($temperatureUnits !== prevSettings.temperatureUnits) {
$temperatureUnits = prevSettings.temperatureUnits;
}
$fileOrder = $fileOrder.filter((id) => !id.includes('embed'));
@@ -166,6 +197,8 @@
class="h-full {$fileObservers.size > 1 ? 'horizontal' : ''}"
accessToken={options.token}
geocoder={false}
geolocate={false}
hash={false}
/>
<OpenIn bind:files={options.files} />
<LayerControl />

View File

@@ -1,3 +1,5 @@
import { basemaps } from "$lib/assets/layers";
export type EmbeddingOptions = {
token: string;
files: string[];
@@ -13,6 +15,8 @@ export type EmbeddingOptions = {
temp: boolean,
power: boolean,
},
distanceMarkers: boolean,
directionMarkers: boolean,
distanceUnits: 'metric' | 'imperial',
velocityUnits: 'speed' | 'pace',
temperatureUnits: 'celsius' | 'fahrenheit',
@@ -33,6 +37,8 @@ export const defaultEmbeddingOptions = {
temp: false,
power: false,
},
distanceMarkers: false,
directionMarkers: false,
distanceUnits: 'metric',
velocityUnits: 'speed',
temperatureUnits: 'celsius',
@@ -57,7 +63,4 @@ export function getCleanedEmbeddingOptions(options: any, defaultOptions: any = d
return cleanedOptions;
}
export const allowedEmbeddingBasemaps = [
'mapboxOutdoors',
'mapboxSatellite',
];
export const allowedEmbeddingBasemaps = Object.keys(basemaps).filter(basemap => !['ordnanceSurvey'].includes(basemap));

View File

@@ -5,7 +5,16 @@
import * as Select from '$lib/components/ui/select';
import { Checkbox } from '$lib/components/ui/checkbox';
import * as RadioGroup from '$lib/components/ui/radio-group';
import { Zap, HeartPulse, Orbit, Thermometer, SquareActivity } from 'lucide-svelte';
import {
Zap,
HeartPulse,
Orbit,
Thermometer,
SquareActivity,
Coins,
Milestone,
Video
} from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import {
allowedEmbeddingBasemaps,
@@ -35,11 +44,11 @@
let manualCamera = false;
let zoom = 0;
let lat = 0;
let lon = 0;
let bearing = 0;
let pitch = 0;
let zoom = '0';
let lat = '0';
let lon = '0';
let bearing = '0';
let pitch = '0';
$: hash = manualCamera ? `#${zoom}/${lat}/${lon}/${bearing}/${pitch}` : '';
@@ -58,6 +67,21 @@
$: if (options.elevation.height || options.elevation.show) {
resizeMap();
}
function updateCamera() {
if ($map) {
let center = $map.getCenter();
lat = center.lat.toFixed(4);
lon = center.lng.toFixed(4);
zoom = $map.getZoom().toFixed(2);
bearing = $map.getBearing().toFixed(1);
pitch = $map.getPitch().toFixed(0);
}
}
$: if ($map) {
$map.on('moveend', updateCamera);
}
</script>
<Card.Root>
@@ -164,6 +188,20 @@
</div>
</div>
{/if}
<div class="flex flex-row items-center gap-2">
<Checkbox id="distance-markers" bind:checked={options.distanceMarkers} />
<Label for="distance-markers" class="flex flex-row items-center gap-1">
<Coins size="16" />
{$_('menu.distance_markers')}
</Label>
</div>
<div class="flex flex-row items-center gap-2">
<Checkbox id="direction-markers" bind:checked={options.directionMarkers} />
<Label for="direction-markers" class="flex flex-row items-center gap-1">
<Milestone size="16" />
{$_('menu.direction_markers')}
</Label>
</div>
<div class="flex flex-row flex-wrap justify-between gap-3">
<Label class="flex flex-col items-start gap-2">
{$_('menu.distance_units')}
@@ -205,18 +243,52 @@
</RadioGroup.Root>
</Label>
</div>
<div class="flex flex-col gap-3 p-3 border rounded-md">
<div class="flex flex-row items-center gap-2">
<Checkbox id="manual-camera" bind:checked={manualCamera} />
<Label for="manual-camera" class="flex flex-row items-center gap-1">
<Video size="16" />
{$_('embedding.manual_camera')}
</Label>
</div>
<p class="text-sm text-muted-foreground">
{$_('embedding.manual_camera_description')}
</p>
<div class="flex flex-row flex-wrap items-center gap-6">
<Label class="flex flex-col gap-1">
<span>{$_('embedding.latitude')}</span>
<span>{lat}</span>
</Label>
<Label class="flex flex-col gap-1">
<span>{$_('embedding.longitude')}</span>
<span>{lon}</span>
</Label>
<Label class="flex flex-col gap-1">
<span>{$_('embedding.zoom')}</span>
<span>{zoom}</span>
</Label>
<Label class="flex flex-col gap-1">
<span>{$_('embedding.bearing')}</span>
<span>{bearing}</span>
</Label>
<Label class="flex flex-col gap-1">
<span>{$_('embedding.pitch')}</span>
<span>{pitch}</span>
</Label>
</div>
</div>
<Label>
{$_('embedding.preview')}
</Label>
<div class="relative h-[600px]">
<Embedding bind:options={iframeOptions} />
<Embedding bind:options={iframeOptions} bind:hash />
</div>
<Label>
{$_('embedding.code')}
</Label>
<pre class="bg-primary text-primary-foreground p-3 rounded-md whitespace-normal break-all">
<code class="language-html">
{`<iframe src="https://gpx.studio${base}/embed?options=${encodeURIComponent(JSON.stringify(getCleanedEmbeddingOptions(options)))}${hash}" width="100%" height="600px" frameborder="0" />`}
{`<iframe src="https://gpx.studio${base}/embed?options=${encodeURIComponent(JSON.stringify(getCleanedEmbeddingOptions(options)))}${hash}" width="100%" height="600px" frameborder="0" style="outline: none;"/>`}
</code>
</pre>
</fieldset>

View File

@@ -10,7 +10,7 @@
<Button
variant="ghost"
class="absolute top-0 flex-wrap h-fit bg-background font-semibold rounded-md py-1 px-2 gap-1.5 xs:text-base mt-2.5 ml-2.5 mr-12"
href="{getURLForLanguage($locale, '/embed')}?files={encodeURIComponent(JSON.stringify(files))}"
href="{getURLForLanguage($locale, '/app')}?files={encodeURIComponent(JSON.stringify(files))}"
target="_blank"
>
{$_('menu.open_in')}

View File

@@ -9,8 +9,16 @@ title: Integration
# { title }
<DocsNote>
This section is a work in progress.
You can use **gpx.studio** to create maps showing your GPX files and embed them in your website.
All you need is:
1. A <a href="https://account.mapbox.com/auth/signup" target="_blank">Mapbox access token</a> to load the map, and
1. GPX files hosted on your server or a public URL.
You can then play with the configurator below to customize your map and generate the corresponding HTML code.
<DocsNote type="warning">
You will need to set up <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank">Cross-Origin Resource Sharing (CORS)</a> headers on your server to allow <b>gpx.studio</b> to load your GPX files.
</DocsNote>
<EmbeddingPlaygound />

View File

@@ -25,7 +25,7 @@ You can use the search bar to look for an address and navigate to it on the map.
The locate button will center the map on your current location.
<DocsNote>
This only works if you have allowed your browser and the website to access your location.
This only works if you have allowed your browser and <b>gpx.studio</b> to access your location.
</DocsNote>
### <PersonStanding size="16" class="inline-block" style="margin-bottom: 2px" /> Street view

View File

@@ -44,5 +44,5 @@ Open the export dialog to save the currently selected files to your computer.
Open the export dialog to save all files to your computer.
<DocsNote type="warning">
If your download does not start after clicking the download button, please check your browser settings to allow downloads from this website.
If your download does not start after clicking the download button, please check your browser settings to allow downloads from <b>gpx.studio</b>.
</DocsNote>

View File

@@ -20,5 +20,5 @@ Applying the tool to a file containing multiple tracks will create a new file fo
Similarly, applying the tool to a track containing multiple segments will create (in the same file) a new track for each of the segments it contains.
<DocsNote>
When extracting the tracks of a file containing [points of interest](../gpx), the tool will automatically assign each point of interest to the track it is closest to.
When extracting the tracks of a file containing <a href="../gpx">points of interest</a>, the tool will automatically assign each point of interest to the track it is closest to.
</DocsNote>

View File

@@ -382,9 +382,9 @@
"show_controls": "Show controls",
"manual_camera": "Manual camera",
"manual_camera_description": "You can move the map below to adjust the camera position.",
"zoom": "Zoom",
"latitude": "Latitude",
"longitude": "Longitude",
"zoom": "Zoom",
"pitch": "Pitch",
"bearing": "Bearing",
"preview": "Preview",

View File

@@ -23,5 +23,5 @@
</script>
{#if embeddingOptions}
<Embedding options={embeddingOptions} />
<Embedding options={embeddingOptions} hash={$page.url.hash} />
{/if}