简体   繁体   English

使用@React-Google-Maps/api 将 HTML 渲染到 Infowindow

[英]React Render HTML to Infowindow using @React-Google-Maps/api

How do I to render html in google maps Infowindow?如何在谷歌地图信息窗口中呈现 html?

I have tried several different ways to do it, but none of them seems to work.我尝试了几种不同的方法来做到这一点,但它们似乎都不起作用。

My code:我的代码:

import React, { Component, useState } from 'react';
import ReactDOMServer from 'react-dom/server';
import { GoogleMap, LoadScript, useLoadScript, InfoWindow, Marker, } from '@react-google-maps/api'

export class MarkerWithInfoWindow extends React.Component {

    constructor() {
        super();
        this.state = {
            isOpen: false
        }
        this.onToggleOpen = this.onToggleOpen.bind(this);
        this.onEventWindowClick = this.onEventWindowClick.bind(this)
    }

    onToggleOpen() {
        this.setState({
            isOpen: !this.state.isOpen
        });
    }



    render() {

        const imgUrl = this.props.icon;
        return (<Marker
            title={this.props.title}
            position={this.props.position}

            icon={{
                url: imgUrl,
            }}
        >
            {this.state.isOpen && <InfoWindow
                onCloseClick={this.onToggleOpen}
                position={this.props.position}
                onMouseOut={this.onToggleOpen}
                pixelOffset={{ width: 25, height: 25 }}
                zIndex={-1}
                onClick={this.onEventWindowClick(this)} 
            >
                <> {ReactDOMServer.renderToString(this.props.content)}</>
            </InfoWindow>}
        </Marker>)
    }
}

my result looks like this:我的结果如下所示:

在此处输入图像描述

I guess content prop is passed as HTML string, then dangerouslySetInnerHTML needs to be set to render it as html instead of returning it as a plain string, for instance:我猜content道具作为 HTML 字符串传递,然后需要设置dangerouslySetInnerHTML以将其呈现为 html 而不是将其作为纯字符串返回,例如:

const InfoWindowContent = () => <div dangerouslySetInnerHTML={{ __html: this.props.content }}></div>;

Usage用法

<InfoWindow
     onCloseClick={this.onToggleOpen}
     position={this.props.position}>
      <InfoWindowContent/>
</InfoWindow>

Demo演示

I've done this only as a functional component.我只是将其作为一个功能组件来完成。 According to the Google Map API docs, the desired HTML content can be passed as the value of the content property of the InfoWindow instance at its instantiation.根据 Google Map API 文档,所需的 HTML 内容可以作为 InfoWindow 实例在其实例化时的content属性的值传递。 According to the documentation of the react-google-maps/api , the (initial) options can be passed as a prop in the InfoWindow JSX.根据react-google-maps/api的文档,(初始)选项可以作为InfoWindow JSX 中的道具传递。

In my case, I recompute the InfoWindow content on the fly, so I keep that string as a piece of state ( dataWindowContent in my case).在我的情况下,我会即时重新计算 InfoWindow 内容,因此我将该字符串保留为dataWindowContent (在我的情况下为 dataWindowContent )。 React guarantees that the InfoWindow component will be rerendered each time the state changes, so that's how I keep mine current. React 保证每次 state 更改时都会重新渲染 InfoWindow 组件,这就是我保持最新状态的方式。

Finally, the InfoWindow component is created with the InfoWindow component open by default.最后,在 InfoWindow 组件默认打开的情况下创建 InfoWindow 组件。 I keep mine closed until it has something to show, so I put that behavior in the onInfoWindowLoad handler.我一直保持关闭状态,直到它有东西要显示,所以我把这个行为放在 onInfoWindowLoad 处理程序中。

You'll need a ref to the underlying Google Maps API instance -- the InfoWindow component conveniently passes that object as an argument when it invokes the onLoad handler.您需要一个对底层 Google Maps API 实例的引用——InfoWindow 组件在调用 onLoad 处理程序时方便地将 object 作为参数传递。 So here's a sketch of how you might do what you're attempting (note that I haven't exercised this, I'm just trying to say what you might try):所以这里是你如何做你正在尝试的事情的草图(请注意,我没有练习过这个,我只是想说你可能会尝试什么):

const MarkerWithInfoWindow = ( {content, title, position, icon, ...props} ) => {
  const [infoWindowContent, setInfoWindowContent] = useState(content);
  const [localPosition, setLocalPosition] = useState(position);
  const rawInfoWindowRef = useRef(null);

  const onInfoWindowLoad = (aRawInfoWindow) => {
    rawInfoWindowRef.current = aRawInfoWindow;
    if (''===infoWindowContent) {
      aRawInfoWindow.close();
    }
  };
  return (
    <GoogleMap>
      <Marker
        title={title}
        position={localPosition}
        icon={{url: icon}}
      >
      <InfoWindow
        onLoad={onInfoWindowLoad}
        onCloseClick={onInfoWindowClick}
        options={{content: infoWindowContent}}
        position={localPosition}         
      />
      </Marker>
    <GoogleMap>
  );
};

Note that I've passed your desired HTML into the InfoWindow instance as the value of its content parameter inside its option prop.请注意,我已将您所需的 HTML 传递到 InfoWindow 实例中,作为其option道具中其content参数的值。

Note also that position and content props are used to initialize the corresponding local state.另请注意, positioncontent props 用于初始化相应的本地 state。 Use their setters to move the marker/infoWindow or move the map.使用他们的设置器移动标记/信息窗口或移动 map。 Also note I've surrounded your Marker and InfoWindow with a containing GoogleMap.另请注意,我已经用包含 GoogleMap 包围了您的标记和信息窗口。 I'm pretty sure the components require this container.我很确定组件需要这个容器。 You might need set the center property of the containing map as another piece of state so that it changes if the position changes.您可能需要将包含 map 的center属性设置为 state 的另一部分,以便在 position 更改时更改。

This approach lets you avoid the use of dangerouslySetInnerHTML .这种方法可以让您避免使用dangerouslySetInnerHTML The only way to change infoWindowContent is to use its setter ( setInfoWindowContent ) and this will force a rerender of the component tree.更改 infoWindowContent 的唯一方法是使用其设置器 ( setInfoWindowContent ),这将强制重新渲染组件树。 In that re-render, the low-level InfoWindow instance will be updated with its new content automatically, and it will render the HTML.在重新渲染中,低级 InfoWindow 实例将使用其新内容自动更新,并将渲染 HTML。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM