React js从路径中删除点更新多边形

React js delete point from the path update the Polygon

我有下面的地图,正如你应该在地图上我有一个多边形和标记,它们是多边形的主要点,下面我打印了多边形的主要点,即标记。

我为用户提供了删除多边形点的可能性,如下图所示,通过单击 X,点被删除。

问题是这样的,当我点击X时,这个点作为标记被消除了,但它似乎仍然是多边形的一个固定点,这是不应该的,多边形应该改变它的形状,基于消除点。

我不明白我哪里错了。 你能帮帮我吗

Link: codesandbox

索引:

import React from "react";
import ReactDOM from "react-dom";

import Map from "./Map";
import "./styles.css";

//import { makeStyles } from "@material-ui/core/styles";
import ExpansionPanel from "@material-ui/core/ExpansionPanel";
import ExpansionPanelSummary from "@material-ui/core/ExpansionPanelSummary";
import ExpansionPanelDetails from "@material-ui/core/ExpansionPanelDetails";
import Typography from "@material-ui/core/Typography";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import ClearIcon from "@material-ui/icons/Clear";
import TextField from "@material-ui/core/TextField";

const API_KEY = "MY_API_KEY";

/*const useStyles = makeStyles(theme => ({
  root: {
    width: "100%"
  },
  heading: {
    fontSize: theme.typography.pxToRem(15),
    fontWeight: theme.typography.fontWeightRegular
  }
}));*/

const useStyles = theme => ({
  root: {
    width: "100%"
  },
  heading: {
    fontSize: theme.typography.pxToRem(15),
    fontWeight: theme.typography.fontWeightRegular
  }
});

const center = {
  lat: 38.9065495,
  lng: -77.0518192
};

//const classes = useStyles();
//className={classes.heading}

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      paths: [
        { lat: 38.97330905858943, lng: -77.10469090410157 },
        { lat: 38.9209748864926, lng: -76.9083102888672 },
        { lat: 38.82689001319151, lng: -76.92204319902345 },
        { lat: 38.82261046915962, lng: -77.0181735701172 },
        { lat: 38.90174038629909, lng: -77.14314305253907 }
      ]
    };
  }

  render() {
    const { paths } = this.state;

    return (
      <div className="App2">
        <Map
          apiKey={API_KEY}
          center={center}
          paths={paths}
          point={paths => this.setState({ paths })}
        />
        {paths.map((pos, key) => {
          return (
            <ExpansionPanel key={key}>
              <ExpansionPanelSummary
                expandIcon={<ExpandMoreIcon />}
                aria-controls="panel1a-content"
                id="panel1a-header"
              >
                <ClearIcon
                  style={{ color: "#dc004e" }}
                  onClick={() => {
                    paths.splice(key, 1);
                    console.log(paths);
                    this.setState({ paths: paths });
                  }}
                />
                <Typography>Point #{key}</Typography>
              </ExpansionPanelSummary>
              <ExpansionPanelDetails>
                <TextField
                  fullWidth
                  key={"lat" + key}
                  label="Latitude"
                  type="text"
                  value={pos.lat}
                  disabled={true}
                />
                <TextField
                  fullWidth
                  key={"lng" + key}
                  label="Longitude"
                  type="text"
                  value={pos.lng}
                  disabled={true}
                />
              </ExpansionPanelDetails>
            </ExpansionPanel>
          );
        })}
      </div>
    );
  }
}

//export default withStyles(useStyles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

地图:

import React, { useState, useRef, useCallback } from "react";
import {
  LoadScript,
  GoogleMap,
  DrawingManager,
  Polygon,
  Marker
} from "@react-google-maps/api";

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 });
    }
  }
}

export default function Map({ apiKey, center, paths = [], point }) {
  const [path, setPath] = useState(paths);
  const [state, setState] = useState({
    drawingMode: "polygon"
  });

  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() });
      });
      setPath(paths);
      console.log("onPolygonComplete", paths);
      point(paths);
      noDraw();
      poly.setMap(null);
    },
    [point]
  );

  /*const onLoad = React.useCallback(function onLoad(map) {
    //console.log(map);
  }, []);

  const onDrawingManagerLoad = React.useCallback(function onDrawingManagerLoad(
    drawingManager
  ) {
    // console.log(drawingManager);
  },
  []);*/

  // 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() };
        });
      setPath(nextPath);
      point(nextPath);
    }
  }, [setPath, 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;
  }, []);

  console.log(path);

  return (
    <div className="App">
      <LoadScriptOnlyIfNeeded
        id="script-loader"
        googleMapsApiKey={apiKey}
        libraries={libraries}
        language="it"
        region="us"
      >
        <GoogleMap
          mapContainerClassName="App-map"
          center={center}
          zoom={10}
          version="weekly"
          //onLoad={onLoad}
        >
          {path.length === 0 ? (
            <DrawingManager
              drawingMode={state.drawingMode}
              options={options}
              onPolygonComplete={onPolygonComplete}
              //onLoad={onDrawingManagerLoad}
              editable
              draggable
              // Event used when manipulating and adding points
              onMouseUp={onEdit}
              // Event used when dragging the whole Polygon
              onDragEnd={onEdit}
            />
          ) : (
            <Polygon
              options={{
                fillColor: `#2196F3`,
                strokeColor: `#2196F3`,
                fillOpacity: 0.5,
                strokeWeight: 2
              }}
              // Make the Polygon editable / draggable
              editable
              draggable
              path={path}
              // Event used when manipulating and adding points
              onMouseUp={onEdit}
              // Event used when dragging the whole Polygon
              onDragEnd={onEdit}
              onLoad={onLoad}
              onUnmount={onUnmount}
            />
          )}
          {path.map((pos, key) => {
            return <Marker key={key} label={"" + key} position={pos} />;
          })}
        </GoogleMap>
      </LoadScriptOnlyIfNeeded>
    </div>
  );
}

在取消事件期间,在函数参数中使用该数组的索引调用函数。

removetheArray = value => {
    const { paths } = this.state;
    this.setState({
      paths: paths.splice(value, 1)
    });
  };

函数名称是 removetheArray 并将索引作为值传递,删除数组并更新地图以防地图未更新,您必须初始化地图。

将 useEffect 添加到 Map 组件以针对每个渲染更新 paths

export default function Map({ apiKey, center, paths = [], point }) {
  const [path, setPath] = useState();
  const [state, setState] = useState({
    drawingMode: "polygon"
  });
  useEffect(() => {
    setPath(paths);
  }, [paths]);
 .
 .
 .

并使用过滤器代替拼接

在 React 中你不应该直接改变状态。

 onClick={() => {
                    this.setState({
                      paths: this.state.paths.filter((_, i) => i !== key)
                    });

或者像下面这样拼接

 onClick={() => {
                   
                    const paths = this.state.paths;
                    this.setState({ 
                      paths: [...paths.slice(0,key), ...paths.slice(key+1)]})

                  }}

codesandbox