Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring-your-own-map for Web Components #395

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions web/src/ferrostar-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ export class FerrostarMap extends LitElement {
@state()
protected _tripState: TripState | null = null;

// Configures the control on first load.
/**
* Configures the map on first load.
*
* Note: This will only be invoked if there is no map set
* by the time of the first component update.
* If you provide your own map parameter,
* configuration is left to the caller.
* Be sure to set the DOM parent via the slot as well.
*/
@property({ type: Function, attribute: false })
configureMap?: (map: Map) => void;

Expand Down Expand Up @@ -86,7 +94,21 @@ export class FerrostarMap extends LitElement {
geolocateOnLoad: boolean = true;

routeAdapter: RouteAdapter | null = null;

/**
* The MapLibre map instance.
*
* This will be automatically initialized by default
* when the web component does its first update cycle.
* However, you can also explicitly set this value
* when initializing the web component to provide your own map instance.
*
* Note: If you set this property, you MUST also pass the map's container attribute
* via the slot!
*/
@property({ type: Object, attribute: false })
map: maplibregl.Map | null = null;

geolocateControl: GeolocateControl | null = null;
navigationController: NavigationController | null = null;
simulatedLocationMarker: maplibregl.Marker | null = null;
Expand All @@ -98,11 +120,17 @@ export class FerrostarMap extends LitElement {
[hidden] {
display: none !important;
}

#map {
#container {
height: 100%;
width: 100%;
}

#map, ::slotted(:first-child) {
height: 100%;
width: 100%;
display: block;
}

instructions-view {
top: 10px;
Expand Down Expand Up @@ -162,7 +190,7 @@ export class FerrostarMap extends LitElement {
if (changedProperties.has("locationProvider") && this.locationProvider) {
this.locationProvider.updateCallback = this.onLocationUpdated.bind(this);
}
if (this.map) {
if (this.map && this.map.loaded()) {
if (changedProperties.has("styleUrl")) {
this.map.setStyle(this.styleUrl);
}
Expand Down Expand Up @@ -190,11 +218,25 @@ export class FerrostarMap extends LitElement {
}

firstUpdated() {
// Skip initialization of the map if the user has supplied one already via a slot!
const slotChildren = this.shadowRoot!.querySelector('slot')?.assignedElements() || [];
if (slotChildren.length == 0 && this.map === null) {
this.initMap()
}
}

/**
* Initialize the MapLibre Map control.
*
* This is run by default on firstUpdated,
* but is skipped if the user adds a map of their own.
*/
initMap() {
this.map = new maplibregl.Map({
container: this.shadowRoot!.getElementById("map")!,
style: this.styleUrl
? this.styleUrl
: "https://demotiles.maplibre.org/style.json",
? this.styleUrl
: "https://demotiles.maplibre.org/style.json",
center: this.center ?? [0, 0],
pitch: this.pitch,
bearing: 0,
Expand Down Expand Up @@ -293,6 +335,7 @@ export class FerrostarMap extends LitElement {
},
});

// TODO: Configuration param where to insert the layer
this.map?.addLayer({
id: "route",
type: "line",
Expand Down Expand Up @@ -387,7 +430,8 @@ export class FerrostarMap extends LitElement {
<style>
${this.customStyles}
</style>
<div id="map">
<div id="container">
<slot id="map"></slot>
<instructions-view .tripState=${this._tripState}></instructions-view>
<div id="bottom-component">
<trip-progress-view
Expand Down
Loading