reactjs - React 传单 map 位置不在 App.js 中时出现故障

标签 reactjs leaflet geolocation openstreetmap react-leaflet

我正在尝试在我的 React 应用程序中使用 Leaflet map ,但遇到了一个奇怪的问题。我告诉我的 map 在whenReady函数中平移到用户当前的地理位置(如果他们允许访问他们的位置),但是当它这样做时, map 会出现故障。更奇怪的是,只有当我将 map 放入从 App.js 路由到的 View 中时才会发生这种情况(我想将其与导航栏一起显示)。当它位于 App.js 本身中时,不会发生这种情况,并且 map 会正确显示我的位置。我附上图片来说明我的意思:

本地图位于 App.js 中时: The map displays correctly with the pin in the center

本地图位于另一个组件中时: The map is entirely grey with the pin out of the center

这是我针对两种情况的代码:

map 位于 App.js 中时的代码:

import React, {Component} from 'react';
import L from 'leaflet';
import './MapView.css';
import fence from './assets/fence.png';
import pin from './assets/pin.png';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';

class App extends Component {
  constructor() {
    super();
    this.state = {
      markers: [],
      center: [51.505, -0.09]
    };
    this.addMarker = this.addMarker.bind(this)
  }

  fence = L.icon({
    iconUrl: fence,
    iconSize:     [46.3125, 51.5625], // size of the icon
    iconAnchor:   [22, 25], // point of the icon which will correspond to marker's location
    popupAnchor:  [0, -25]
  });
  
  addMarker = (e) => {
    const {markers} = this.state
    markers.push(this.state.center)
    this.setState({markers})
  }

  render() {
    const self = this;
    return (
      <div className="map-container">
        <button onClick={this.addMarker} className="btn">+</button>
        <div className="center"></div>
      <MapContainer 
        className="map"
        minZoom= {8}
        zoom={20} 
        center = {this.state.center}
        whenReady={(map) => {
          if ('geolocation' in navigator) {
            navigator.geolocation.getCurrentPosition(function (location) {
              console.log(location);
              map.target.panTo(new L.LatLng(location.coords.latitude, location.coords.longitude))

              var marker = L.marker([location.coords.latitude, location.coords.longitude], {icon: L.icon({
                iconUrl: pin,
                iconSize:     [24, 38], // size of the icon
                iconAnchor:   [12.5, 40], // point of the icon which will correspond to marker's location
                popupAnchor:  [0, -50]
              })} ).addTo(map.target);
              marker.bindPopup("Your current location")
              marker.openPopup()
            });
          }

          map.target.on("drag", function (e) {
            self.setState({center: map.target.getCenter()})
          });

          map.target.on("zoom", function (e) {
            self.setState({center: map.target.getCenter()})
          })
        }}
        >
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
        ></TileLayer>
        {this.state.markers.map((position, idx) => 
          <Marker key={`marker-${idx}`} icon={this.fence} position={position}>
          <Popup>
            <span>Title<br/></span>
          </Popup>
        </Marker>
        )}
      </MapContainer>
      </div>
    );
  }
}

export default App;

map 位于另一个 View 时的代码(从 App.js 路由):

//App.js
import React from "react";
import "./App.css";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import MapView from './MapView';
import AddView from './AddView';
import Navbar from './Navbar';

function App() {
  return (
    <div className="App">
      <Router>
      <Navbar/>
        <Switch>
          <Route exact from="/" component={MapView} />
          <Route exact path="/new" component={AddView} />
        </Switch>
      </Router>
    </div>
  );
}

export default App;

//MapView.js
import React, {Component} from 'react';
import L from 'leaflet';
import './MapView.css';
import fence from './assets/fence.png';
import pin from './assets/pin.png';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';

class MapView extends Component {
  constructor() {
    super();
    this.state = {
      markers: [],
      center: [51.505, -0.09]
    };
    this.addMarker = this.addMarker.bind(this)
  }

  fence = L.icon({
    iconUrl: fence,
    iconSize:     [46.3125, 51.5625], // size of the icon
    iconAnchor:   [22, 25], // point of the icon which will correspond to marker's location
    popupAnchor:  [0, -25]
  });
  
  addMarker = (e) => {
    const {markers} = this.state
    markers.push(this.state.center)
    this.setState({markers})
  }

  render() {
    const self = this;
    return (
      <div className="map-container">
        <button onClick={this.addMarker} className="btn">+</button>
        <div className="center"></div>
      <MapContainer 
        id="map"
        className="map"
        minZoom= {8}
        zoom={20} 
        center = {this.state.center}
        whenReady={(map) => {
            if ('geolocation' in navigator) {
              navigator.geolocation.getCurrentPosition(function (location) {
                localStorage.setItem('latitude', location.coords.latitude)
                localStorage.setItem('longitude', location.coords.longitude)
                let latitude= location.coords.latitude;
                let longitude= location.coords.longitude;
                console.log(location);

                map.target.panTo(new L.LatLng(latitude, longitude))
  
                var marker = L.marker([latitude, longitude], {icon: L.icon({
                  iconUrl: pin,
                  iconSize:     [24, 38], 
                  iconAnchor:   [12.5, 40], 
                  popupAnchor:  [0, -50]
                })} ).addTo(map.target);
                marker.bindPopup("Your current location")
                marker.openPopup()
              });
            } else {
                console.log("Ik kom erin bro wtf")
                let latitude = localStorage.getItem('latitude') ?? 51.505
                let longitude = localStorage.getItem('longitude') ?? -0.09

                map.target.panTo(new L.LatLng(latitude, longitude))
            }
  
            map.target.on("drag", function (e) {
              self.setState({center: map.target.getCenter()})
            });
  
            map.target.on("zoom", function (e) {
              self.setState({center: map.target.getCenter()})
            })
          }}
        >
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
        ></TileLayer>
        {this.state.markers.map((position, idx) => 
          <Marker key={`marker-${idx}`} icon={this.fence} position={position}>
          <Popup>
            <span>Title<br/></span>
          </Popup>
        </Marker>
        )}
      </MapContainer>
      </div>
    );
  }
}

export default MapView;

//Navbar.js
import { makeStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import {
    Link
  } from "react-router-dom";


const useStyles = makeStyles((theme) => ({
    root: {
      flexGrow: 1,
    },
    menuButton: {
      marginRight: theme.spacing(2),
    },
    title: {
      flexGrow: 1,
    },
    bar: {
        height: '7.5vh',
    }
  }));

function Navbar() {
    const classes = useStyles();

    return (
        <AppBar position="static" className={classes.bar}>
        <Toolbar>
          <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" className={classes.title}>
            Work in progress
          </Typography>
          <Link color="inherit" to="/new">Report construction</Link>
          <Button color="inherit">Login</Button>
        </Toolbar>
      </AppBar>
    );
  }
  
  export default Navbar;

我对Leaflet没有太多了解,因为这是我用它制作的第一个应用程序,所以如果我混淆了背后的一些理论,请考虑这一点。有谁知道我的代码、我的思维方式是否有问题,或者我是否缺少一些传单理论?我期待听到任何答案。

最佳答案

您可能想尝试在 whileReady() 内平移到您的位置之前设置延迟。函数启动时 map 可能未完全渲染,这也许可以解决问题

setTimeout(() => { this.goToLocation() }, 1000);

关于reactjs - React 传单 map 位置不在 App.js 中时出现故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66900080/

相关文章:

javascript - 地理位置将变量设置为当前位置

c# - 如何在 C# 应用程序中使用 HTML5 地理定位

javascript - firefox:navigator.geolocation.getCurrentPosition 不再成功

reactjs - 如何在 Link 组件 Material UI 中覆盖 Typography colorPrimary

reactjs - Gatsby 构建命令 - 内容丰富的插件无法从 .env 文件中获取 spaceId 和 accessToken

Leaflet map 事件上的Angular 7变量访问问题

javascript - event.latLng 在 Leaflet 中未定义

javascript - "Cannot read property ' 尝试设置状态 Prop 并将其传递到组件时状态 ' of undefined"

html - 如何在屏幕底部对齐元素在 Material ui中

postgresql - PostGis Multipolygon ERROR - 纵坐标太少