javascript - Mapbox 标记弹出窗口不会单独打开/关闭

标签 javascript reactjs mapbox mapbox-gl mapbox-marker

当用户在我的 map 上单击添加的标记时,它会打开 map 上所有标记的弹出窗口 enter image description here

弹出窗口会针对在数据库加载的标记上单击的单个标记打开,但对于“setShowUserPopup”,它们会针对用户添加的每个标记打开,如照片所示(表单是弹出内容)

感谢您提前提供的任何帮助!

import React, { useState, useEffect } from "react";
import ReactMapGL, { Marker, Popup } from "react-map-gl";

import { listLogEntries } from "./API";
import LogEntryForm from "./LogEntryForm";
import { Grid, Card, Icon, Fab } from "@material-ui/core";

const BasicMap = () => {
  // Markers loaded from database
  const [logEntries, setLogEntries] = useState([]);
  const [showPopup, setShowPopup] = useState({});

  // Markers from user input
  const [userMarkers, setUserMarkers] = useState([]);
  const [showUserPopup, setShowUserPopup] = useState({});

  // viewport is all the infomation about the default map state
  const [viewport, setViewport] = useState({
    width: "100vw",
    height: "100vh",
    latitude: 52.950001,
    longitude: -1.15,
    zoom: 6,
    minZoom: 3
    // maxZoom: 3
  });

  // Get entries from API

  const getEntries = async () => {
    const logEntries = await listLogEntries();
    setLogEntries(logEntries);
  };

  useEffect(() => {
    getEntries();
  }, []);

  const showAddMarkerPopup = event => {
    const [longitude, latitude] = event.lngLat;

    setUserMarkers([
      ...userMarkers,
      {
        id: userMarkers.length + 1,
        lat: latitude,
        long: longitude,
        draggable: true
      }
    ]);
  };

  useEffect(() => {
    console.log("userMarkers", userMarkers);
  }, [userMarkers]);

  return (
    <ReactMapGL
      {...viewport}
      mapStyle="mapbox://styles/veleter/ck7xdy1yo1bkj1ipmsbhe9c96"
      mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_TOKEN}
      onViewportChange={setViewport}
      onClick={showAddMarkerPopup}
    >
      {/* DATABASE LOADED MARKERS */}
      {logEntries.map(entry => (
        <React.Fragment key={entry._id}>
          <Marker latitude={entry.latitude} longitude={entry.longitude}>
            <div
              onClick={() =>
                setShowPopup({
                  ...showPopup,
                  [entry._id]: true
                })
              }
            >
              <svg
                className="marker yellow"
                style={{
                  height: `${6 * viewport.zoom}px`,
                  width: `${6 * viewport.zoom}px`
                }}
                version="1.1"
                id="Layer_1"
                x="0px"
                y="0px"
                viewBox="0 0 512 512"
              >
                <g>
                  <g>
                    <path
                      d="M256,0C153.755,0,70.573,83.182,70.573,185.426c0,126.888,165.939,313.167,173.004,321.035
                        c6.636,7.391,18.222,7.378,24.846,0c7.065-7.868,173.004-194.147,173.004-321.035C441.425,83.182,358.244,0,256,0z M256,278.719
                        c-51.442,0-93.292-41.851-93.292-93.293S204.559,92.134,256,92.134s93.291,41.851,93.291,93.293S307.441,278.719,256,278.719z"
                    />
                  </g>
                </g>
              </svg>
            </div>
          </Marker>
          {showPopup[entry._id] ? (
            <Popup
              latitude={entry.latitude}
              longitude={entry.longitude}
              closeButton={true}
              closeOnClick={false}
              dynamicPosition={true}
              onClose={() =>
                setShowPopup({
                  ...showPopup,
                  [entry._id]: false
                })
              }
              anchor="top"
            >
              <div className="popup">
                {/* <h3>{entry.title}</h3>
                <p>{entry.comments}</p>
                <p>
                  <b>Longitude: </b>
                  {entry.longitude}
                </p>
                <p>
                  <b>Latitude: </b>
                  {entry.latitude}
                </p>
                <small>
                  Ticket Placed:{" "}
                  {new Date(entry.visitDate).toLocaleDateString()}
                </small>
                {entry.image && <img src={entry.image} alt={entry.title} />} */}

                <Card elevation={3} className="p-4">
                  <div className="flex items-center">
                    <Fab
                      size="medium"
                      className="bg-light-error circle-44 box-shadow-none overflow-hidden"
                    >
                      <Icon className="text-error">star_outline</Icon>
                    </Fab>
                    <h5 className="font-medium text-error m-0 ml-3">
                      {entry.title}
                    </h5>
                  </div>
                  <div className="pt-4 flex items-center">
                    <h2 className="m-0 text-muted flex-grow"></h2>
                    <div className="ml-3 small-circle bg-error text-white"></div>
                    <span className="text-13">({entry.longitude})</span>
                    <span className="text-13">({entry.latitude})</span>
                  </div>
                </Card>
              </div>
            </Popup>
          ) : null}
        </React.Fragment>
      ))}

      {/* USER ADDED MARKER */}

      {userMarkers.map(userMarker => (
        <React.Fragment key={userMarker._id}>
          <Marker
            latitude={userMarker.lat}
            longitude={userMarker.long}
            draggable
            // onDragEnd={setUserMarkers}
          >
            <div
              onClick={() =>
                setShowUserPopup({
                  ...showUserPopup,
                  [userMarker._id]: true
                })
              }
            >
              <div>
                <svg
                  className="marker red"
                  style={{
                    height: `${6 * viewport.zoom}px`,
                    width: `${6 * viewport.zoom}px`
                  }}
                  version="1.1"
                  id="Layer_1"
                  x="0px"
                  y="0px"
                  viewBox="0 0 512 512"
                >
                  <g>
                    <g>
                      <path
                        d="M256,0C153.755,0,70.573,83.182,70.573,185.426c0,126.888,165.939,313.167,173.004,321.035
                        c6.636,7.391,18.222,7.378,24.846,0c7.065-7.868,173.004-194.147,173.004-321.035C441.425,83.182,358.244,0,256,0z M256,278.719
                        c-51.442,0-93.292-41.851-93.292-93.293S204.559,92.134,256,92.134s93.291,41.851,93.291,93.293S307.441,278.719,256,278.719z"
                      />
                    </g>
                  </g>
                </svg>
              </div>
            </div>
          </Marker>

          {showUserPopup[userMarker._id] ? (
            <Popup
              latitude={userMarker.lat}
              longitude={userMarker.long}
              closeButton={true}
              closeOnClick={false}
              dynamicPosition={true}
              onClose={() =>
                setShowUserPopup({
                  ...showUserPopup,
                  [userMarker._id]: false
                })
              }
              anchor="top"
            >
              <div className="popup">
                <LogEntryForm />
              </div>
            </Popup>
          ) : null}
        </React.Fragment>
      ))}
    </ReactMapGL>
  );
};
export default BasicMap;

最佳答案

错误来自于没有向市场传递准确的 ID。当您单击某个标记并将其设置为 true 时,您会对 map 上的所有标记执行此操作。

您需要做的是将 ID 传递给需要打开的元素(即模式),然后使用 onClick 事件定位该 ID。

 onClick={e => {
      setShowPopup(e.currentTarget.id);
}}

然后要显示所需的元素,您应该将事件中的值与ID进行比较:

{userMarkersID === showUserPopup.id && (
      <div>Whatever you wanna show</div>
)}

其中 userMarkersID 是 map 上每个标记的 ID。希望有帮助

关于javascript - Mapbox 标记弹出窗口不会单独打开/关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60997591/

相关文章:

javascript - 更新 redux store 中的嵌套数据

reactjs - 在 ReactJs 中使用鼠标事件在 Canvas 上绘制直线

javascript - 为什么分页计算不正确?

javascript - 使用 codemirror 编辑调用函数

javascript - TypeScript + React.Lazy

javascript - react +mapbox-gl : Include popup?

android - 父 View 更改大小时,MapBox Android 使布局无效

javascript - 如何检测是否应该更新先前对象的属性?

php - 使用 PHP 流式传输远程服务器的 MP3

javascript - 无法通过 JQuery/AJAX 将 POST 数据发送到 JSON 文件,为什么?