如何检查标记是否在反应本机地图中屏幕上显示的区域中

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.