如何检查标记是否在反应本机地图中屏幕上显示的区域中
how to check if Marker is in the region displayed on the screen in react native maps
我在底部的 FlatList 中水平显示了项目列表,并在地图中显示了所有标记。现在用户可以自由缩放 in/out 地图或单击任何标记,底部的 FlatList 将滚动到项目。用户还可以滚动 FlatList 并根据索引标记进行选择。当列表很大且用户手动放大地图时。
现在的问题是用户可以缩放地图上的任何位置,当用户滑动下面的列表并更改项目索引时,我需要能够检查该标记是否在屏幕上,如果不在屏幕上则缩放到该标记.
所以我可以使用以下代码手动缩放区域。
const animateMapToRegion = (region = null, duration = 1000) => {
if (region) {
mapRef.current.animateToRegion(region, duration);
}
};
仅当屏幕上没有标记时才需要制作此动画。我检查了文档,但找不到任何功能来检查标记是否在屏幕上。
我只想在标记在屏幕上不可见时设置动画。请协助。
我最后为 iOS 和 Android 添加了我自己的实现。
在AIRGoogleMapManager.m
中添加以下方法
RCT_EXPORT_METHOD(isMarkerWithinScreen:(nonnull NSNumber *)reactTag
position:(CLLocationCoordinate2D)position
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSVisibleRegion region = [mapView.projection visibleRegion];
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
resolve(@{@"visible": @([bounds containsCoordinate:position])});
}
}];
}
在AirMapModule.java
中添加以下方法
@ReactMethod
public void isMarkerWithinScreen(final int tag, ReadableMap coordinate, final Promise promise) {
final ReactApplicationContext context = getReactApplicationContext();
final double lat = coordinate.getDouble("latitude");
final double lng = coordinate.getDouble("longitude");
final LatLng position = new LatLng(lat,lng);
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock()
{
@Override
public void execute(NativeViewHierarchyManager nvhm)
{
AirMapView view = (AirMapView) nvhm.resolveView(tag);
if (view == null)
{
promise.reject("AirMapView not found");
return;
}
if (view.map == null)
{
promise.reject("AirMapView.map is not valid");
return;
}
LatLngBounds currentScreen = view.map.getProjection().getVisibleRegion().latLngBounds;
boolean onScreen = currentScreen.contains(position);
WritableMap visibleJson = new WritableNativeMap();
visibleJson.putBoolean("visible", onScreen);
promise.resolve(visibleJson);
}
});
}
add 最后在node_modules/react-native-maps/lib/components/MapView.js
下面添加
isMarkerWithinScreen(marker) {
if (Platform.OS === 'android') {
return NativeModules.AirMapModule.isMarkerWithinScreen(
this._getHandle(),
marker.coordinate
);
} else if (Platform.OS === 'ios') {
return this._runCommand('isMarkerWithinScreen', [marker.coordinate]);
}
return Promise.reject('isMarkerWithinScreen not supported on this platform');
}
现在您可以将其用作,
const marker = //your marker;
const visibility = await mapRef.current.isMarkerWithinScreen(marker);
const {visible} = visibility;
console.log('visible-->', visible); //If visible is true marker is on screen otherwise its not.
我在底部的 FlatList 中水平显示了项目列表,并在地图中显示了所有标记。现在用户可以自由缩放 in/out 地图或单击任何标记,底部的 FlatList 将滚动到项目。用户还可以滚动 FlatList 并根据索引标记进行选择。当列表很大且用户手动放大地图时。
现在的问题是用户可以缩放地图上的任何位置,当用户滑动下面的列表并更改项目索引时,我需要能够检查该标记是否在屏幕上,如果不在屏幕上则缩放到该标记.
所以我可以使用以下代码手动缩放区域。
const animateMapToRegion = (region = null, duration = 1000) => {
if (region) {
mapRef.current.animateToRegion(region, duration);
}
};
仅当屏幕上没有标记时才需要制作此动画。我检查了文档,但找不到任何功能来检查标记是否在屏幕上。
我只想在标记在屏幕上不可见时设置动画。请协助。
我最后为 iOS 和 Android 添加了我自己的实现。
在AIRGoogleMapManager.m
中添加以下方法RCT_EXPORT_METHOD(isMarkerWithinScreen:(nonnull NSNumber *)reactTag
position:(CLLocationCoordinate2D)position
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
id view = viewRegistry[reactTag];
if (![view isKindOfClass:[AIRGoogleMap class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRGoogleMap *mapView = (AIRGoogleMap *)view;
GMSVisibleRegion region = [mapView.projection visibleRegion];
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
resolve(@{@"visible": @([bounds containsCoordinate:position])});
}
}];
}
在AirMapModule.java
中添加以下方法 @ReactMethod
public void isMarkerWithinScreen(final int tag, ReadableMap coordinate, final Promise promise) {
final ReactApplicationContext context = getReactApplicationContext();
final double lat = coordinate.getDouble("latitude");
final double lng = coordinate.getDouble("longitude");
final LatLng position = new LatLng(lat,lng);
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock()
{
@Override
public void execute(NativeViewHierarchyManager nvhm)
{
AirMapView view = (AirMapView) nvhm.resolveView(tag);
if (view == null)
{
promise.reject("AirMapView not found");
return;
}
if (view.map == null)
{
promise.reject("AirMapView.map is not valid");
return;
}
LatLngBounds currentScreen = view.map.getProjection().getVisibleRegion().latLngBounds;
boolean onScreen = currentScreen.contains(position);
WritableMap visibleJson = new WritableNativeMap();
visibleJson.putBoolean("visible", onScreen);
promise.resolve(visibleJson);
}
});
}
add 最后在node_modules/react-native-maps/lib/components/MapView.js
下面添加isMarkerWithinScreen(marker) {
if (Platform.OS === 'android') {
return NativeModules.AirMapModule.isMarkerWithinScreen(
this._getHandle(),
marker.coordinate
);
} else if (Platform.OS === 'ios') {
return this._runCommand('isMarkerWithinScreen', [marker.coordinate]);
}
return Promise.reject('isMarkerWithinScreen not supported on this platform');
}
现在您可以将其用作,
const marker = //your marker;
const visibility = await mapRef.current.isMarkerWithinScreen(marker);
const {visible} = visibility;
console.log('visible-->', visible); //If visible is true marker is on screen otherwise its not.