Skip to content

Commit 1812e00

Browse files
authored
feat: method querySourceFeatures (#16)
feat: add method querySourceFeatures
1 parent 9bd853a commit 1812e00

File tree

5 files changed

+134
-4
lines changed

5 files changed

+134
-4
lines changed

README.md

+27
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,33 @@ Remove a layer added with addLayer() by id.
689689
mapbox.removeLayer( id );
690690
```
691691

692+
### queryRenderedFeatures
693+
https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures
694+
Returns an array of GeoJSON Feature objects representing visible features that satisfy the query parameters.
695+
696+
```js
697+
mapbox
698+
.queryRenderedFeatures({
699+
point: {
700+
lat: 52.3701494345567,
701+
lng: 4.823684692382513,
702+
},
703+
layers: ['circle-with-source-object'],
704+
filter: ['==', ['get', 'querySample'], '2'],
705+
})
706+
.then((result) => console.log('query rendered features', result))
707+
```
708+
709+
### querySourceFeatures
710+
https://docs.mapbox.com/mapbox-gl-js/api/map/#map#querysourcefeatures
711+
Returns an array of GeoJSON Feature objects representing features within the specified vector tile or GeoJSON source that satisfy the query parameters.
712+
713+
```js
714+
mapbox
715+
.querySourceFeatures('source_id', { filter: ['==', ['get', 'querySample'], '2'] })
716+
.then((result) => console.log('query source features', result));
717+
```
718+
692719
### addLinePoint
693720
Dynamically add a point to a line.
694721

demo/app/main-view-model.ts

+4
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,10 @@ export class HelloWorldModel extends Observable {
481481
filter: ['all', ['==', '$id', '2']],
482482
})
483483
.then((result) => console.log('query rendered features', JSON.stringify(result)));
484+
485+
this.mapbox
486+
.querySourceFeatures('circle-with-source-object_source', { filter: ['==', ['get', 'querySample'], '2'] })
487+
.then((result) => console.log('query source features', JSON.stringify(result)));
484488
}, 3000);
485489
});
486490

src/mapbox.android.ts

+41
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
MapboxViewBase,
3434
OfflineRegion,
3535
QueryRenderedFeaturesOptions,
36+
QuerySourceFeaturesOptions,
3637
SetCenterOptions,
3738
SetTiltOptions,
3839
SetViewportOptions,
@@ -1538,6 +1539,46 @@ export class Mapbox extends MapboxCommon implements MapboxApi {
15381539
});
15391540
}
15401541

1542+
querySourceFeatures(sourceId: string, options?: QuerySourceFeaturesOptions): Promise<Feature[]> {
1543+
return new Promise((resolve, reject) => {
1544+
try {
1545+
if (!options) {
1546+
options = {};
1547+
}
1548+
1549+
const source = this._mapboxMapInstance.getStyle().getSource(sourceId);
1550+
if (!source) {
1551+
throw new Error(`Source with id "${sourceId}" not found.`);
1552+
}
1553+
1554+
let features;
1555+
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
1556+
if (source instanceof com.mapbox.mapboxsdk.style.sources.GeoJsonSource) {
1557+
features = source.querySourceFeatures(queryFilter);
1558+
} else if (source instanceof com.mapbox.mapboxsdk.style.sources.VectorSource) {
1559+
if (!options.sourceLayer) {
1560+
throw new Error('The option "sourceLayer" is required for vector sources.');
1561+
}
1562+
features = source.querySourceFeatures([options.sourceLayer], queryFilter);
1563+
} else {
1564+
throw new Error('Only sources from type "vector" or "geojson" are supported.');
1565+
}
1566+
1567+
const result = [];
1568+
for (let i = 0; i < features.size(); i++) {
1569+
const feature: com.mapbox.geojson.Feature = features.get(i);
1570+
result.push(JSON.parse(feature.toJson()));
1571+
}
1572+
resolve(result);
1573+
} catch (ex) {
1574+
if (Trace.isEnabled()) {
1575+
CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
1576+
}
1577+
reject(ex);
1578+
}
1579+
});
1580+
}
1581+
15411582
/**
15421583
*
15431584
* @deprecated

src/mapbox.common.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ export interface QueryRenderedFeaturesOptions {
4242

4343
// ------------------------------------------------------------
4444

45+
export interface QuerySourceFeaturesOptions {
46+
sourceLayer?: string;
47+
filter?: any[];
48+
}
49+
50+
// ------------------------------------------------------------
51+
4552
export interface Feature {
4653
id?: any;
4754
type: string;
@@ -615,6 +622,8 @@ export interface MapboxApi {
615622

616623
queryRenderedFeatures(options: QueryRenderedFeaturesOptions, nativeMap?: any): Promise<Feature[]>;
617624

625+
querySourceFeatures(sourceId: string, options?: QuerySourceFeaturesOptions, nativeMap?: any): Promise<Feature[]>;
626+
618627
addPolygon(options: AddPolygonOptions, nativeMap?: any): Promise<any>;
619628

620629
removePolygons(ids?: any[], nativeMap?: any): Promise<any>;
@@ -661,10 +670,10 @@ export interface MapboxApi {
661670

662671
getLayers(nativeMap?: any): Promise<LayerCommon[]>;
663672

664-
getImage(imageId: string, nativeMap?: any): Promise<ImageSource>
673+
getImage(imageId: string, nativeMap?: any): Promise<ImageSource>;
665674

666675
addImage(imageId: string, image: string, nativeMap?: any): Promise<void>;
667-
676+
668677
removeImage(imageId: string, nativeMap?: any): Promise<void>;
669678
}
670679

@@ -739,7 +748,9 @@ export interface MapboxViewApi {
739748
removeMarkers(options?: any): Promise<any>;
740749

741750
queryRenderedFeatures(options: QueryRenderedFeaturesOptions): Promise<Feature[]>;
742-
751+
752+
querySourceFeatures(sourceId: string, options?: QuerySourceFeaturesOptions): Promise<Feature[]>;
753+
743754
setOnMapClickListener(listener: (data: LatLng) => boolean): Promise<any>;
744755

745756
setOnMapLongClickListener(listener: (data: LatLng) => boolean): Promise<any>;
@@ -957,6 +968,9 @@ export abstract class MapboxViewCommonBase extends ContentView implements Mapbox
957968
queryRenderedFeatures(options: QueryRenderedFeaturesOptions): Promise<Feature[]> {
958969
return this.mapbox.queryRenderedFeatures(options, this.getNativeMapView());
959970
}
971+
querySourceFeatures(sourceId: string, options?: QuerySourceFeaturesOptions): Promise<Feature[]> {
972+
return this.mapbox.querySourceFeatures(sourceId, options, this.getNativeMapView());
973+
}
960974
addPolygon(options: AddPolygonOptions): Promise<any> {
961975
return this.mapbox.addPolygon(options, this.getNativeMapView());
962976
}

src/mapbox.ios.ts

+45-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
DownloadOfflineRegionOptions,
1414
Feature,
1515
LatLng,
16+
LayerCommon,
1617
ListOfflineRegionsOptions,
1718
MapStyle,
1819
MapboxApi,
@@ -22,6 +23,7 @@ import {
2223
MapboxViewBase,
2324
OfflineRegion,
2425
QueryRenderedFeaturesOptions,
26+
QuerySourceFeaturesOptions,
2527
SetCenterOptions,
2628
SetTiltOptions,
2729
SetViewportOptions,
@@ -32,7 +34,6 @@ import {
3234
UserLocationCameraMode,
3335
Viewport,
3436
telemetryProperty,
35-
LayerCommon,
3637
} from './mapbox.common';
3738

3839
import { iOSNativeHelper } from '@nativescript/core/utils';
@@ -1422,6 +1423,49 @@ export class Mapbox extends MapboxCommon implements MapboxApi {
14221423
});
14231424
}
14241425

1426+
querySourceFeatures(sourceId: string, options?: QuerySourceFeaturesOptions, nativeMap?): Promise<Feature[]> {
1427+
return new Promise((resolve, reject) => {
1428+
try {
1429+
const theMap: MGLMapView = nativeMap || this._mapboxViewInstance;
1430+
if (!options) {
1431+
options = {};
1432+
}
1433+
1434+
const source = theMap.style.sourceWithIdentifier(sourceId);
1435+
if (!source) {
1436+
throw new Error(`Source with id "${sourceId}" not found.`);
1437+
}
1438+
1439+
let features;
1440+
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
1441+
if (source instanceof MGLShapeSource) {
1442+
features = source.featuresMatchingPredicate(queryFilter);
1443+
} else if (source instanceof MGLVectorTileSource) {
1444+
if (!options.sourceLayer) {
1445+
throw new Error('The option "sourceLayer" is required for vector sources.');
1446+
}
1447+
const sourceLayerIds = options.sourceLayer ? NSSet.setWithArray<string>(iOSNativeHelper.collections.jsArrayToNSArray([options.sourceLayer])) : null;
1448+
features = source.featuresInSourceLayersWithIdentifiersPredicate(sourceLayerIds, queryFilter);
1449+
} else {
1450+
throw new Error('Only sources from type "vector" or "geojson" are supported.');
1451+
}
1452+
1453+
const result = [];
1454+
for (let i = 0; i < features.count; i++) {
1455+
const feature: MGLFeature = features.objectAtIndex(i);
1456+
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
1457+
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding) as any));
1458+
}
1459+
resolve(result);
1460+
} catch (ex) {
1461+
if (Trace.isEnabled()) {
1462+
CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
1463+
}
1464+
reject(ex);
1465+
}
1466+
});
1467+
}
1468+
14251469
/**
14261470
* @deprecated
14271471
*/

0 commit comments

Comments
 (0)