diff --git a/demo/app/main-page.ts b/demo/app/main-page.ts index a678433..9c00076 100644 --- a/demo/app/main-page.ts +++ b/demo/app/main-page.ts @@ -53,7 +53,17 @@ function onMapReady(args) { console.log("'Nice location' marker callout tapped"); } }] - ); + ).then(() => { + console.log("Markers added"); + setTimeout(() => { + map.queryRenderedFeatures({ + point: { + lat: 52.3602160, + lng: 4.8891680 + } + }).then(result => console.log(JSON.stringify(result))); + }, 1000); + }); setTimeout(() => { map.setViewport( diff --git a/src/mapbox.android.ts b/src/mapbox.android.ts index 988bbdf..150a9ef 100755 --- a/src/mapbox.android.ts +++ b/src/mapbox.android.ts @@ -13,6 +13,7 @@ import { AnimateCameraOptions, DeleteOfflineRegionOptions, DownloadOfflineRegionOptions, + Feature, LatLng, ListOfflineRegionsOptions, MapboxApi, @@ -21,6 +22,7 @@ import { MapboxViewBase, MapStyle, OfflineRegion, + QueryRenderedFeaturesOptions, SetCenterOptions, SetTiltOptions, SetViewportOptions, @@ -805,6 +807,40 @@ export class Mapbox extends MapboxCommon implements MapboxApi { }); } + queryRenderedFeatures(options: QueryRenderedFeaturesOptions, nativeMap?): Promise> { + return new Promise((resolve, reject) => { + try { + const theMap = nativeMap || _mapbox; + const point = options.point; + if (point === undefined) { + reject("Please set the 'point' parameter"); + return; + } + const mapboxPoint = new com.mapbox.mapboxsdk.geometry.LatLng(options.point.lat, options.point.lng); + const screenLocation = theMap.mapboxMap.getProjection().toScreenLocation(mapboxPoint); + if (theMap.mapboxMap.queryRenderedFeatures) { + const features /* List */ = theMap.mapboxMap.queryRenderedFeatures(screenLocation, null, options.layerIds); + const result:Array = []; + for (let i = 0; i < features.size(); i++) { + // see https://www.mapbox.com/android-docs/api/mapbox-java/libjava-geojson/3.4.1/com/mapbox/geojson/Feature.html + const feature = features.get(i); + result.push({ + id: feature.id(), + type: feature.type(), + properties: JSON.parse(feature.properties().toString()) + }); + } + resolve(result); + } else { + reject("Feature not supported by this Mapbox version"); + } + } catch (ex) { + console.log("Error in mapbox.queryRenderedFeatures: " + ex); + reject(ex); + } + }); + } + addPolygon(options: AddPolygonOptions, nativeMap?): Promise { return new Promise((resolve, reject) => { try { diff --git a/src/mapbox.common.ts b/src/mapbox.common.ts index d0290cf..ce8050f 100755 --- a/src/mapbox.common.ts +++ b/src/mapbox.common.ts @@ -18,6 +18,17 @@ export interface LatLng { lng: number; } +export interface QueryRenderedFeaturesOptions { + point: LatLng; + layerIds?: string[]; +} + +export interface Feature { + id: any; + type?: string; + properties: Object; +} + export interface AddPolygonOptions { /** * Set this in case you want to later pass it to 'removePolygons'. TODO doesn't exist yet ;) @@ -347,6 +358,8 @@ export interface MapboxApi { trackUser(options: TrackUserOptions, nativeMap?: any): Promise; + queryRenderedFeatures(options: QueryRenderedFeaturesOptions, nativeMap?: any): Promise>; + addPolygon(options: AddPolygonOptions, nativeMap?: any): Promise; removePolygons(ids?: Array, nativeMap?: any): Promise; @@ -450,6 +463,8 @@ export interface MapboxViewApi { removeMarkers(options?: any): Promise; + queryRenderedFeatures(options: QueryRenderedFeaturesOptions): Promise>; + setOnMapClickListener(listener: (data: LatLng) => void): Promise; setOnMapLongClickListener(listener: (data: LatLng) => void): Promise; @@ -486,6 +501,8 @@ export interface MapboxViewApi { trackUser(options: TrackUserOptions): Promise; + queryRenderedFeatures(options: QueryRenderedFeaturesOptions): Promise>; + addPolygon(options: AddPolygonOptions): Promise; removePolygons(ids?: Array): Promise; @@ -584,6 +601,10 @@ export abstract class MapboxViewCommonBase extends ContentView implements Mapbox return this.mapbox.trackUser(options, this.getNativeMapView()); } + queryRenderedFeatures(options: QueryRenderedFeaturesOptions): Promise> { + return this.mapbox.queryRenderedFeatures(options, this.getNativeMapView()); + } + addPolygon(options: AddPolygonOptions): Promise { return this.mapbox.addPolygon(options, this.getNativeMapView()); } diff --git a/src/mapbox.ios.ts b/src/mapbox.ios.ts index 5d667b2..f2e9aff 100755 --- a/src/mapbox.ios.ts +++ b/src/mapbox.ios.ts @@ -11,6 +11,7 @@ import { AnimateCameraOptions, DeleteOfflineRegionOptions, DownloadOfflineRegionOptions, + Feature, LatLng, ListOfflineRegionsOptions, MapboxApi, @@ -19,6 +20,7 @@ import { MapboxViewBase, MapStyle, OfflineRegion, + QueryRenderedFeaturesOptions, SetCenterOptions, SetTiltOptions, SetViewportOptions, @@ -438,6 +440,36 @@ export class Mapbox extends MapboxCommon implements MapboxApi { }); } + queryRenderedFeatures(options: QueryRenderedFeaturesOptions, nativeMap?): Promise> { + return new Promise((resolve, reject) => { + try { + const theMap: MGLMapView = nativeMap || _mapbox.mapView; + const point = options.point; + if (point === undefined) { + reject("Please set the 'point' parameter"); + return; + } + + const {x, y} = theMap.convertCoordinateToPointToView({latitude: point.lat, longitude: point.lng}, theMap); + const features = theMap.visibleFeaturesAtPoint({x, y}); + + const result = []; + for (let i = 0; i < features.count; i++) { + let feature: MGLFeature = features.objectAtIndex(i); + result.push({ + id: feature.identifier, + properties: JSON.parse(feature.attributes.toString()), + }); + } + + resolve(result); + } catch (ex) { + console.log("Error in mapbox.queryRenderedFeatures: " + ex); + reject(ex); + } + }); + } + addPolygon(options: AddPolygonOptions, nativeMap?): Promise { return new Promise((resolve, reject) => { const theMap = nativeMap || _mapbox.mapView;