Skip to content

Commit 6886f2a

Browse files
committed
feat: support adding images from HTTP and base64 data URLs
1 parent 48aa53e commit 6886f2a

File tree

5 files changed

+54
-28
lines changed

5 files changed

+54
-28
lines changed

README.md

+28
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,34 @@ Remove a layer added with addLayer() by id.
800800
mapbox.removeLayer( id );
801801
```
802802

803+
### addImage
804+
Add an image with `addImage` by providing an id and image path.
805+
806+
The image path can be either:
807+
1. a resource path, which will be loaded using [`fromFileOrResourceSync`](https://docs.nativescript.org/api/class/ImageSource#fromfileorresourcesync)
808+
809+
```js
810+
mapbox.addImage('my-resource', 'res://my-resource');
811+
```
812+
813+
2. a local path, which will be loaded using [`fromFileOrResourceSync`](https://docs.nativescript.org/api/class/ImageSource#fromfileorresourcesync)
814+
815+
```js
816+
mapbox.addImage('my-local-image', '~/my-local-image.png');
817+
```
818+
819+
3. a base64 data URL, which will be loaded using [`fromBase64Sync`](https://docs.nativescript.org/api/class/ImageSource#frombase64sync)
820+
821+
```js
822+
mapbox.addImage('my-base64-image', 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=');
823+
```
824+
825+
4. an HTTP URL, which will be loaded using [`fromUrl`](https://docs.nativescript.org/api/class/ImageSource#fromurl)
826+
827+
```js
828+
mapbox.addImage('my-web-image', 'https://picsum.photos/200');
829+
```
830+
803831
### queryRenderedFeatures
804832
https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures
805833
Returns an array of GeoJSON Feature objects representing visible features that satisfy the query parameters.

src/ui-mapbox/common.ts

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Color, ContentView, ImageSource, Property, Trace, booleanConverter } from '@nativescript/core';
1+
import { Color, ContentView, ImageSource, Property, Trace, Utils, booleanConverter } from '@nativescript/core';
22

33
export * from './geo.utils';
44
export * from './expression/expression-parser';
@@ -712,7 +712,7 @@ export interface MapboxApi {
712712

713713
getImage(imageId: string, nativeMap?: any): Promise<ImageSource>;
714714

715-
addImage(imageId: string, image: string, nativeMap?: any): Promise<void>;
715+
addImage(imageId: string, imagePath: string, nativeMap?: any): Promise<void>;
716716

717717
removeImage(imageId: string, nativeMap?: any): Promise<void>;
718718
project(data: LatLng): { x: number; y: number };
@@ -773,6 +773,17 @@ export abstract class MapboxCommon implements MapboxCommonApi {
773773
async hasFineLocationPermission() {
774774
return true;
775775
}
776+
777+
protected async fetchImageSource(imagePath: string): Promise<ImageSource> {
778+
if (Utils.isDataURI(imagePath)) {
779+
const [, base64] = imagePath.split(';base64,');
780+
return ImageSource.fromBase64Sync(base64);
781+
}
782+
if (Utils.isFileOrResourcePath(imagePath)) {
783+
return ImageSource.fromFileOrResourceSync(imagePath);
784+
}
785+
return ImageSource.fromUrl(imagePath);
786+
}
776787
}
777788

778789
// ------------------------------------------------------------
@@ -872,7 +883,7 @@ export interface MapboxViewApi {
872883

873884
getImage(imageId: string, nativeMap?: any): Promise<ImageSource>;
874885

875-
addImage(imageId: string, image: string, nativeMap?: any): Promise<void>;
886+
addImage(imageId: string, imagePath: string, nativeMap?: any): Promise<void>;
876887

877888
removeImage(imageId: string, nativeMap?: any): Promise<void>;
878889

@@ -1060,8 +1071,8 @@ export abstract class MapboxViewCommonBase extends ContentView implements Mapbox
10601071
getImage(imageId: string): Promise<ImageSource> {
10611072
return this.mapbox.getImage(imageId, this.getNativeMapView());
10621073
}
1063-
addImage(imageId: string, image: string): Promise<void> {
1064-
return this.mapbox.addImage(imageId, image, this.getNativeMapView());
1074+
addImage(imageId: string, imagePath: string): Promise<void> {
1075+
return this.mapbox.addImage(imageId, imagePath, this.getNativeMapView());
10651076
}
10661077
removeImage(imageId: string): Promise<void> {
10671078
return this.mapbox.removeImage(imageId, this.getNativeMapView());

src/ui-mapbox/index.android.ts

+5-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { request } from '@nativescript-community/perms';
8-
import { AndroidApplication, Application, Color, File, Http, Image, ImageSource, Trace, Utils, knownFolders, path } from '@nativescript/core';
8+
import { AndroidApplication, Application, Color, File, Http, ImageSource, Trace, Utils, knownFolders, path } from '@nativescript/core';
99
import { ExpressionParser } from './expression/expression-parser';
1010
import { Layer, LayerFactory } from './layers/layer-factory';
1111
import {
@@ -27,7 +27,6 @@ import {
2727
MapboxApi,
2828
MapboxCommon,
2929
MapboxMarker,
30-
MapboxTraceCategory,
3130
MapboxViewBase,
3231
OfflineRegion,
3332
QueryRenderedFeaturesOptions,
@@ -1223,23 +1222,18 @@ export class Mapbox extends MapboxCommon implements MapboxApi {
12231222
});
12241223
}
12251224

1226-
async addImage(imageId: string, image: string, nativeMap?: any): Promise<void> {
1227-
return new Promise((resolve, reject) => {
1225+
async addImage(imageId: string, imagePath: string, nativeMap?: any): Promise<void> {
1226+
return new Promise(async (resolve, reject) => {
12281227
const theMap = nativeMap || this._mapboxMapInstance;
12291228

12301229
if (!theMap) {
12311230
reject('No map has been loaded');
12321231
return;
12331232
}
12341233

1235-
if (!image.startsWith('res://')) {
1236-
image = path.join(knownFolders.currentApp().path, image.replace('~/', ''));
1237-
}
1238-
1239-
const img = ImageSource.fromFileOrResourceSync(image);
1240-
12411234
try {
1242-
theMap.getStyle().addImage(imageId, img.android);
1235+
const imageSource = await this.fetchImageSource(imagePath);
1236+
theMap.getStyle().addImage(imageId, imageSource.android);
12431237
resolve();
12441238
} catch (ex) {
12451239
reject('Error during addImage: ' + ex);

src/ui-mapbox/index.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export declare class Mapbox extends MapboxCommon implements MapboxApi {
4343
onDestroy(nativeMap?: any): Promise<void>;
4444
setMapStyle(style: string | MapStyle, nativeMap?: any): Promise<void>;
4545
getImage(imageId: string, nativeMap?: any): Promise<ImageSource>;
46-
addImage(imageId: string, image: string, nativeMap?: any): Promise<void>;
46+
addImage(imageId: string, imagePath: string, nativeMap?: any): Promise<void>;
4747
removeImage(imageId: string, nativeMap?: any): Promise<void>;
4848
addMarkers(markers: MapboxMarker[], nativeMap?: any): Promise<void>;
4949
removeMarkers(ids?: any, nativeMap?: any): Promise<void>;

src/ui-mapbox/index.ios.ts

+4-11
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
MapboxApi,
1919
MapboxCommon,
2020
MapboxMarker,
21-
MapboxTraceCategory,
2221
MapboxViewBase,
2322
OfflineRegion,
2423
QueryRenderedFeaturesOptions,
@@ -1216,24 +1215,18 @@ export class Mapbox extends MapboxCommon implements MapboxApi {
12161215
});
12171216
}
12181217

1219-
async addImage(imageId: string, image: string, nativeMap?: any): Promise<void> {
1220-
return new Promise((resolve, reject) => {
1218+
async addImage(imageId: string, imagePath: string, nativeMap?: any): Promise<void> {
1219+
return new Promise(async (resolve, reject) => {
12211220
const theMap: MGLMapView = nativeMap || this._mapboxViewInstance;
12221221

12231222
if (!theMap) {
12241223
reject('No map has been loaded');
12251224
return;
12261225
}
12271226

1228-
if (!image.startsWith('res://')) {
1229-
const appPath = knownFolders.currentApp().path;
1230-
image = appPath + '/' + image.replace('~/', '');
1231-
}
1232-
1233-
const img = ImageSource.fromFileOrResourceSync(image);
1234-
12351227
try {
1236-
theMap.style.setImageForName(img.ios, imageId);
1228+
const imageSource = await this.fetchImageSource(imagePath);
1229+
theMap.style.setImageForName(imageSource.ios, imageId);
12371230
resolve();
12381231
} catch (ex) {
12391232
reject('Error during addImage: ' + ex);

0 commit comments

Comments
 (0)