React-google-maps:如何创建一个可点击的 kml 地图来显示 kml 的元数据?

Céd*_*oem 6 methods google-maps kml reactjs react-google-maps

编辑:根据指南,有一个名为 getMetadata() 的方法。我如何使用它来返回道具?

描述:

使用 React-google-maps 包,我已经能够使用自己的 kml 文件加载 Google 地图。该 KML 文件包含多个形状,每个形状背后都有元数据。我想要的是,当用户单击这些形状之一时,他会在弹出窗口中看到形状背后的数据。

例子

假设我有一个 Google 地图,其中包含显示两个国家/地区的 kml 文件。用户将鼠标悬停在这些国家/地区之一上,会看到一个弹出窗口,显示他所在的国家/地区。他将鼠标悬停在第二个国家上空并得到相同的结果。当他单击该国家/地区的 KML 形状时,他会收到更多信息。

这需要我了解一些事情:

- 如何在 KML 形状上创建悬停效果以显示基于形状的数据
- 如何在 KML 形状上创建单击事件以显示基于形状的数据

但是,我无法理解如何使这个 KML 文件具有交互性。
这是我到目前为止所拥有的:

import React, { Component } from 'react';
import { withScriptjs, withGoogleMap, GoogleMap, Marker, KmlLayer } from "react-google-maps"

const MyMapComponent = withScriptjs(withGoogleMap((props) =>
  <GoogleMap
    defaultZoom={8}
    defaultCenter={{ lat: 50.5010789, lng: 4.4764595 }}
  >
    <KmlLayer 
        url='https://example.be/kmlfile.kml'
        options={{ preserveViewport : false}}
    />
    {props.isMarkerShown && <Marker position={{ lat: 50.5010789, lng: 4.4764595 }} />}
  </GoogleMap>
))


export default class GoogleMaps extends Component {
    render(){
        return( 
            <MyMapComponent
              isMarkerShown
              googleMapURL="https://maps.googleapis.com/maps/api/js?key=MYKEY&v=3.exp&libraries=geometry,drawing,places"
              loadingElement={<div style={{ height: `100%` }} />}
              containerElement={<div style={{ height: `100%` }} />}
              mapElement={<div style={{ height: `100%` }} />}
            />
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

Céd*_*oem 4

所以我按照一些教程解决了这个问题。我完全忽略了react-google-maps包,我只是使用简单的Javascript。任何正在寻找一种在 KMLayers 之间添加和切换以及向其添加单击和悬停操作的方法的人,这就是我的做法,也是我对其他开发人员的建议:

尖端

1:用GEOJSON替换KML

首先,我现在使用的不是KMLayer而是Datalayer。这使我能够更好地控制并且在 Google 上有更多的文档。因此,您必须将 KML 转换为 GeoJson。我发现@Mapbox toGeoJSON做得很好,因为它还保留了您的自定义数据(如果您想更自由地处理数据,这一点非常重要!)。另外,他们还共享他们的代码以集成到您的应用程序中,因此您不必每次都手动转换。

2:分析Google Api数据层文档

听起来很简单,但仍然值得一提。正如我所说,Google 分享了很多有关实现数据层的信息。如何添加单击和鼠标悬停事件,如何设计每个单独形状的样式并获取特定信息,...
关于数据层的 Google 文档

3:用addGeoJson()替换loadGeoJson()

如果您的应用程序需要在不同的数据层之间切换或只需添加和删除一个数据层,那么您很快就会发现自己在使用loadGeoJson(). 因此addGeoJson(), ,它将允许您用来map.data.remove()删除当前的数据层。

图片来源:@mensi 关于如何删除数据层的回答

最终代码

import React, { Component } from 'react';
import { SearchConsumer } from '../App.js';
import Icon from '../library/icons/Icon';

var map = ''
var dataLayer = ''
export default class mapSelection extends Component  {
    constructor(props){
        super(props)
        this.onScriptLoad = this.onScriptLoad.bind(this)
    }
    onScriptLoad() {
        // CREATE YOUR GOOGLE MAPS
        map = new window.google.maps.Map(
          document.getElementById('map'),
           {
                // ADD OPTIONS LIKE STYLE, CENTER, GESTUREHANDLING, ...
                center: { lat: 50.5, lng: 4 },
                zoom: 8,
                gestureHandling: 'greedy',
                disableDefaultUI: true,
            });
    }
    dataHandler = (getJson) => {
        // FIRST I REMOVE THE CURRENT LAYER (IF THERE IS ONE)
        for (var i = 0; i < dataLayer.length; i++) {
            map.data.remove(dataLayer[i])
        }
        // THEN I FETCH MY JSON FILE, IN HERE I'M USING A PROP BECAUSE 
        // I WANT TO USE THIS DATAHANDLER MULTIPLE TIMES & DYNAMICALLY 
        // I CAN NOW DO SOMETHING LIKE THIS: 
        // onClick(this.dataHandler(www.anotherlinktojsonfile.com/yourjsonfile.json))
        // ON EACH BUTTON AND CHOOSE WHICH JSON FILE NEEDS TO BE FETCHED IN MY DATAHANDLER.
        fetch(getJson)
            .then(response => response.json())
            .then(featureCollection => {
                dataLayer = map.data.addGeoJson(featureCollection)
                // ADD SOME NEW STYLE IF YOU WANT TO
                map.data.setStyle({strokeWeight: 0.5, fillOpacity: 0 });
            }
            );
        map.data.addListener('mouseover', (event) => {
            map.data.revertStyle();
            // ADD A STYLE WHEN YOU HOVER OVER A SPECIFIC POLYGON
            map.data.overrideStyle(event.feature, {strokeWeight: 1, fillOpacity: 0.1 });
            // IN CONSOLE LOG, YOU CAN SEE ALL THE DATA YOU CAN RETURN
            console.log(event.feature)
        });
        map.data.addListener('mouseout', (event) => {
            // REVERT THE STYLE TO HOW IT WAS WHEN YOU HOVER OUT
            map.data.revertStyle();
        });
    }
    componentDidMount() {
        // LOADING THE GOOGLE MAPS ITSELF
        if (!window.google) {
          var s = document.createElement('script');
          s.type = 'text/javascript';
          s.src = 'https://maps.google.com/maps/api/js?key=' + process.env.REACT_APP_MAPS_API_KEY;
          var x = document.getElementsByTagName('script')[0];
          x.parentNode.insertBefore(s, x);
          // Below is important. 
          //We cannot access google.maps until it's finished loading
          s.addEventListener('load', e => {
            this.onScriptLoad()
            this.dataHandler('https://linktoyourjson.com/yourjsonfile.json')

          })
        } else {
          this.onScriptLoad()
        }
    }
    render () {
        return (
            <div id='mapContainer'>
                <div style={{ width: '100%', height: '100%' }} id='map' />
            </div>
        );
    }
};
Run Code Online (Sandbox Code Playgroud)

额外学分

我还要感谢cuneyt.aliustaoglu.biz提供的关于如何在没有任何软件包的情况下使用 Google 地图的详细教程。

感谢所有帮助我解决小问题的人

有问题或建议吗?

如果有任何问题或者我错过了什么,您可以随时询问或告诉我,如有必要,我会编辑这篇文章。