1- import  React ,  {  useCallback ,  useEffect ,  useMemo ,  useRef  }  from  'react' ; 
1+ import  React ,  {  useCallback ,  useEffect ,  useMemo ,  useRef ,   useState  }  from  'react' ; 
22import  PropTypes  from  'prop-types' ; 
33import  loadBMap ,  {  initMapInfo  }  from  '../../../../utils/map-utils' ; 
44import  {  appAvatarURL ,  baiduMapKey ,  googleMapKey ,  mediaUrl  }  from  '../../../../utils/constants' ; 
@@ -8,21 +8,27 @@ import { MAP_TYPE as MAP_PROVIDER } from '../../../../constants';
88import  {  EVENT_BUS_TYPE ,  MAP_TYPE ,  STORAGE_MAP_CENTER_KEY ,  STORAGE_MAP_TYPE_KEY ,  STORAGE_MAP_ZOOM_KEY  }  from  '../../../constants' ; 
99import  {  createBMapGeolocationControl ,  createBMapZoomControl  }  from  './control' ; 
1010import  {  customAvatarOverlay ,  customImageOverlay  }  from  './overlay' ; 
11+ import  ModalPortal  from  '../../../../components/modal-portal' ; 
12+ import  ImageDialog  from  '../../../../components/dialog/image-dialog' ; 
1113
1214import  './index.css' ; 
1315
1416const  DEFAULT_POSITION  =  {  lng : 104.195 ,  lat : 35.861  } ; 
1517const  DEFAULT_ZOOM  =  4 ; 
16- const  BATCH_SIZE  =  500 ; 
1718const  MAX_ZOOM  =  21 ; 
1819const  MIN_ZOOM  =  3 ; 
1920
20- const  MapView  =  ( {  images,  onOpenCluster } )  =>  { 
21+ const  MapView  =  ( {  images } )  =>  { 
22+   const  [ imageIndex ,  setImageIndex ]  =  useState ( 0 ) ; 
23+   const  [ clusterLeaveIds ,  setClusterLeaveIds ]  =  useState ( [ ] ) ; 
24+ 
2125  const  mapInfo  =  useMemo ( ( )  =>  initMapInfo ( {  baiduMapKey,  googleMapKey } ) ,  [ ] ) ; 
26+   const  clusterLeaves  =  useMemo ( ( )  =>  images . filter ( image  =>  clusterLeaveIds . includes ( image . id ) ) ,  [ images ,  clusterLeaveIds ] ) ; 
2227
2328  const  mapRef  =  useRef ( null ) ; 
2429  const  clusterRef  =  useRef ( null ) ; 
2530  const  batchIndexRef  =  useRef ( 0 ) ; 
31+   const  clickTimeoutRef  =  useRef ( null ) ; 
2632
2733  const  saveMapState  =  useCallback ( ( )  =>  { 
2834    if  ( ! mapRef . current )  return ; 
@@ -68,44 +74,57 @@ const MapView = ({ images, onOpenCluster }) => {
6874    return  {  center : savedCenter ,  zoom : savedZoom  } ; 
6975  } ,  [ ] ) ; 
7076
71-   const  onClickMarker  =  useCallback ( ( e ,  markers )  =>  { 
72-     saveMapState ( ) ; 
73-     const  imageIds  =  markers . map ( marker  =>  marker . _id ) ; 
74-     onOpenCluster ( imageIds ) ; 
75-   } ,  [ onOpenCluster ,  saveMapState ] ) ; 
76- 
77-   const  renderMarkersBatch  =  useCallback ( ( )  =>  { 
78-     if  ( ! images . length  ||  ! clusterRef . current )  return ; 
79- 
80-     const  startIndex  =  batchIndexRef . current  *  BATCH_SIZE ; 
81-     const  endIndex  =  Math . min ( startIndex  +  BATCH_SIZE ,  images . length ) ; 
82-     const  batchMarkers  =  [ ] ; 
83- 
84-     for  ( let  i  =  startIndex ;  i  <  endIndex ;  i ++ )  { 
85-       const  image  =  images [ i ] ; 
86-       const  {  lng,  lat }  =  image ; 
87-       const  point  =  new  window . BMapGL . Point ( lng ,  lat ) ; 
88-       const  marker  =  customImageOverlay ( point ,  image ,  { 
89-         callback : ( e ,  markers )  =>  onClickMarker ( e ,  markers ) 
90-       } ) ; 
91-       batchMarkers . push ( marker ) ; 
92-     } 
93-     clusterRef . current . addMarkers ( batchMarkers ) ; 
94- 
95-     if  ( endIndex  <  images . length )  { 
96-       batchIndexRef . current  +=  1 ; 
97-       setTimeout ( renderMarkersBatch ,  20 ) ;  // Schedule the next batch 
98-     } 
99-   } ,  [ images ,  onClickMarker ] ) ; 
77+   const  getPoints  =  useCallback ( ( images )  =>  { 
78+     if  ( ! window . Cluster  ||  ! images )  return  [ ] ; 
79+     return  window . Cluster . pointTransformer ( images ,  ( data )  =>  ( { 
80+       point : [ data . location . lng ,  data . location . lat ] , 
81+       properties : { 
82+         id : data . id , 
83+         src : data . src , 
84+       } 
85+     } ) ) ; 
86+   } ,  [ ] ) ; 
10087
10188  const  initializeCluster  =  useCallback ( ( )  =>  { 
102-     if  ( mapRef . current  &&  ! clusterRef . current )  { 
103-       clusterRef . current  =  new  window . BMapLib . MarkerCluster ( mapRef . current ,  { 
104-         callback : ( e ,  markers )  =>  onClickMarker ( e ,  markers ) , 
105-         maxZoom : 21 , 
106-       } ) ; 
107-     } 
108-   } ,  [ onClickMarker ] ) ; 
89+     clusterRef . current  =  new  window . Cluster . View ( mapRef . current ,  { 
90+       clusterRadius : 80 , 
91+       updateRealTime : true , 
92+       fitViewOnClick : false , 
93+       isAnimation : true , 
94+       clusterMap : ( properties )  =>  ( {  src : properties . src ,  id : properties . id  } ) , 
95+       clusterReduce : ( acc ,  properties )  =>  { 
96+         if  ( ! acc . properties )  { 
97+           acc . properties  =  [ ] ; 
98+         } 
99+         acc . properties . push ( properties ) ; 
100+       } , 
101+       renderClusterStyle : { 
102+         type : window . Cluster . ClusterRender . DOM , 
103+         inject : ( props )  =>  customImageOverlay ( props ) , 
104+       } , 
105+     } ) ; 
106+ 
107+     clusterRef . current . setData ( getPoints ( images ) ) ; 
108+ 
109+     clusterRef . current . on ( window . Cluster . ClusterEvent . CLICK ,  ( element )  =>  { 
110+       if  ( clickTimeoutRef . current )  { 
111+         clearTimeout ( clickTimeoutRef . current ) ; 
112+         clickTimeoutRef . current  =  null ; 
113+         return ; 
114+       }  else  { 
115+         clickTimeoutRef . current  =  setTimeout ( ( )  =>  { 
116+           let  imageIds  =  [ ] ; 
117+           if  ( element . isCluster )  { 
118+             imageIds  =  clusterRef . current . getLeaves ( element . id ) . map ( item  =>  item . properties . id ) . filter ( Boolean ) ; 
119+           }  else  { 
120+             imageIds  =  [ element . properties . id ] ; 
121+           } 
122+           clickTimeoutRef . current  =  null ; 
123+           setClusterLeaveIds ( imageIds ) ; 
124+         } ,  300 ) ; 
125+       } 
126+     } ) ; 
127+   } ,  [ images ,  getPoints ] ) ; 
109128
110129  const  renderBaiduMap  =  useCallback ( ( )  =>  { 
111130    if  ( ! mapRef . current  ||  ! window . BMapGL . Map )  return ; 
@@ -141,8 +160,20 @@ const MapView = ({ images, onOpenCluster }) => {
141160    initializeCluster ( ) ; 
142161
143162    batchIndexRef . current  =  0 ; 
144-     renderMarkersBatch ( ) ; 
145-   } ,  [ addMapController ,  initializeCluster ,  initializeUserMarker ,  renderMarkersBatch ,  getBMapType ,  loadMapState ] ) ; 
163+   } ,  [ addMapController ,  initializeCluster ,  initializeUserMarker ,  getBMapType ,  loadMapState ] ) ; 
164+ 
165+   const  handleClose  =  useCallback ( ( )  =>  { 
166+     setImageIndex ( 0 ) ; 
167+     setClusterLeaveIds ( [ ] ) ; 
168+   } ,  [ ] ) ; 
169+ 
170+   const  moveToPrevImage  =  useCallback ( ( )  =>  { 
171+     setImageIndex ( ( imageIndex  +  clusterLeaves . length  -  1 )  %  clusterLeaves . length ) ; 
172+   } ,  [ imageIndex ,  clusterLeaves . length ] ) ; 
173+ 
174+   const  moveToNextImage  =  useCallback ( ( )  =>  { 
175+     setImageIndex ( ( imageIndex  +  1 )  %  clusterLeaves . length ) ; 
176+   } ,  [ imageIndex ,  clusterLeaves . length ] ) ; 
146177
147178  useEffect ( ( )  =>  { 
148179    const  modifyMapTypeSubscribe  =  window . sfMetadataContext . eventBus . subscribe ( EVENT_BUS_TYPE . MODIFY_MAP_TYPE ,  ( newType )  =>  { 
@@ -172,6 +203,17 @@ const MapView = ({ images, onOpenCluster }) => {
172203  return  ( 
173204    < div  className = "sf-metadata-view-map" > 
174205      < div  className = "sf-metadata-map-container"  ref = { mapRef }  id = "sf-metadata-map-container" > </ div > 
206+       { clusterLeaveIds . length  >  0  &&  ( 
207+         < ModalPortal > 
208+           < ImageDialog 
209+             imageItems = { clusterLeaves } 
210+             imageIndex = { imageIndex } 
211+             closeImagePopup = { handleClose } 
212+             moveToPrevImage = { moveToPrevImage } 
213+             moveToNextImage = { moveToNextImage } 
214+           /> 
215+         </ ModalPortal > 
216+       ) } 
175217    </ div > 
176218  ) ; 
177219} ; 
0 commit comments