I have the following map, as you should on the map I have a polygon and markers which are the main points of the polygon, below I have the main points of the polygon printed, i.e. the markers.
I give the user the possibility to delete points of the polygon, as you can see below in the image by clicking on the X, the point is eliminated.
The problem is this, when I click on the X, the point is eliminated as a marker, but it seems to remain as a fixed point of the polygon, which it really shouldn't do, the polygon should change its shape, based on the eliminated point.
I am not able to understand where I am wrong. Can you give me some help.
Link: codesandbox
Index:
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);
Map:
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>
);
}