React Native Maps动态标记会降低性能

时间:2018-12-08 18:17:01

标签: node.js reactjs react-native react-native-maps

我正在尝试让我的react-native-maps应用程序与arcgis esri地理编码api交互。由于某些原因,当我通过在标记周围滚动来更改区域时,标记会非常不一致,并且会随机弹出并消失,并且通常会出现很多错误。我应该做些什么,以便仅重新渲染某些标记或以某种方式在当前区域中缓存标记?

演示https://giphy.com/gifs/1o1o3wktAFkcV7B06R

import React from 'react';
import { Dimensions, ScrollView, StyleSheet, View } from 'react-native';
import { ExpoLinksView } from '@expo/samples';

import MapView, { Marker } from 'react-native-maps';

import SphericalMercator from "@mapbox/sphericalmercator";

const dimensions = Dimensions.get('window');
const ASPECT_RATIO = dimensions.width / dimensions.height;
const LATITUDE = 41.8241;
const LONGITUDE = -87.6561;
const LATITUDE_DELTA = 0.003;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;

const merc = new SphericalMercator();

const getZoomLevelFromRegion = (region, viewport) => {
  const { longitudeDelta } = region;
  const { width } = viewport;
  const lngD = (360 + longitudeDelta) % 360;
  const tiles = width / 256;
  const portion = lngD / 360;
  const tilePortion = portion / tiles;
  return Math.log2(1 / tilePortion);
};

const getRegionByZoomLevel = (center, zoomLevel, viewport) => {
  const { latitude, longitude } = center;
  const { width, height } = viewport;

  const [x, y] = merc.px([lng, lat], zoomLevel);

  const xmin = Math.floor(x - width / 2);
  const xmax = xmin + width;
  const ymin = Math.floor(y - height / 2);
  const ymax = ymin + height;

  const nw = merc.ll([xmin, ymin], zoomLevel);
  const se = merc.ll([xmax, ymax], zoomLevel);

  const latitudeDelta = nw[1] - se[1];
  const longitudeDelta = se[0] - nw[0];

  return {
    latitude,
    longitude,
    latitudeDelta,
    longitudeDelta
  };
};

const getRegionBoundaries = (center, zoomLevel, viewport ) => {
  const { latitude, longitude, latitudeDelta, longitudeDelta } = center;
  const { width, height } = viewport;

  const [x, y] = merc.px([longitude, latitude], zoomLevel);
  const xmin = Math.floor(x - width / 2);
  const xmax = xmin + width;
  const ymin = Math.floor(y - height / 2);
  const ymax = ymin + height;

  const [westLongitude, northLatitude] = merc.ll([xmin, ymin], zoomLevel);
  const [eastLongitude, southLatitude] = merc.ll([xmax, ymax], zoomLevel);

  return {
    northLatitude,
    southLatitude,
    westLongitude,
    eastLongitude
  };
};

export default class LinksScreen extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      region: {
        latitude: LATITUDE,
        longitude: LONGITUDE,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA,
      },
      layout: null,
      markers: [],
    };

    this.onRegionChange = this.onRegionChange.bind(this);
    this.getZoomLevel = this.getZoomLevel.bind(this);
  }

  getZoomLevel() {
    const { region, layout } = this.state;
    if (!region || !layout) return null;

    return getZoomLevelFromRegion(region,layout);
  }

  onRegionChange(region) {
    const zoomLevel = this.getZoomLevel();

     if (!zoomLevel) {
       return null;
     }

     const { latitude, longitude } = region;
     const { width, height } = this.state.layout;

     const {
       northLatitude,
       southLatitude,
       westLongitude,
       eastLongitude
     } = getRegionBoundaries(
       { latitude, longitude },
       Math.floor(zoomLevel) + 1,
       { width: width, height: height }
     );

     if(zoomLevel < 13){
       if(this.state.markers.length){
         this.setState({
           region,
           layout: this.state.layout,
           markers: [],
         });
       }

       return;
     }

    fetch(`https://some_arcgis_api/query?geometry={"xmin":${westLongitude},"ymin":${southLatitude},"xmax":${eastLongitude}",ymax":${northLatitude},"spatialReference":{"wkid":4326}}&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&geometryPrecision=6&f=geojson`)
    .then((response) => response.json())
    .then((responseJSON) => {
      this.setState({
        region,
        layout: this.state.layout,
        markers: responseJSON.features.map(function(feature){
          return {
            key: feature.id,
            coordinate: {
              latitude: feature.geometry.coordinates[1],
              longitude: feature.geometry.coordinates[0],
            }
          }
        })
      });
    })
  }

  static navigationOptions = {
    header: null,
  };

  render() {
    return (
      <View style={styles.container}>
           <MapView
             style={styles.map}
             mapType="hybrid"
             onLayout={e => this.setState({
               layout: {width: e.nativeEvent.layout.width * 2,height:e.nativeEvent.layout.height * 2},
               region: this.state.region,
               markers: this.state.markers,
             })}
             initialRegion={{
              latitude: LATITUDE,
              longitude: LONGITUDE,
              latitudeDelta: LATITUDE_DELTA,
              longitudeDelta: LONGITUDE_DELTA,
             }}
             onRegionChange={this.onRegionChange}
           >
             {this.state.markers.map(marker => (
              <Marker
                key={marker.key}
                coordinate={marker.coordinate}
              />
            ))}
        </MapView>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  map: {
    ...StyleSheet.absoluteFillObject,
  },
});

0 个答案:

没有答案