首页 > 解决方案 > 在 React Google Maps 中创建自定义按钮

问题描述

我目前正在使用一个个人项目react-google-maps,但在地图上显示自定义按钮时遇到问题。我想创建一个悬停在地图上的菜单按钮,就像谷歌地图的左上角(搜索栏)一样。

根据文档的说明,您必须创建一个 div 并使用以下命令将其放在地图的特定一侧。

map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(<div>);

但是,我无法让它与 React 很好地配合使用,因为 Google 文档在 vanilla js 中。在 React 中放置这行代码的好地方在哪里?我知道在 vanilla js 中你几乎可以把它放在任何地方。

我还查看了react-google-maps 文档,但似乎没有在 API 中实现这个特定的用例。

有没有办法在 React 中轻松创建悬停在地图上的自定义按钮react-google-maps?如果没有,是否有一个巧妙的技巧可以让它以某种方式工作?或者也许是我不知道的 CSS 技巧?

这是我目前为该项目提供的一些示例代码:

代码沙箱

MapContainer.js

import React from 'react';
import { GoogleMap, withScriptjs, withGoogleMap } from "react-google-maps";
import { compose, withProps } from "recompose";
import Menu from "./Menu";

// -----------------------------------------------------------------------------------------
// needed to construct Google Maps in React

const styles = require('../../assets/styles/GoogleMapStyles.json');


const MyMapComponent = compose(
    withProps({
        googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=YOUR_API_KEY",
        loadingElement: < div style={{ height: `100%` }} />,
        containerElement: < div style={{ height: `100%` }} />,
        mapElement: < div style={{ height: `100%` }} />
    }),
    withScriptjs,
    withGoogleMap
)((props) =>

    <GoogleMap
        defaultZoom={15}
        defaultCenter={props.location}
        defaultOptions={{styles: styles,
            disableDefaultUI: true}}
    >
        <Menu /> // the hamburger icon that I want hovered over the map
    </GoogleMap>
);

// -----------------------------------------------------------------------------------------

export default class MapContainer extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            user: {
                currentLocation: {lat: null, lng: null}
            },
            map: null
        };

    }

    componentDidMount() {
        .....
    }

    render() {
        return(
            <div id="map-container" ref="map">
                <MyMapComponent 
                location={this.state.user.currentLocation}/>
            </div>
        );
    }
}

菜单.js


import React from 'react';
import '@fortawesome/fontawesome-free/css/all.min.css';

export default class Menu extends React.Component {
    constructor(props) {
        super(props);
    }

    render() { 
        return(
            <div>
                <span className="menu-btn">
                    <i class="fas fa-bars"></i>
                </span>
            </div>
        );
    }
}

在此先感谢您的帮助。在这一点上,任何想法/评论/见解都会受到赞赏。我已经考虑这个问题很长一段时间了,我现在处于一个我不能再忽视它的地方......

标签: javascriptreactjsgoogle-mapsreact-google-maps

解决方案


如果您使用 >= React 16.0,有一个简单的方法可以做到这一点:

在 Map 组件的返回值中使用预生成的 div 和 ReactDom.createPortal 并使用 map 参数调用 onload 以添加 div,如下所示:

import React from 'react';
import ReactDom from 'react-dom';
import { GoogleMap, withScriptjs, withGoogleMap } from "react-google-maps";
import { compose, withProps } from "recompose";
import Menu from "./Menu";

// -----------------------------------------------------------------------------------------
// needed to construct Google Maps in React

const styles = require('../../assets/styles/GoogleMapStyles.json');
const controlButtonDiv = document.createElement('div');
const handleOnLoad = map => {
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlButtonDiv);
};

const MyMapComponent = compose(
    withProps({
        googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=YOUR_API_KEY",
        loadingElement: < div style={{ height: `100%` }} />,
        containerElement: < div style={{ height: `100%` }} />,
        mapElement: < div style={{ height: `100%` }} />
    }),
    withScriptjs,
    withGoogleMap
)((props) =>

    <><GoogleMap
        defaultZoom={15}
        defaultCenter={props.location}
        defaultOptions={{styles: styles,
            disableDefaultUI: true}}
        onLoad={map => handleOnLoad(map)
    >
    </GoogleMap>,
    ReactDom.createPortal(<Menu />, controlButtonDiv),
    </>
);

我实际上是用 google-map-react 库做的,但它是相同的想法,你只需要添加

yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => handleOnLoad(map, maps)}

作为属性并做同样的事情。


推荐阅读