javascript - React js 谷歌地图 react-google-maps-api 添加 StandaloneSearchBox

标签 javascript reactjs google-maps react-google-maps

我想添加一个 StandaloneSearchBox,但我无法添加它这是我收到的问题,这是我正在使用的代码。

我按照文档示例中所示进行了操作,但无法使其正常工作,也找不到工作示例。

我在 codesanbox 上发布了一个示例,与我使用的代码相同。

链接:codesandbox

enter image description here

代码:

import React, { useState, useRef, useCallback } from "react";
import {
  LoadScript,
  GoogleMap,
  DrawingManager,
  Polygon,
  Marker,
  OverlayView,
  StandaloneSearchBox
} from "@react-google-maps/api";
import Switch from "@material-ui/core/Switch";

import Paper from "@material-ui/core/Paper";
import MenuItem from "@material-ui/core/MenuItem";
import MenuList from "@material-ui/core/MenuList";

import "./styles.css";
const libraries = ["drawing"];

const options = {
  drawingControl: true,
  drawingControlOptions: {
    drawingModes: ["polygon"]
  },
  polygonOptions: {
    fillColor: `#2196F3`,
    strokeColor: `#2196F3`,
    fillOpacity: 0.5,
    strokeWeight: 2,
    clickable: true,
    editable: true,
    draggable: true,
    zIndex: 1
  }
};

class LoadScriptOnlyIfNeeded extends LoadScript {
  componentDidMount() {
    const cleaningUp = true;
    const isBrowser = typeof document !== "undefined"; // require('@react-google-maps/api/src/utils/isbrowser')
    const isAlreadyLoaded =
      window.google &&
      window.google.maps &&
      document.querySelector("body.first-hit-completed"); // AJAX page loading system is adding this class the first time the app is loaded
    if (!isAlreadyLoaded && isBrowser) {
      // @ts-ignore
      if (window.google && !cleaningUp) {
        console.error("google api is already presented");
        return;
      }

      this.isCleaningUp().then(this.injectScript);
    }

    if (isAlreadyLoaded) {
      this.setState({ loaded: true });
    }
  }
}

const defaultPaths = [];

export default function Map({ apiKey, center, paths = defaultPaths, point }) {
  const [state, setState] = useState({
    drawingMode: "polygon",
    pointSelect: null,
    checkedA: true
  });

  const noDraw = () => {
    setState(function set(prevState) {
      return Object.assign({}, prevState, {
        drawingMode: "maker"
      });
    });
  };

  const onPolygonComplete = React.useCallback(
    function onPolygonComplete(poly) {
      const polyArray = poly.getPath().getArray();
      let paths = [];
      polyArray.forEach(function(path) {
        paths.push({ lat: path.lat(), lng: path.lng() });
      });
      console.log("onPolygonComplete", paths);
      point(paths);
      noDraw();
      poly.setMap(null);
    },
    [point]
  );

  // Define refs for Polygon instance and listeners
  const polygonRef = useRef(null);
  const listenersRef = useRef([]);

  // Call setPath with new edited path
  const onEdit = useCallback(() => {
    if (polygonRef.current) {
      const nextPath = polygonRef.current
        .getPath()
        .getArray()
        .map(latLng => {
          return { lat: latLng.lat(), lng: latLng.lng() };
        });
      console.log("nextPath", nextPath);
      //setPath(nextPath);
      point(nextPath);
    }
  }, [point]);

  // Bind refs to current Polygon and listeners
  const onLoad = useCallback(
    polygon => {
      polygonRef.current = polygon;
      const path = polygon.getPath();
      listenersRef.current.push(
        path.addListener("set_at", onEdit),
        path.addListener("insert_at", onEdit),
        path.addListener("remove_at", onEdit)
      );
    },
    [onEdit]
  );

  // Clean up refs
  const onUnmount = useCallback(() => {
    listenersRef.current.forEach(lis => lis.remove());
    polygonRef.current = null;
  }, []);

  const deletePoint = key => {
    let pp = paths.filter((_, i) => i !== key);
    point(pp);
    setState(function set(prevState) {
      return Object.assign({}, prevState, {
        pointSelect: null
      });
    });
  };

  console.log("Map", paths);

  const handleChange = name => event => {
    setState({ ...state, [name]: event.target.checked });
  };

  const onPlacesChanged = al => console.log(al);

  return (
    <div className="App">
      Hi Web!!
      <LoadScriptOnlyIfNeeded
        id="script-loader"
        googleMapsApiKey={apiKey}
        libraries={libraries}
        language="it"
        region="us"
      >
        <GoogleMap
          mapContainerClassName="App-map"
          center={center}
          zoom={18}
          version="weekly"
        >
          <StandaloneSearchBox
            onLoad={onLoad}
            onPlacesChanged={onPlacesChanged}
          >
            <input
              type="text"
              placeholder="Customized your placeholder"
              style={{
                boxSizing: `border-box`,
                border: `1px solid transparent`,
                width: `240px`,
                height: `32px`,
                padding: `0 12px`,
                borderRadius: `3px`,
                boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
                fontSize: `14px`,
                outline: `none`,
                textOverflow: `ellipses`,
                position: "absolute",
                left: "50%",
                marginLeft: "-120px"
              }}
            />
          </StandaloneSearchBox>
          {state.checkedA && state.pointSelect !== null && (
            <OverlayView
              position={paths[state.pointSelect]}
              mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
            >
              <Paper>
                <MenuList>
                  <MenuItem disabled={true}>
                    Punto #{state.pointSelect}
                  </MenuItem>
                  <MenuItem onClick={() => deletePoint(state.pointSelect)}>
                    Elimina punto
                  </MenuItem>
                  <MenuItem>Modifica Punto</MenuItem>
                  <MenuItem
                    onClick={() => {
                      setState(function set(prevState) {
                        return Object.assign({}, prevState, {
                          pointSelect: null
                        });
                      });
                    }}
                  >
                    Annulla
                  </MenuItem>
                </MenuList>
              </Paper>
            </OverlayView>
          )}
          <div
            style={{
              backgroundColor: "#fff",
              borderRadius: 4,
              border: "1px solid #ccc",
              padding: 10,
              zIndex: 99999999,
              position: "absolute",
              top: "5px",
              right: "5px",
              width: "200px"
            }}
          >
            <b>Controls</b>
            <br />
            <br />
            <hr
              style={{
                //color: "#3794ff",
                backgroundColor: "#3794ff",
                height: 1
              }}
            />
            <Switch
              value="checkedA"
              inputProps={{ "aria-label": "secondary checkbox" }}
            />
            Show
            <br />
            <Switch
              checked={state.checkedA}
              value="checkedA"
              inputProps={{ "aria-label": "secondary checkbox" }}
              onChange={handleChange("checkedA")}
            />
            Show menu
          </div>
          {paths.length < 1 ? (
            <DrawingManager
              drawingMode={state.drawingMode}
              options={options}
              onPolygonComplete={onPolygonComplete}
            />
          ) : (
            <Polygon
              options={{
                fillColor: `#2196F3`,
                strokeColor: `#2196F3`,
                fillOpacity: 0.5,
                strokeWeight: 2
              }}
              // Make the Polygon editable / draggable
              editable
              draggable
              path={paths}
              // Event used when manipulating and adding points
              onMouseUp={onEdit}
              // Event used when dragging the whole Polygon
              onDragEnd={onEdit}
              onLoad={onLoad}
              onUnmount={onUnmount}
            />
          )}
          {paths.length > 0 &&
            paths.map((pos, key) => {
              return (
                <Marker
                  key={key}
                  label={"" + key}
                  position={pos}
                  onRightClick={pos => {
                    //let pp = paths.filter((_, i) => i !== key);
                    //point(pp);
                    console.log(key);
                    setState(function set(prevState) {
                      return Object.assign({}, prevState, {
                        pointSelect: key
                      });
                    });
                  }}
                  title={"[" + pos.lat + "," + pos.lng + "]"}
                  draggable
                  onDragEnd={pos => {
                    let obj = { lat: pos.latLng.lat(), lng: pos.latLng.lng() };
                    var copia = Object.assign([], paths);
                    copia[key] = obj;
                    point(copia);
                    if (state.pointSelect !== null)
                      setState(function set(prevState) {
                        return Object.assign({}, prevState, {
                          pointSelect: null
                        });
                      });
                  }}
                />
              );
            })}
        </GoogleMap>
      </LoadScriptOnlyIfNeeded>
    </div>
  );
}

最佳答案

@react-google-maps/api文档状态,用于 StandaloneSearchBox component :

Please do not forget to include "places" to libraries prop array on <LoadingScript />



在您的示例中 libraries可以更新变量以加载场所库:
const libraries = ["drawing", "places"];

示例

一个最小的例子演示了如何使用 StandaloneSearchBox零件:
export default function Map(props) {
  function handleLoad() {}

  function hanldePlacesChanged() {}

  return (
    <LoadScript id="script-loader" googleMapsApiKey="" libraries={["places"]}>
      <GoogleMap
        zoom={5}
        center={{ lat: -25.0270548, lng: 115.1824598 }}
        id="map"
      >
        <StandaloneSearchBox
          onLoad={handleLoad}
          onPlacesChanged={hanldePlacesChanged}
        >
          <input
            type="text"
            placeholder="Customized your placeholder"
            style={{
              boxSizing: `border-box`,
              border: `1px solid transparent`,
              width: `240px`,
              height: `32px`,
              padding: `0 12px`,
              borderRadius: `3px`,
              boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
              fontSize: `14px`,
              outline: `none`,
              textOverflow: `ellipses`,
              position: "absolute",
              left: "50%",
              marginLeft: "-120px"
            }}
          />
        </StandaloneSearchBox>
      </GoogleMap>
    </LoadScript>
  );
}

关于javascript - React js 谷歌地图 react-google-maps-api 添加 StandaloneSearchBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59721795/

相关文章:

javascript - Jquery 设置元素值不适用于长值(guids)

javascript - 在 React.js 应用程序中从广告合作伙伴加载外部脚本

javascript - 单击文本或图像时如何显示 HTML 输入日期?

java - 空指针异常和 getMapAsync 错误

google-maps - 谷歌地图 v3 OverlayView.getProjection()

javascript - HTML 输入字段可自动检索分钟、小时和天的粒度

javascript - 如何在点击时添加和删除事件类 - Angular 方式

javascript - 如果最终用户仍然无法获得所有这些信息,那么节点模型文件夹为何如此之大?

javascript - 超出最大调用堆栈大小/Google map API 自定义 map 类型在允许的范围内递归过多

javascript - 区分人类生成的事件和旧 IE 中生成的浏览器事件