Maps3.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /**
  2. * 首页地图组件-使用ClusteringMapView和VbeClusterMap
  3. * @邠心vbe on 2021/03/18
  4. */
  5. import React, { useEffect, useRef } from 'react';
  6. import { StyleSheet } from 'react-native';
  7. import { PROVIDER_DEFAULT, PROVIDER_GOOGLE } from 'react-native-maps';
  8. import MapView from "@allisonadam81/react-native-super-clusters";
  9. import { MyCluster, MyMarker } from './Cluster';
  10. import VbeClusterMap from 'vbe-cluster-map';
  11. export default Maps3 = ({ region, onMapReady, stopList, useApplesMap=false, showUserLocation=true, onMarkerPress }) => {
  12. const mapRef = useRef();
  13. const superClusterRef = useRef();
  14. useEffect(() => {
  15. if (isIOS) {
  16. //mapRef.current.animateToRegion(region, 500);
  17. mapRef.current.animateCamera({ center: region, zoom: 17 }, { duration: 500 });
  18. //mapRef.current.animateCamera({ center: region, zoom: 17 }, 500); //移动地图到当前位置并放大
  19. } else {
  20. if (mapRef.current?.moveCamera) {
  21. mapRef.current.moveCamera(region, 17);
  22. //mapRef.current.showUserLocation();
  23. }
  24. }
  25. }, [region])
  26. /*componentDidMount() {
  27. this.mapRef = this.ref.current.mapRef ? this.ref.current.mapRef : this.ref.current;
  28. }*/
  29. const renderCluster = (props) => {
  30. //console.log("renderCluster", props);
  31. let hasAvailableConnector = false;
  32. if (props.geometry.hasAvailableConnector === undefined) {
  33. if (superClusterRef) {
  34. const points = superClusterRef.current.getLeaves(props.id, Infinity, 0);
  35. if (points) {
  36. for (let index = 0; index < points.length; index++) {
  37. const point = points[index];
  38. if (point.properties.coordinate?.available) {
  39. hasAvailableConnector = true;
  40. break;
  41. }
  42. }
  43. }
  44. }
  45. } else {
  46. hasAvailableConnector = props.geometry.hasAvailableConnector
  47. }
  48. props.geometry.hasAvailableConnector = hasAvailableConnector;
  49. const latlng = {latitude: props.geometry.coordinates[1], longitude: props.geometry.coordinates[0]}
  50. //InteractionManager.runAfterInteractions();
  51. return (
  52. <MyCluster
  53. {...props}
  54. key={props.id}
  55. location={latlng}
  56. available={hasAvailableConnector}
  57. onOpen={(latlng, id) => openClusterMarker(latlng, id)}/>
  58. );
  59. }
  60. const openClusterMarker = async (latlng, clusterId) => {
  61. var camera = await mapRef.current.getCamera();
  62. camera.center = latlng;
  63. const currentZoom = camera.zoom;
  64. if (currentZoom >= 12) {
  65. openClusterMarker2(clusterId);
  66. return;
  67. }
  68. let targetZoom = Math.max(currentZoom, 10);
  69. let increment = 2 - (targetZoom - 10) * 0.2;
  70. targetZoom += increment;
  71. camera.zoom = targetZoom;
  72. console.log('camera', camera);
  73. mapRef.current.animateCamera(camera, 300);
  74. }
  75. const openClusterMarker2 = async (clusterId) => {
  76. console.log('openClusterMarker2-start', clusterId);
  77. try {
  78. const clusterChildren = await superClusterRef.current.getLeaves(clusterId, Infinity, 0);
  79. console.log('openClusterMarker2-child', clusterChildren);
  80. const coordinates = clusterChildren.map(m => ({
  81. latitude: m.geometry.coordinates[1],
  82. longitude: m.geometry.coordinates[0]
  83. }));
  84. const padding = { top: 50, right: 50, bottom: 50, left: 50 };
  85. console.log('openClusterMarker2-end', coordinates);
  86. // 放弃手动计算 zoom,让地图自动“框”住这些点
  87. mapRef.current.fitToCoordinates(coordinates, {
  88. edgePadding: padding,
  89. animated: true,
  90. });
  91. } catch (e) {
  92. console.log("openClusterMarker2-err", e)
  93. }
  94. }
  95. return (
  96. isIOS
  97. ? <MapView
  98. ref={mapRef}
  99. superClusterRef={superClusterRef}
  100. style={StyleSheet.absoluteFillObject}
  101. minZoom={5}
  102. maxZoom={20}
  103. radius={$vw(12)}
  104. extent={512}
  105. nodeSize={64}
  106. edgePadding={{top:20, left: 20, right: 20, bottom: 20}}
  107. preserveClusterPressBehavior={false}
  108. animationEnabled={true}
  109. showsIndoors={false}
  110. showsTraffic={false}
  111. toolbarEnabled={false}
  112. initialRegion={region}
  113. tintColor={colorAccent}
  114. onMapReady={onMapReady}
  115. poiClickEnabled={false}
  116. zoomControlEnabled={false}
  117. tracksViewChanges={true}
  118. showsMyLocationButton={false}
  119. showsIndoorLevelPicker={false}
  120. showsUserLocation={showUserLocation}
  121. followsUserLocation={showUserLocation}
  122. renderCluster={info => renderCluster(info)}
  123. provider={useApplesMap ? PROVIDER_DEFAULT : PROVIDER_GOOGLE}>
  124. { stopList.map((marker, index) => {
  125. return (
  126. <MyMarker
  127. key={index}
  128. id={marker.id}
  129. coordinate={marker}
  130. onPress={() => onMarkerPress(marker.id)}
  131. />
  132. );
  133. })}
  134. </MapView>
  135. : <VbeClusterMap
  136. ref={mapRef}
  137. style={StyleSheet.absoluteFill}
  138. region={region}
  139. data={stopList}
  140. animation={true}
  141. showCompass={false}
  142. showTraffic={false}
  143. showIndoors={false}
  144. showIndoorLevelPicker={false}
  145. onMapReady={onMapReady}
  146. onMarkerPress={e => onMarkerPress(e.id)}
  147. showUserLocation={showUserLocation}
  148. moveOnMarkerPress={true}
  149. />
  150. );
  151. }