google-map-react 标记聚类问题

Posted

技术标签:

【中文标题】google-map-react 标记聚类问题【英文标题】:google-map-react marker clustering issue 【发布时间】:2021-02-22 05:25:23 【问题描述】:

您好,我正在制作一个理想情况下应该包含标记聚类的反应站点。

为此,我使用了两种不同的技术,既可以有效地显示在地图上,一种甚至可以聚类,但我希望我可以结合这些技术。

原因是这两种技术略有不同,使用有效集群的技术不会让我绘制出组件,而是必须返回一个谷歌标记。

这是我使用的第一个技术。

import React,  Component, useState  from "react";
import GoogleMapReact from "google-map-react";

import TravelAlert from "./TravelAlerts/TravelAlerts";
import IntelAlert from "./IntelAlerts/IntelAlerts";

import "./GoogleMap.css";

//class component
export class GoogleMap extends Component 
  constructor(props) 
    super(props);
  
  componentDidMount() 
  static defaultProps = 
    center: 
      lat: 59.955413,
      lng: 30.337844,
    ,
    zoom: 11,
  ;

  render() 
    return (
      <>
        <GoogleMapReact
          style= height: "100vh", width: "100%", zIndex: -1 
          bootstrapURLKeys=
            key: "AIzaSyAfpKoor5CLGg-HbDwdKHq9mGij2JA-YzE",
          
          defaultCenter=this.props.center
          defaultZoom=this.props.zoom
        >
//Simply .mapping a bunch of props (if done this way component just needs a lat and a lng prop for each component )
          this.props.travelAlerts.map((ta) => (
            <TravelAlert
              lat=ta.latitude
              lng=ta.longitude
              title=ta.title
              description=ta.description
              notes=ta.notes
              riskId=ta.riskId
              startDate=ta.startDate
              endDate=ta.endDate
            />
          ))

          this.props.intelAlerts.map((ta) => (
            <IntelAlert
              lat=ta.latitude
              lng=ta.longitude
              title=ta.title
              description=ta.description
              notes=ta.notes
              riskId=ta.riskId
              startDate=ta.startDate
              endDate=ta.endDate
            />
          ))
        </GoogleMapReact>
      </>
    );
  


export default GoogleMap;

我真的很喜欢这种技术,因为它只允许您将任何组件映射到屏幕的 lat 和 lng。然而,使用这种技术,我无法使这些标记的聚类工作。

这是第二种技术,但这不允许我绘制任何自定义标记,这意味着我必须在地图加载之前绘制出地图的标记。这不是首选,因为我无法映射自己的自定义标记。

import React,  Component  from "react";
import GoogleMapReact from "google-map-react";
import intelAlert from "../../../components/Map/MapContainer/GoogleMap/IntelAlerts/IntelAlerts";
// import MarkerClusterer from "@google/markerclusterer";

export default class GoogleMapContainer extends Component 
  componentDidMount() 
    const script = document.createElement("script");
    script.src =
      "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js";
    script.async = true;
    document.body.appendChild(script);
  

  setGoogleMapRef(map, maps) 
    this.googleMapRef = map;
    this.googleRef = maps;
    
    let markers =
      this.props.intelAlerts &&
      this.props.intelAlerts.map((location) => 
        var loc =  lat: location.latitude, lng: location.longitude ;
        return new this.googleRef.Marker( position: loc );
      );
    let markerCluster = new MarkerClusterer(map, markers, 
      imagePath:
        "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m",
      gridSize: 10,
      minimumClusterSize: 2,
    );
  

  static defaultProps = 
    center: 
      lat: 59.95,
      lng: 30.33,
    ,
    zoom: 11,
  ;

  render() 
    if (this.props.intelAlerts.length) 
      return (
        <GoogleMapReact
          style= height: "100vh", width: "100%", zIndex: -1 
          bootstrapURLKeys= key: "AIzaSyAfpKoor5CLGg-HbDwdKHq9mGij2JA-YzE" 
          yesIWantToUseGoogleMapApiInternals
          onGoogleApiLoaded=( map, maps ) => this.setGoogleMapRef(map, maps)
          defaultCenter= lat: -31.56391, lng: 147.154312 
          defaultZoom=15
          options= streetViewControl: true 
        />
      );
     else 
      return <></>;
    
  


有没有办法仍然能够绘制出我自己的自定义标记并包括标记聚类。

任何帮助或指导都意味着分配,因为关于这个问题的文档很少。

我正在使用 google-map-react npm 包。

编辑 我在角度上做了类似的事情。 在 Angular 中,您可以简单地执行此操作。

<div ng-if="showTravellers" >
      <agm-marker-cluster    [minimumClusterSize]= "minClusterSize"> 

          <agm-marker *ngFor="let m of intelligenceAlerts;let i = index;" [visible]="showIntelligence"  [latitude]="m.latitude" [longitude]="m.longitude" [iconUrl]= 'getTheIcon(m.riskId)'  >
            <agm-snazzy-info-window [maxWidth]="600" maxHeight="200px" [closeWhenOthersOpen]="true" backgroundColor="getTheColor(m.colour);">
                <ng-template>
                    <mat-form-field appearance="standard">
                        <mat-card> <h3><b>m.colour</b> </h3></mat-card>
                  <mat-card> <h3><b>m.title</b> </h3></mat-card>
                  <mat-card> <p>m.notes </p></mat-card>
                   <button>Description</button> <button>Start Date</button><button>End Date</button><button>Notes</button>
                 </mat-form-field>
                </ng-template>
               </agm-snazzy-info-window> 
         </agm-marker>
    </agm-marker-cluster>
    </div>

reactjs 中是否有等价物?

【问题讨论】:

【参考方案1】:

您可以只动态加载 Maps JS API,而不是依赖第 3 方库/包。这样,您只需关注他们的official documentations。对于这个例子,我按照这两个来聚类地图标记以及添加自定义标记:

https://developers.google.com/maps/documentation/javascript/marker-clustering https://developers.google.com/maps/documentation/javascript/custom-markers

这是我制作的 Stackblitz 示例供您参考:https://stackblitz.com/edit/react-map-cluster-64766101

App.js

import React,  Component  from "react";
import  render  from "react-dom";
import Map from "./components/map";
import "./style.css";

class App extends Component 
  render() 
    return (
      <Map
        id="myMap"
        options=
          center:  lat: -28.024, lng: 140.887 ,
          zoom: 3
        
      />
    );
  


export default App;

ma​​p.js

import React,  Component  from "react";
import  render  from "react-dom";

const locations = [
   lat: -31.56391, lng: 147.154312 ,
   lat: -33.718234, lng: 150.363181 ,
   lat: -33.727111, lng: 150.371124 ,
   lat: -33.848588, lng: 151.209834 ,
   lat: -33.851702, lng: 151.216968 ,
   lat: -34.671264, lng: 150.863657 ,
   lat: -35.304724, lng: 148.662905 ,
   lat: -36.817685, lng: 175.699196 ,
   lat: -36.828611, lng: 175.790222 ,
   lat: -37.75, lng: 145.116667 ,
   lat: -37.759859, lng: 145.128708 ,
   lat: -37.765015, lng: 145.133858 ,
   lat: -37.770104, lng: 145.143299 ,
   lat: -37.7737, lng: 145.145187 ,
   lat: -37.774785, lng: 145.137978 ,
   lat: -37.819616, lng: 144.968119 ,
   lat: -38.330766, lng: 144.695692 ,
   lat: -39.927193, lng: 175.053218 ,
   lat: -41.330162, lng: 174.865694 ,
   lat: -42.734358, lng: 147.439506 ,
   lat: -42.734358, lng: 147.501315 ,
   lat: -42.735258, lng: 147.438 ,
   lat: -43.999792, lng: 170.463352 
];

class Map extends Component 
  constructor(props) 
    super(props);
    this.state = 
      map: ""
    ;
  

  onScriptLoad() 
    this.state.map = new window.google.maps.Map(
      document.getElementById(this.props.id),
      this.props.options
    );
    this.addMarker();
  

  componentDidMount() 
    if (!window.google) 
      var s = document.createElement("script");
      s.type = "text/javascript";
      s.src = `https://maps.google.com/maps/api/js?key=YOUR_API_KEY`;
      var x = document.getElementsByTagName("script")[0];
      x.parentNode.insertBefore(s, x);

      var s2 = document.createElement("script");
      s2.type = "text/javascript";
      s2.src = `https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js`;
      var x2 = document.getElementsByTagName("script")[0];
      x2.parentNode.insertBefore(s2, x2);

      s.addEventListener("load", e => 
        this.onScriptLoad();
      );
     else 
      this.onScriptLoad();
    
  
  // Add some markers to the map.
  addMarker() 
    const markers = locations.map((location, i) => 
      return new google.maps.Marker(
        position: location,
        icon:
          "https://developers.google.com/maps/documentation/javascript/examples/full/images/info-i_maps.png",
        map: this.state.map
      );
    );
    // Add a marker clusterer to manage the markers.
    new MarkerClusterer(this.state.map, markers, 
      imagePath:
        "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m"
    );
  

  render() 
    return <div className="map" id=this.props.id />;
  


export default Map;

注意:将 API Key 占位符替换为您的实际 API Key

【讨论】:

很好的答案真的很感激!

以上是关于google-map-react 标记聚类问题的主要内容,如果未能解决你的问题,请参考以下文章

出现标记聚类默认聚类

标记聚类 - 融合表层 - Google Maps v3

OpenLayers,漂亮的标记聚类

将简单的标记聚类器添加到谷歌地图

地图标记不聚类

聚类分析?标记集群