为什么切换视图后,叶片地图变成灰色?它发生在与地图互动后,然后在视图之间切换
我正在制作一个对话框,该对话框具有两个名为地址和地图的选项卡,该选项卡允许用户在地址选项卡中的两个不同的Textfields中输入城市名称和街道名称,并能够在地图中查明或自动限制位置。在地图选项卡中,我使用了React-Leaflet Map向用户显示映射本身,到目前为止是如此出色,但是在选项卡之间切换后,映射更改为单调灰色图像。放大进出不会有帮助!
代码:
import * as React from 'react';
import { useEffect, useState } from 'react';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import useMediaQuery from '@mui/material/useMediaQuery';
import CloseIcon from '@mui/icons-material/CloseOutlined';
import { Divider, IconButton, InputLabel, } from '@mui/material';
import { Box, Grid, Tab, TextField, useTheme } from '@material-ui/core';
import { TabContext, TabList, TabPanel } from '@mui/lab';
import "leaflet/dist/leaflet.css";
import icon from "../../../../Account/components/constants";
import { MapContainer, TileLayer, Marker, useMapEvents, } from 'react-leaflet'
const useGeoLocation = () => {
// this function will allow the user to get the current location of the device!
const [location, setLocation] = useState({
loaded: false,
coordinates: { lat: "", lng: "" }
});
const onSuccess = (location) => {
setLocation({
loaded: true,
coordinates: {
lat: location.coords.latitude,
lng: location.coords.longitude,
}
});
};
const onError = (error) => {
setLocation({
loaded: true,
error,
});
};
useEffect(() => {
if (!("geolocation" in navigator)) {
onError({
code: 0,
message: "Your device GPS is OFF!",
});
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}, []);
return location;
}
export default function AddressDialog() {
// Genral Properties!
const [open, setOpen] = useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [value, setValue] = useState(0);
// Address Tab Properties!
const [city, setCity] = useState("");
const [street, setStreet] = useState();
// Map Properties!
const [initializerPos,] = useState([40.689247, -74.044502]);
const [position, setPosition] = useState(initializerPos);
const [mapState, setMapState] = useState({
position: position,
map: null
});
const zoom_level = 18;
const location = useGeoLocation();
// Arrow funcitons!
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
setValue(0);
};
const handleSubmit = () => {
// api update in here
}
const showMyLocation = () => {
if (location.loaded && !location.error) {
let pos = [location.coordinates.lat, location.coordinates.lng];
setPosition([location.coordinates.lat, location.coordinates.lng]);
setMapState((state) => ({
...state,
position: pos,
}));
const { map } = mapState;
if (map) {
map.flyTo(pos, zoom_level);
}
} else {
if (location.error) {
alert(location.error.message)
}
else {
alert("Problem in loading curent location!")
}
}
};
function AddMarkerToClick() {
const [markers, setMarkers] = useState([]);
useMapEvents({
click(e) {
const newMarker = e.latlng
setMarkers([...markers, newMarker]);
setPosition([e.latlng.lat, e.latlng.lng]);
setMapState((state) => ({
...state,
position: newMarker,
}));
const { map } = mapState;
if (map)
{
map.flyTo(newMarker, zoom_level);
}
},
});
return null
};
return (
<div dir="ltr">
<Button onClick={handleClickOpen} variant="contained" type="button" aria-label="Edit Info" fullWidth size="small">
Edit Address Info
</Button>
<Dialog fullScreen={fullScreen} open={open} aria-labelledby="responsive-dialog-title">
<DialogTitle>
<IconButton onClick={handleClose} aria-label="Close Dialog">
<CloseIcon fontSize="medium" />
</IconButton>
</DialogTitle>
<Divider />
<DialogTitle>Edit Address</DialogTitle>
<DialogContent id ="dialogContent" >
<DialogContentText>
In this section you are able to edit your address info
</DialogContentText>
<TabContext value={value.toString()} >
<Box >
<TabList
onChange={(event, newValue) => { setValue(parseInt(newValue, 10));}}
aria-label="address-map-tab">
<Tab label="Address" value="0" />
<Tab label="Map" value="1" />
</TabList>
</Box>
<TabPanel value="0">
<Grid container spacing={theme.spacing(0)}
>
<Grid item xs={12} sm={6}>
<TextField value={city} onChange={(e) => setCity(e.target.value)} margin="normal" variant="outlined"
required
fullWidth
type="text"
name="area"
id="area"
label={"city"}
placeholder={"ex: New York"}
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
value={street}
onChange={(e) => setStreet(e.target.value)}
margin="normal"
variant="outlined"
required
fullWidth
type="text"
name="street"
id="street"
label={"Streen Name"}
placeholder={"ex: wall street"}
/>
</Grid>
</Grid>
</TabPanel>
<TabPanel value="1">
<Grid container>
<div style={{
marginLeft: "auto",
marginRight: "auto",
width: "100%"
}}>
<InputLabel>
Your location in map:
</InputLabel>
<MapContainer
center={mapState.position}
zoom ={15}
scrollWheelZoom
style={{
height: fullScreen ? 200 : 350,
width: fullScreen ? "100%" : "100%",
textAlign: "center",
marginLeft: "auto",
marginRight: "auto",
marginTop: theme.spacing(1)
}}
whenCreated={map => setMapState({ map })}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<AddMarkerToClick />
{
position && (
<Marker position={position} icon={icon}></Marker>
)
}
</MapContainer>
<Button variant="outlined" color="primary" size="large" onClick={showMyLocation}>
Here!
</Button>
</div>
</Grid>
</TabPanel>
</TabContext>
</DialogContent>
<DialogActions style={{ marginLeft: theme.spacing(2), marginRight: theme.spacing(2) }}>
<Grid container direction="row" spacing={1}>
<Grid item container xs={4} dir="left" justifyContent="flex-end">
<Button variant="contained" type="button" color="error" fullWidth
name="cancel-btn" onClick={handleClose}
>
Cancel
</Button>
</Grid>
<Grid item container xs={8} >
<Button variant="contained" type="button" color="primary" fullWidth
name="submit-btn" onClick={handleSubmit} >
Save
</Button>
</Grid>
</Grid>
</DialogActions>
</Dialog>
</div>
);
在选项卡之间切换后,地图变成灰色,什么也没显示!
然后与映射进行交互,例如单击它,放大或输出结果导致错误!
未接收错误:设置地图中心并首先缩放。
I was making a dialog which has two tabs named Address and Map, which allows the user to enter city name and street name in two different textfields in address tab and be able to pinpoint or auto-locate the location in the map. In map tab I was using react-leaflet map to show the map itself to the user, so far so good but after switching between tabs the map changes to a monotonic gray image. zoom in and out won't help it!
Code:
import * as React from 'react';
import { useEffect, useState } from 'react';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import useMediaQuery from '@mui/material/useMediaQuery';
import CloseIcon from '@mui/icons-material/CloseOutlined';
import { Divider, IconButton, InputLabel, } from '@mui/material';
import { Box, Grid, Tab, TextField, useTheme } from '@material-ui/core';
import { TabContext, TabList, TabPanel } from '@mui/lab';
import "leaflet/dist/leaflet.css";
import icon from "../../../../Account/components/constants";
import { MapContainer, TileLayer, Marker, useMapEvents, } from 'react-leaflet'
const useGeoLocation = () => {
// this function will allow the user to get the current location of the device!
const [location, setLocation] = useState({
loaded: false,
coordinates: { lat: "", lng: "" }
});
const onSuccess = (location) => {
setLocation({
loaded: true,
coordinates: {
lat: location.coords.latitude,
lng: location.coords.longitude,
}
});
};
const onError = (error) => {
setLocation({
loaded: true,
error,
});
};
useEffect(() => {
if (!("geolocation" in navigator)) {
onError({
code: 0,
message: "Your device GPS is OFF!",
});
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}, []);
return location;
}
export default function AddressDialog() {
// Genral Properties!
const [open, setOpen] = useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [value, setValue] = useState(0);
// Address Tab Properties!
const [city, setCity] = useState("");
const [street, setStreet] = useState();
// Map Properties!
const [initializerPos,] = useState([40.689247, -74.044502]);
const [position, setPosition] = useState(initializerPos);
const [mapState, setMapState] = useState({
position: position,
map: null
});
const zoom_level = 18;
const location = useGeoLocation();
// Arrow funcitons!
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
setValue(0);
};
const handleSubmit = () => {
// api update in here
}
const showMyLocation = () => {
if (location.loaded && !location.error) {
let pos = [location.coordinates.lat, location.coordinates.lng];
setPosition([location.coordinates.lat, location.coordinates.lng]);
setMapState((state) => ({
...state,
position: pos,
}));
const { map } = mapState;
if (map) {
map.flyTo(pos, zoom_level);
}
} else {
if (location.error) {
alert(location.error.message)
}
else {
alert("Problem in loading curent location!")
}
}
};
function AddMarkerToClick() {
const [markers, setMarkers] = useState([]);
useMapEvents({
click(e) {
const newMarker = e.latlng
setMarkers([...markers, newMarker]);
setPosition([e.latlng.lat, e.latlng.lng]);
setMapState((state) => ({
...state,
position: newMarker,
}));
const { map } = mapState;
if (map)
{
map.flyTo(newMarker, zoom_level);
}
},
});
return null
};
return (
<div dir="ltr">
<Button onClick={handleClickOpen} variant="contained" type="button" aria-label="Edit Info" fullWidth size="small">
Edit Address Info
</Button>
<Dialog fullScreen={fullScreen} open={open} aria-labelledby="responsive-dialog-title">
<DialogTitle>
<IconButton onClick={handleClose} aria-label="Close Dialog">
<CloseIcon fontSize="medium" />
</IconButton>
</DialogTitle>
<Divider />
<DialogTitle>Edit Address</DialogTitle>
<DialogContent id ="dialogContent" >
<DialogContentText>
In this section you are able to edit your address info
</DialogContentText>
<TabContext value={value.toString()} >
<Box >
<TabList
onChange={(event, newValue) => { setValue(parseInt(newValue, 10));}}
aria-label="address-map-tab">
<Tab label="Address" value="0" />
<Tab label="Map" value="1" />
</TabList>
</Box>
<TabPanel value="0">
<Grid container spacing={theme.spacing(0)}
>
<Grid item xs={12} sm={6}>
<TextField value={city} onChange={(e) => setCity(e.target.value)} margin="normal" variant="outlined"
required
fullWidth
type="text"
name="area"
id="area"
label={"city"}
placeholder={"ex: New York"}
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
value={street}
onChange={(e) => setStreet(e.target.value)}
margin="normal"
variant="outlined"
required
fullWidth
type="text"
name="street"
id="street"
label={"Streen Name"}
placeholder={"ex: wall street"}
/>
</Grid>
</Grid>
</TabPanel>
<TabPanel value="1">
<Grid container>
<div style={{
marginLeft: "auto",
marginRight: "auto",
width: "100%"
}}>
<InputLabel>
Your location in map:
</InputLabel>
<MapContainer
center={mapState.position}
zoom ={15}
scrollWheelZoom
style={{
height: fullScreen ? 200 : 350,
width: fullScreen ? "100%" : "100%",
textAlign: "center",
marginLeft: "auto",
marginRight: "auto",
marginTop: theme.spacing(1)
}}
whenCreated={map => setMapState({ map })}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<AddMarkerToClick />
{
position && (
<Marker position={position} icon={icon}></Marker>
)
}
</MapContainer>
<Button variant="outlined" color="primary" size="large" onClick={showMyLocation}>
Here!
</Button>
</div>
</Grid>
</TabPanel>
</TabContext>
</DialogContent>
<DialogActions style={{ marginLeft: theme.spacing(2), marginRight: theme.spacing(2) }}>
<Grid container direction="row" spacing={1}>
<Grid item container xs={4} dir="left" justifyContent="flex-end">
<Button variant="contained" type="button" color="error" fullWidth
name="cancel-btn" onClick={handleClose}
>
Cancel
</Button>
</Grid>
<Grid item container xs={8} >
<Button variant="contained" type="button" color="primary" fullWidth
name="submit-btn" onClick={handleSubmit} >
Save
</Button>
</Grid>
</Grid>
</DialogActions>
</Dialog>
</div>
);
After switching between tabs, the map grayed out, and shows nothing!
Then interacting with map, e.g, clicking on it, zoom in or out results the error!
Uncaught Error: Set map center and zoom first.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的解决方案:
我所做的是保存映射的当前(在与映射的第一次互动之后),然后尝试从保存状态重新启动它以备将来使用(切换到其他选项卡/视图)。
为了保存地图的状态,在从地图视图中切换之前,它应该正好发生!在这种情况下,在切换回地址选项卡或关闭对话框之前。
固定代码:
我在代码中做了一些评论以演示解决方案。如果您知道一个更好的解决方案,我期待看到它。
My Solution:
What I did is to save the current (after first interaction with map) state of the map and then try to restart it from saved state for future use (switching to other tabs/views).
To save the state of the map, It should happen right exactly before switching out from the map view! In this case before switching back to address tab or closing The Dialog.
Fixed Code:
I did some comments in the code to demonstrate the solution. If you know a better solution to this problem I looking forward to see it.