Skip to content

Commit

Permalink
feat: add setFeatureState / getFeatureState / removeFeatureState
Browse files Browse the repository at this point in the history
  • Loading branch information
Gnative committed Jul 5, 2023
1 parent eef0506 commit 6224e83
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,45 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
}
}

fun setFeatureState(
sourceId: String,
sourceLayerId: String?,
featureId: String,
state: Map<String, Any>
) {
if (mMap == null) {
Logger.e("MapView", "setFeatureState, map is null")
return
}
mMap.setFeatureState(sourceId, sourceLayerId, featureId, state)
}

fun getFeatureState(
callbackID: String?,
sourceId: String,
sourceLayerId: String?,
featureId: String
) {
val result = mMap?.getFeatureState(sourceId, sourceLayerId, featureId) { result ->
sendResponse(callbackID) { response ->
if (result != null) {
response.putString("data", "test")
} else {
response.putNull("data")
}
}
}
}

fun removeFeatureState(
sourceId: String,
sourceLayerId: String?,
featureId: String,
stateKey: String?
) {
mMap?.removeFeatureState(sourceId, sourceLayerId, featureId, stateKey)
}

// endregion

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,30 @@ open class RCTMGLMapViewManager(context: ReactApplicationContext) :
args!!.getString(3)
);
}
"setFeatureState" -> {
mapView!!.setFeatureState(
args!!.getString(1),
args!!.getString(2),
args!!.getString(3),
args!!.getString(4),
);
}
"getFeatureState" -> {
mapView!!.getFeatureState(
args!!.getString(0),
args!!.getString(1),
args!!.getString(2),
args!!.getString(3),
);
}
"removeFeatureState" -> {
mapView!!.removeFeatureState(
args!!.getString(1),
args!!.getString(2),
args!!.getString(3),
args!!.getString(4)
);
}
"queryRenderedFeaturesAtPoint" -> {
mapView.queryRenderedFeaturesAtPoint(
args!!.getString(0),
Expand Down
154 changes: 154 additions & 0 deletions example/src/examples/V10/SetFeatureState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import React from 'react';
import {Alert, View, Text} from 'react-native';
import MapboxGL from '@rnmapbox/maps';

import BaseExamplePropTypes from '../common/BaseExamplePropTypes';
import Page from '../common/Page';
import Bubble from '../common/Bubble';

const GeoJSON = {
"type": "FeatureCollection",
"features": [
{
"id": "square",
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
[
[
8.307645244914198,
48.49063431500133
],
[
8.307645244914198,
45.57348217729648
],
[
12.538446560172616,
45.57348217729648
],
[
12.538446560172616,
48.49063431500133
],
[
8.307645244914198,
48.49063431500133
]
]
],
"type": "Polygon"
}
}
]
}

const styles = {
mapView: { flex: 1 },
bubbles:{
position: 'absolute',
left:0,
right:0,
bottom: 50,
padding:10,
},
bubble :{
position: 'relative',
padding:0,
top:0,
left:0,
right:0,
bottom:0,
margin:0,
marginBottom: 10
}
};

class SerFeatureState extends React.Component {
static propTypes = {
...BaseExamplePropTypes,
};

state = {
active: null,
};

onPress = () => {
this.setState(
{
active: !this.state.active,
},
() => {
this._map.setFeatureState('customShapeSource', 'customSourceLayer', 'square', { active: this.state.active } );
},
);
};

onGetFeatureStatePress = async () => {
const featureState = await this._map.getFeatureState('customShapeSource', 'customSourceLayer', 'square', 'active')
console.log(featureState);
Alert.alert("Feature state", JSON.stringify(featureState));
}

onRemoveFeatureStatePress = () => {
this._map.removeFeatureState('customShapeSource', 'customSourceLayer', 'square')
this.setState({
active: null
})
}

render() {
return (
<Page {...this.props}>
<MapboxGL.MapView
ref={(c) => (this._map = c)}
style={styles.mapView}
>
<MapboxGL.Camera
zoomLevel={4}
centerCoordinate={[
10.36503690835832,
47.036730450390394
]}
animationMode="none"
/>
<MapboxGL.ShapeSource
id="customShapeSource"
shape={GeoJSON}
onPress={(e) => {
console.log(`ShapeSource onPress: ${e.features}`, e.features);
}}
>
<MapboxGL.FillLayer
id="customSourceFill"
sourceLayerID="customSourceLayer"
style={{
fillColor: [
'case',
['boolean', ['feature-state', 'active'], false],
'green',
'red',
],
fillAntialias: true,
}}
/>
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
<View style={styles.bubbles}>
<Bubble style={styles.bubble} onPress={this.onPress}>
<Text>Toggle Feature State</Text>
</Bubble>
<Bubble style={styles.bubble} onPress={this.onRemoveFeatureStatePress}>
<Text>Remove Feature State</Text>
</Bubble>
<Bubble style={styles.bubble} onPress={this.onGetFeatureStatePress}>
<Text>Get Feature State</Text>
</Bubble>
</View>
</Page>
);
}
}

export default SerFeatureState;
2 changes: 2 additions & 0 deletions example/src/scenes/GroupAndItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import MapHandlers from '../examples/V10/MapHandlers';
import Markers from '../examples/V10/Markers';
import QueryTerrainElevation from '../examples/V10/QueryTerrainElevation';
import TerrainSkyAtmosphere from '../examples/V10/TerrainSkyAtmosphere';
import SetFeatureState from '../examples/V10/SetFeatureState'

const MostRecentExampleKey = '@recent_example';

Expand Down Expand Up @@ -265,6 +266,7 @@ const Examples = new ExampleGroup('React Native Mapbox', [
new ExampleItem('Query Terrain Elevation', QueryTerrainElevation),
new ExampleItem('Camera Animation', CameraAnimation),
new ExampleItem('Map Handlers', MapHandlers),
new ExampleItem('Set Feature State', SetFeatureState),
]),
new ExampleGroup('Map', [
new ExampleItem('Show Map', ShowMap),
Expand Down
23 changes: 23 additions & 0 deletions ios/RCTMGL-v10/RCTMGLMapViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,29 @@ @interface RCT_EXTERN_REMAP_MODULE(RCTMGLMapView, RCTMGLMapViewManager, RCTViewM
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(setFeatureState:(nonnull NSNumber *)reactTag
sourceId:(nonnull NSString*)sourceId
sourceLayerId:(nullable NSString*)sourceLayerId
featureId:(nonnull NSString*)featureId
state:(nonnull NSDictionary<NSString *, id> *)state
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(getFeatureState:(nonnull NSNumber *)reactTag
sourceId:(nonnull NSString*)sourceId
sourceLayerId:(nullable NSString*)sourceLayerId
featureId:(nonnull NSString*)featureId
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(removeFeatureState:(nonnull NSNumber *)reactTag
sourceId:(nonnull NSString*)sourceId
sourceLayerId:(nullable NSString*)sourceLayerId
featureId:(nonnull NSString*)featureId
stateKey:(nullable NSString*)stateKey
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(getCenter:(nonnull NSNumber*)reactTag
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
Expand Down
49 changes: 49 additions & 0 deletions ios/RCTMGL-v10/RCTMGLMapViewManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,55 @@ extension RCTMGLMapViewManager {
}
}

@objc
func setFeatureState(_ reactTag: NSNumber,
sourceId: String,
sourceLayerId: String?,
featureId: String,
state: [String: Any],
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) -> Void {
withMapboxMap(reactTag, name:"setFeatureState", rejecter: rejecter) { mapboxMap in
mapboxMap.setFeatureState(sourceId: sourceId, sourceLayerId: sourceLayerId, featureId: featureId, state:state)
resolver(nil)
}
}

@objc
func getFeatureState(_ reactTag: NSNumber,
sourceId: String,
sourceLayerId: String?,
featureId: String,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) -> Void {
withMapboxMap(reactTag, name:"getFeatureState", rejecter: rejecter) { mapboxMap in
mapboxMap.getFeatureState(sourceId: sourceId, sourceLayerId: sourceLayerId, featureId: featureId) { result in
switch result {
case .success(let featureState):
// Handle success case, e.g., invoke resolver with the feature state
resolver(featureState)
case .failure(let error):
// Handle failure case, e.g., invoke rejecter with the error
rejecter("Error retrieving feature state", error.localizedDescription, error)
}
}
}
}

@objc
func removeFeatureState(_ reactTag: NSNumber,
sourceId: String,
sourceLayerId: String?,
featureId: String,
stateKey: String?,
resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock) -> Void {
withMapboxMap(reactTag, name:"getFeatureState", rejecter: rejecter) { mapboxMap in
mapboxMap.removeFeatureState(sourceId: sourceId, sourceLayerId: sourceLayerId, featureId: featureId, stateKey:stateKey)
resolver(nil)
}
}

@objc
func getCenter(_ reactTag: NSNumber,
resolver: @escaping RCTPromiseResolveBlock,
Expand Down
Loading

0 comments on commit 6224e83

Please sign in to comment.