Skip to content

Commit

Permalink
[APP-3958] Maplibre component cleanup (#513)
Browse files Browse the repository at this point in the history
  • Loading branch information
micheal-parks committed Apr 23, 2024
1 parent 6cb17f8 commit 72fccc1
Show file tree
Hide file tree
Showing 13 changed files with 230 additions and 85 deletions.
4 changes: 2 additions & 2 deletions packages/blocks/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@viamrobotics/prime-blocks",
"version": "0.0.28",
"version": "0.0.29",
"publishConfig": {
"access": "public"
},
Expand Down Expand Up @@ -42,7 +42,7 @@
"three": ">=0.159"
},
"dependencies": {
"maplibre-gl": "^3.3.0"
"maplibre-gl": "^4.1.3"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/blocks/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// MapLibre components
export { default as MapLibre } from './maplibre/index.svelte';
export { default as MapLibreMarker } from './maplibre/marker.svelte';
export { default as MapLibreDirectionalMarker } from './maplibre/directional-marker.svelte';
export { default as MapLibreControls } from './maplibre/controls.svelte';
export { useMapLibre, useMapLibreEvent } from './maplibre/hooks';
export type { LngLat, GeoPose, Waypoint } from './maplibre/types';

Expand Down
40 changes: 40 additions & 0 deletions packages/blocks/src/lib/maplibre/controls.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!--
@component
Adds a set of navigation controls.
@example
```html
<MapLibre>
<MapLibreControls />
</MapLibre>
```
@see https://maplibre.org/maplibre-gl-js/docs/API/classes/NavigationControl/
-->
<script lang="ts">
import { NavigationControl, type ControlPosition } from 'maplibre-gl';
import { onMount } from 'svelte';
import { useMapLibre } from './hooks';
export let position: ControlPosition = 'top-right';
export let showCompass = true;
export let showZoom = true;
export let visualizePitch = true;
const { map } = useMapLibre();
const control = new NavigationControl();
$: control.options.showCompass = showCompass;
$: control.options.showZoom = showZoom;
$: control.options.visualizePitch = visualizePitch;
onMount(() => {
map.addControl(control, position);
return () => {
map.removeControl(control);
};
});
</script>
31 changes: 31 additions & 0 deletions packages/blocks/src/lib/maplibre/directional-marker.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import Marker from './marker.svelte';
/** The longitude of the marker. */
export let lng = 0;
/** The latitude of the marker. */
export let lat = 0;
/** The rotation angle of the marker (clockwise, in degrees) */
export let rotation = 0;
/** The relative size of the marker. */
export let scale = 1;
let element: HTMLElement;
</script>

<div
bind:this={element}
class="h-7.5 w-7.5"
style:background-image={`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='green' stroke='white' stroke-width='2' %3E%3Cpath d='M12,2L4.5,20.29L5.21,21L12,18L18.79,21L19.5,20.29L12,2Z' /%3E%3C/svg%3E")`}
/>

<Marker
{element}
{lng}
{lat}
{rotation}
{scale}
/>
76 changes: 44 additions & 32 deletions packages/blocks/src/lib/maplibre/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<script lang="ts">
import 'maplibre-gl/dist/maplibre-gl.css';
import { onMount, createEventDispatcher, onDestroy } from 'svelte';
import { onMount, tick } from 'svelte';
import { provideMapContext } from './hooks';
import { Map, NavigationControl } from 'maplibre-gl';
import { Map, type MapOptions } from 'maplibre-gl';
import { style } from './style';
import type { LngLat } from '$lib';
Expand All @@ -44,51 +44,65 @@ export let maxZoom = 22;
*/
export let center: LngLat = { lng: -73.984_421, lat: 40.771_811_6 };
/** The MapLibre Map instance */
/** A binding to the MapLibre Map instance */
export let map: Map | undefined = undefined;
interface Events {
/** Fired after the map has been created. */
create: Map;
/** Fired when the map camera moves. */
move: Map;
/** Fired when the map resizes. */
resize: Map;
}
export let options: Partial<MapOptions> | undefined = undefined;
/** Fired after the map has been created. */
export let onCreate: undefined | ((map: Map) => void) = undefined;
/** Fired when the map camera moves. */
export let onMove: undefined | ((map: Map) => void) = undefined;
/** Fired when the map resizes. */
export let onResize: undefined | ((map: Map) => void) = undefined;
const dispatch = createEventDispatcher<Events>();
const context = provideMapContext(center, zoom);
let container: HTMLElement;
let created = false;
const setMapSize = () => {
const canvas = map!.getCanvas();
const canvas = map?.getCanvas();
context.size.set({
width: canvas.clientWidth,
height: canvas.clientHeight,
width: canvas?.clientWidth ?? 0,
height: canvas?.clientHeight ?? 0,
});
};
const handleCreate = () => {
if (map === undefined) {
return;
}
created = true;
dispatch('create', map!);
onCreate?.(map);
// Resize the map after any slots have been rendered.
requestAnimationFrame(() => map!.resize());
void tick().then(() => map?.resize());
};
const handleMove = () => {
context.center.set(map!.getCenter());
context.zoom.set(map!.getZoom());
dispatch('move', map!);
if (map === undefined) {
return;
}
context.center.set(map.getCenter());
context.zoom.set(map.getZoom());
onMove?.(map);
};
const handleResize = () => {
if (map === undefined) {
return;
}
setMapSize();
context.center.set(map!.getCenter());
context.zoom.set(map!.getZoom());
dispatch('resize', map!);
context.center.set(map.getCenter());
context.zoom.set(map.getZoom());
onResize?.(map);
};
onMount(() => {
Expand All @@ -102,22 +116,20 @@ onMount(() => {
maxPitch,
minZoom,
maxZoom,
...options,
});
context.map.set(map);
const nav = new NavigationControl({ showZoom: false });
map.addControl(nav, 'top-right');
map.on('move', handleMove);
map.on('resize', handleResize);
map.on('style.load', handleCreate);
});
onDestroy(() => {
map?.off('move', handleMove);
map?.off('resize', handleResize);
map?.off('style.load', handleCreate);
return () => {
map?.off('move', handleMove);
map?.off('resize', handleResize);
map?.off('style.load', handleCreate);
};
});
$: map?.setMinPitch(minPitch);
Expand All @@ -129,7 +141,7 @@ $: map?.setMaxPitch(maxPitch);
{/if}

<div
class="h-full"
class="h-full {$$restProps.class ?? ''}"
{...$$restProps}
>
<div
Expand Down
18 changes: 12 additions & 6 deletions packages/blocks/src/lib/maplibre/marker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@
import { onDestroy } from 'svelte';
import { Marker, LngLat } from 'maplibre-gl';
import { useMapLibre } from './hooks';
import type { GeoPose } from '$lib';
/** The Geo position of the marker. */
export let pose: GeoPose | undefined;
/** The longitude of the marker. */
export let lng = 0;
/** The latitude of the marker. */
export let lat = 0;
/** The rotation angle of the marker (clockwise, in degrees) */
export let rotation = 0;
/** The relative size of the marker. */
export let scale = 1;
Expand All @@ -33,14 +38,15 @@ const { map } = useMapLibre();
let marker: Marker | undefined;
$: if (pose) {
$: {
marker?.remove();
marker = new Marker(element ? { element, scale, color } : { scale, color });
marker.setLngLat(new LngLat(0, 0));
marker.getElement().style.zIndex = '1';
marker.setLngLat(new LngLat(pose.lng, pose.lat));
marker.setRotation(pose.rotation);
marker.addTo(map);
}
$: marker?.setLngLat(new LngLat(lng, lat));
$: marker?.setRotation(rotation);
onDestroy(() => marker?.remove());
</script>
5 changes: 3 additions & 2 deletions packages/blocks/src/lib/navigation-map/components/map.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { Button, Icon, ToggleButtons, Tooltip } from '@viamrobotics/prime-core';
import type { Map } from 'maplibre-gl';
import { MapLibre, type GeoPose } from '$lib';
import { MapLibre, type GeoPose, MapLibreControls } from '$lib';
import { environment, view } from '../stores';
import SceneLayer from './scene-layer.svelte';
import RobotMarker from './robot-marker.svelte';
Expand Down Expand Up @@ -74,8 +74,9 @@ onDestroy(() => {
maxPitch={$view === '3D' ? maxPitch : minPitch}
minZoom={6}
bind:map
on:create
>
<MapLibreControls showZoom={false} />

<Nav
on:add-waypoint
on:delete-waypoint
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
<script lang="ts">
import { MapLibreMarker, type GeoPose } from '$lib';
export let element = document.createElement('div');
element.style.backgroundImage = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='green' stroke='white' stroke-width='2' %3E%3Cpath d='M12,2L4.5,20.29L5.21,21L12,18L18.79,21L19.5,20.29L12,2Z' /%3E%3C/svg%3E")`;
element.style.width = `30px`;
element.style.height = `30px`;
import { MapLibreDirectionalMarker, type GeoPose } from '$lib';
/** The Lng,Lat and rotation of the marker. */
export let pose: GeoPose | undefined = undefined;
</script>

{#if pose}
<MapLibreMarker
{element}
{pose}
<MapLibreDirectionalMarker
lng={pose.lng}
lat={pose.lat}
rotation={pose.rotation}
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { waypoints } from '../stores';
{#each $waypoints as waypoint (waypoint.id)}
<MapLibreMarker
scale={0.7}
pose={{ lng: waypoint.lng, lat: waypoint.lat, rotation: 0 }}
lng={waypoint.lng}
lat={waypoint.lat}
/>
{/each}
1 change: 0 additions & 1 deletion packages/blocks/src/lib/navigation-map/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ $: $envStore = environment;
<Map
bind:map
{baseGeoPose}
on:create
on:add-waypoint
on:delete-waypoint
on:update-obstacles
Expand Down
9 changes: 7 additions & 2 deletions packages/blocks/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script lang="ts">
import pointcloudUrl from '$lib/assets/pointcloud.pcd?url';
import motionPath from '$lib/assets/cbirrtsmooth800.txt?raw';
import { MapLibre, SlamMap2D } from '$lib';
import { MapLibre, MapLibreControls, SlamMap2D } from '$lib';
import NavigationMap from './navigation-map.svelte';
import FollowingMarker from './following-marker.svelte';
const fetchPointcloud = async () => {
const response = await fetch(pointcloudUrl);
Expand Down Expand Up @@ -45,7 +46,11 @@ const path = () =>

<div class="px-12">
<div class="relative aspect-video w-full border border-gray-200 pt-0">
<MapLibre />
<MapLibre>
<MapLibreControls />
</MapLibre>
</div>
</div>

<FollowingMarker />
</div>
Loading

0 comments on commit 72fccc1

Please sign in to comment.