如何在React中使用带有高级标记的Google地图?

huangapple go评论85阅读模式
英文:

How to use google map with advanced markers in react?

问题

I was trying to create a custom marker using Google Maps advanced markers

Data so that you can reproduce the example. Just put any image where image is being used.

 const center = {
    lat: 28.7041,
    lng: 77.102,
  };

  const markers = [
    {
      key: "1",
      coordinates: {
        lat: 28.7041,
        lng: 77.102,
      },
      marker: {
        text: "BUS-001",
        backgroundColor: "black",
      },
    },
    {
      key: "2",
      coordinates: {
        lat: 28.4557,
        lng: 77.032,
      },
      marker: {
        text: "BUS-002",
        backgroundColor: "red",
      },
    },
    {
      key: "3",
      coordinates: {
        lat: 28.457,
        lng: 77.0412,
      },
      marker: {
        text: "BUS-003",
        backgroundColor: "blue",
      },
    },
  ];
 
import React, { useEffect, useState } from "react";
import Typography from "@mui/material/Typography"; // Update the import statement
import busTopViewImage from "../assets/bus-top-view.png";
import { Grid } from "@mui/material";


const Map = ({ center, markers }) => {
  useEffect(() => {
    async function initMap() {
      const { Map } = (await google.maps.importLibrary(
        "maps"
      )) as google.maps.MapsLibrary;
      const { AdvancedMarkerElement } = (await google.maps.importLibrary(
        "marker"
      )) as google.maps.MarkerLibrary;

      const map = new Map(document.getElementById("map-view") as HTMLElement, {
        center,
        zoom: 14,
        mapId: "4504f8b37365c3d0",
      });
      let mapMarkers = [];
      for (let markerData of markers) {
        const markerComponent = document.createElement("div");
        markerComponent.innerHTML = `
  <img src="${busTopViewImage}" />
  <h5 style="background-color: ${markerData.marker.backgroundColor}; color: white; border-radius: 10px; padding: 8px;">
        ${markerData.marker.text}
  </h5>
`;
        const m = new AdvancedMarkerElement({
          map,
          position: markerData.coordinates,
          content: markerComponent,
        });
        mapMarkers.push(m);
      }
    }
    initMap();
  }, []);

  return <div id="map-view" style={{ width: "100%", height: "100%" }}></div>;
};
export default Map;

The issue I am facing is that I want to use a React component as marker as below.

const Marker = ({ text, backgroundColor }) => {
  return (
    <Grid
      container
      justifyContent="stretch"
      alignItems="center"
      direction="column"
      style={{
        boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
        marginBottom: "3rem",
      }}
    >
      <img src={busTopViewImage} alt="Bus Marker" />
      <Grid
        item
        style={{
          boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
          backgroundColor: backgroundColor,
          borderRadius: "10px",
          padding: "0 0.5rem",
        }}
      >
        <Typography variant="body1" color="white">
          {text}
        </Typography>
      </Grid>
    </Grid>
  );
};

To what I know about react, it uses babel to convert jsx to javascript nodes using the document.createElement as that api wants. I want to know if there is any library/react function that can ingest this Marker component and help me use remove that ugly markerComponent.innerHTML in that useEffect.
If you know of any method please share an example or provide some sources of information.

I already tried the react packages available for google maps. Some only allow static images and one of them accepted the Marker but while zooming in and out didn't change the marker position.

英文:

I was trying to create a custom marker using Google Maps advanced markers

Data so that you can reproduce the example. Just put any image where image is being used.

 const center = {
lat: 28.7041,
lng: 77.102,
};
const markers = [
{
key: &quot;1&quot;,
coordinates: {
lat: 28.7041,
lng: 77.102,
},
marker: {
text: &quot;BUS-001&quot;,
backgroundColor: &quot;black&quot;,
},
},
{
key: &quot;2&quot;,
coordinates: {
lat: 28.4557,
lng: 77.032,
},
marker: {
text: &quot;BUS-002&quot;,
backgroundColor: &quot;red&quot;,
},
},
{
key: &quot;3&quot;,
coordinates: {
lat: 28.457,
lng: 77.0412,
},
marker: {
text: &quot;BUS-003&quot;,
backgroundColor: &quot;blue&quot;,
},
},
];
import React, { useEffect, useState } from &quot;react&quot;;
import Typography from &quot;@mui/material/Typography&quot;; // Update the import statement
import busTopViewImage from &quot;../assets/bus-top-view.png&quot;;
import { Grid } from &quot;@mui/material&quot;;
const Map = ({ center, markers }) =&gt; {
useEffect(() =&gt; {
async function initMap() {
const { Map } = (await google.maps.importLibrary(
&quot;maps&quot;
)) as google.maps.MapsLibrary;
const { AdvancedMarkerElement } = (await google.maps.importLibrary(
&quot;marker&quot;
)) as google.maps.MarkerLibrary;
const map = new Map(document.getElementById(&quot;map-view&quot;) as HTMLElement, {
center,
zoom: 14,
mapId: &quot;4504f8b37365c3d0&quot;,
});
let mapMarkers = [];
for (let markerData of markers) {
const markerComponent = document.createElement(&quot;div&quot;);
markerComponent.innerHTML = `
&lt;img src=&quot;${busTopViewImage}&quot; /&gt;
&lt;h5 style=&quot;background-color: ${markerData.marker.backgroundColor}; color: white; border-radius: 10px; padding: 8px;&quot;&gt;
${markerData.marker.text}
&lt;/h5&gt;
`;
const m = new AdvancedMarkerElement({
map,
position: markerData.coordinates,
content: markerComponent,
});
mapMarkers.push(m);
}
}
initMap();
}, []);
return &lt;div id=&quot;map-view&quot; style={{ width: &quot;100%&quot;, height: &quot;100%&quot; }}&gt;&lt;/div&gt;;
};
export default Map;

The issue I am facing is that I want to use a React component as marker as below.

const Marker = ({ text, backgroundColor }) =&gt; {
return (
&lt;Grid
container
justifyContent=&quot;stretch&quot;
alignItems=&quot;center&quot;
direction=&quot;column&quot;
style={{
boxShadow: &quot;0 2px 4px rgba(0, 0, 0, 0.2)&quot;,
marginBottom: &quot;3rem&quot;,
}}
&gt;
&lt;img src={busTopViewImage} alt=&quot;Bus Marker&quot; /&gt;
&lt;Grid
item
style={{
boxShadow: &quot;0 2px 4px rgba(0, 0, 0, 0.2)&quot;,
backgroundColor: backgroundColor,
borderRadius: &quot;10px&quot;,
padding: &quot;0 0.5rem&quot;,
}}
&gt;
&lt;Typography variant=&quot;body1&quot; color=&quot;white&quot;&gt;
{text}
&lt;/Typography&gt;
&lt;/Grid&gt;
&lt;/Grid&gt;
);
};

To what I know about react, it uses babel to convert jsx to javascript nodes using the document.createElement as that api wants. I want to know if there is any library/react function that can ingest this Marker component and help me use remove that ugly markerComponent.innerHTML in that useEffect.
If you know of any method please share an example or provide some sources of information.

I already tried the react packages available for google maps. Some only allow static images and one of them accepted the Marker but while zooming in and out didn't change the marker position.

答案1

得分: 1

你可以看出,你可以像这样将DOM节点传递给高级标记:

const markerComponent = document.createElement("div");
markerComponent.innerHTML = `
  <img src="${busTopViewImage}" />
  <h5 style="background-color: ${markerData.marker.backgroundColor}; color: white; border-radius: 10px; padding: 8px;">
        ${markerData.marker.text}
  </h5>
`;
const m = new AdvancedMarkerElement({
  map,
  position: markerData.coordinates,
  content: markerComponent,
});

唯一你遗漏的是通过React生成HTML。

// 在虚拟DOM节点上设置一个React根
const markerComponent = document.createElement("div");
// 在新的DOM节点上初始化根
const root = ReactDOM.createRoot(el);
// 将HTML输出到根节点
root.render(<Marker ... />);

// 使用它
const m = new AdvancedMarkerElement({
  map,
  position: markerData.coordinates,
  content: markerComponent,
});

如果你需要与树的其余部分共享状态,你可以将其与Portals结合使用。

英文:

As you can tell, you can pass DOM nodes into advanced markers like you have here:

        const markerComponent = document.createElement(&quot;div&quot;);
        markerComponent.innerHTML = `
  &lt;img src=&quot;${busTopViewImage}&quot; /&gt;
  &lt;h5 style=&quot;background-color: ${markerData.marker.backgroundColor}; color: white; border-radius: 10px; padding: 8px;&quot;&gt;
        ${markerData.marker.text}
  &lt;/h5&gt;
`;
        const m = new AdvancedMarkerElement({
          map,
          position: markerData.coordinates,
          content: markerComponent,
        });

The only thing you're missing is to generate the HTML via React.

    // Setup a React root on a virtual DOM node
    const markerComponent = document.createElement(&quot;div&quot;);
    // Initialize root at new DOM node
    const root = ReactDOM.createRoot(el);
    // Output HTML into it
    root.render(&lt;Marker ... /&gt;);

     // Use it
    const m = new AdvancedMarkerElement({
          map,
          position: markerData.coordinates,
          content: markerComponent,
        });

If you need to share state with the rest of the tree, you can combine this with Portals.

huangapple
  • 本文由 发表于 2023年7月28日 02:51:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76782661.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定