我正在尝试让我的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,
},
});