diff --git a/README.md b/README.md index 0be5af9c..a170aa88 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Radar.initialize('prj_test_pk_...', { /* options */ }); Add the following script in your `html` file ```html - + ``` Then initialize the Radar SDK @@ -73,8 +73,8 @@ To create a map, first initialize the Radar SDK with your publishable key. Then ```html - - + + @@ -98,8 +98,8 @@ To create an autocomplete input, first initialize the Radar SDK with your publis ```html - - + + @@ -130,8 +130,8 @@ To power [geofencing](https://radar.com/documentation/geofencing/overview) exper ```html - - + + diff --git a/package-lock.json b/package-lock.json index fe0b5715..ece66673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "radar-sdk-js", - "version": "4.4.1", + "version": "4.5.0-beta.0", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 39b01b49..bcce4715 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "radar-sdk-js", - "version": "4.4.1", + "version": "4.5.0-beta.0", "description": "Web Javascript SDK for Radar, location infrastructure for mobile and web apps.", "homepage": "https://radar.com", "type": "module", diff --git a/src/ui/RadarMap.ts b/src/ui/RadarMap.ts index 4ccfcbdf..7aabe34c 100644 --- a/src/ui/RadarMap.ts +++ b/src/ui/RadarMap.ts @@ -80,6 +80,7 @@ const getStyle = (options: RadarOptions, mapOptions: RadarMapOptions) => { class RadarMap extends maplibregl.Map { _markers: RadarMarker[] = []; _features: RadarMapFeature[] = []; + _defaultMarker?: string; constructor(radarMapOptions: RadarMapOptions) { const config = Config.get(); @@ -152,6 +153,16 @@ class RadarMap extends maplibregl.Map { }; this.on('resize', onResize); this.on('load', onResize); + + // parse radar metadata from style + this.on('style.load', () => { + const style = this.getStyle(); + const metadata: any = style.metadata || {}; + + if (metadata['radar:marker']) { // default marker associated with custom style + this._defaultMarker = metadata['radar:marker']; + } + }); } addMarker(marker: RadarMarker) { diff --git a/src/ui/RadarMarker.ts b/src/ui/RadarMarker.ts index d76342f2..64e7e984 100644 --- a/src/ui/RadarMarker.ts +++ b/src/ui/RadarMarker.ts @@ -89,6 +89,7 @@ const defaultMarkerOptions: RadarMarkerOptions = { }; class RadarMarker extends maplibregl.Marker { + _options: RadarMarkerOptions; _map!: RadarMap; constructor(markerOptions: RadarMarkerOptions) { @@ -107,83 +108,11 @@ class RadarMarker extends maplibregl.Marker { super(maplibreOptions); + this._options = markerOptions; + // handle marker images (Radar marker, or custom URL) if (markerOptions.marker || markerOptions.url) { - const originalElement = this._element.cloneNode(true); - this._element.childNodes.forEach((child) => { - child.remove(); - }); - - const onSuccess = (blob: Blob) => { - const markerObject = URL.createObjectURL(blob); - this._element.replaceChildren(createImageElement({ - width: markerOptions.width, - height: markerOptions.height, - url: markerObject, - })); - }; - - const onError = (err: any) => { - Logger.error(`Could not load marker: ${err.message} - falling back to default marker`); - IMAGE_CACHE.set(markerOptions.url as string, 'failed'); // mark as failed - this._element.replaceChildren(...Array.from(originalElement.childNodes)); - } - - // custom URL image - if (markerOptions.url) { - const loadImage = () => { // fetch marker data from URL - fetch(markerOptions.url as string) - .then(res => { - if (res.status === 200) { - res.blob() - .then((data) => { - IMAGE_CACHE.set(markerOptions.url as string, data); // cache data - onSuccess(data); - }) - .catch(onError); - } else { - onError(new Error(res.statusText)); - } - }) - .catch(onError) - }; - - // attempt to use cached data, otherwise fetch marker image data from URL - useCachedImage(markerOptions.url) - .then(onSuccess) - .catch((reason: 'miss' | 'timedout' | 'failed' | Error) => { - if (reason !== 'miss') { - Logger.debug(`RadarMarker: cache lookup for ${markerOptions.url}: ${reason}`); - } - loadImage(); - }); - } - - // Radar hosted image - if (markerOptions.marker) { - const loadMarker = () => { - Http.request({ - method: 'GET', - version: 'maps', - path: `markers/${markerOptions.marker}`, - responseType: 'blob', - }) - .then(({ data }) => { - IMAGE_CACHE.set(markerOptions.url as string, data); // cache data - onSuccess(data) - }) - .catch(onError); - }; - - useCachedImage(markerOptions.marker as string) - .then(onSuccess) - .catch((reason: 'miss' | 'timedout' | 'failed' | Error) => { - if (reason !== 'miss') { - Logger.debug(`RadarMarker: cache lookup for ${markerOptions.marker} ${reason}`); - } - loadMarker(); - }); - } + this.getCustomImage(markerOptions); } // handle deprecated popup options @@ -238,7 +167,98 @@ class RadarMarker extends maplibregl.Marker { } } + // load marker image from a URL or as a Radar asset (custom styles) + getCustomImage(markerOptions: RadarMarkerOptions) { + const originalElement = this._element.cloneNode(true); + this._element.childNodes.forEach((child) => { + child.remove(); + }); + + const onSuccess = (blob: Blob) => { + const markerObject = URL.createObjectURL(blob); + this._element.replaceChildren(createImageElement({ + width: markerOptions.width, + height: markerOptions.height, + url: markerObject, + })); + }; + + const onError = (err: any) => { + Logger.error(`Could not load marker: ${err.message} - falling back to default marker`); + IMAGE_CACHE.set(markerOptions.url as string, 'failed'); // mark as failed + this._element.replaceChildren(...Array.from(originalElement.childNodes)); + } + + // custom URL image + if (markerOptions.url) { + const loadImage = () => { // fetch marker data from URL + fetch(markerOptions.url as string) + .then(res => { + if (res.status === 200) { + res.blob() + .then((data) => { + IMAGE_CACHE.set(markerOptions.url as string, data); // cache data + onSuccess(data); + }) + .catch(onError); + } else { + onError(new Error(res.statusText)); + } + }) + .catch(onError) + }; + + // attempt to use cached data, otherwise fetch marker image data from URL + useCachedImage(markerOptions.url) + .then(onSuccess) + .catch((reason: 'miss' | 'timedout' | 'failed' | Error) => { + if (reason !== 'miss') { + Logger.debug(`RadarMarker: cache lookup for ${markerOptions.url}: ${reason}`); + } + loadImage(); + }); + } + + // Radar hosted image + if (markerOptions.marker) { + const loadMarker = () => { + Http.request({ + method: 'GET', + version: 'maps', + path: `markers/${markerOptions.marker}`, + responseType: 'blob', + }) + .then(({ data }) => { + IMAGE_CACHE.set(markerOptions.marker as string, data); // cache data + onSuccess(data) + }) + .catch(onError); + }; + + useCachedImage(markerOptions.marker as string) + .then(onSuccess) + .catch((reason: 'miss' | 'timedout' | 'failed' | Error) => { + if (reason !== 'miss') { + Logger.debug(`RadarMarker: cache lookup for ${markerOptions.marker} ${reason}`); + } + loadMarker(); + }); + } + } + addTo(map: RadarMap) { + // use default marker associated with map style, if none is provided in options + // (and custom style has an associated marker) + const markerOptions = this._options; + if (!markerOptions.url && !markerOptions.marker && !markerOptions.color) { + if (map._defaultMarker) { + this.getCustomImage({ + ...markerOptions, + marker: map._defaultMarker, + }); + } + } + map.addMarker(this); return super.addTo(map); } diff --git a/src/version.ts b/src/version.ts index 45efae50..cd1e34ba 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export default '4.4.1'; +export default '4.5.0-beta.0';