简体   繁体   中英

Want to Update the Center of MapContainer of React-Leaflet-js

I have started using React recently. But when I started React-Leaflet Map, I have get problems. I have a Json file of all countries and I want to zoom upon only that country which I selected. But I have no idea how can I do it?

function Map({ center, zoom }) {
    return (
        <div className="map">
            <MapContainer center={center} zoom={zoom} scrollWheelZoom={true}>
                <TileLayer attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
            </MapContainer>
        </div>
    )
}

Here is My Map.js file, which I've import in my App.js file & give it the data by using useState method.

So leaflet positioning (like most web mapping libraries) works on latitude and longitude. The API you referenced in your comment takes in a country name as a parameter, and returns some COVID data. In order to get your map to respond to respond appropriately, you need to geocode the country names. A quick search found me this repo which has the county name and the latlng of the center of the country: https://github.com/eesur/country-codes-lat-long .

The json file referenced there has data in the format:

{
  "country" : "Albania",
  "alpha2" : "AL",
  "alpha3" : "ALB",
  "numeric" : 8,
  "latitude" : 41,
  "longitude" : 20
}

For simplicity, let's say we download that file, rename it as a.js, and import the contents. Now you have all that data available to you.

Your code doesn't show where you are making the API call to get your COVID data. But let's say there's a function you call that set's the state variable selectedCountry . You can have a useEffect which responds to that state variable:

import countrycodes from './country-codes-lat-long-alpha3.js'

function App() {

  const [selected, setSelected] = useState("")
  const [center, setCenter] = useState([55, 122]) // some initial state

  // Call this effect whenever selected changes
  // (assuming the value of selected is an alpha3 3 character country code)
  useEffect(() => {
    if (selected){
      fetch(`/v3/covid-19/countries/${selected}`)
        .then(res => {
          // do something with your response data
          // set the map center to the lat lng defined by the reference json
          const countryData = countrycodes.ref_country_codes.filter(country => 
            country.alpha3 === selected
          )[0]
          const countryLatLng = {
            lat: countryData.latitude,
            lng: countryData.longitude,
          }
          setCenter(countryLatLng)
        })
    }
  }, [selected])
  

  return (
    <div>
      <Map center={center} />
      <select onChange={() => setSelected(e.target.value}>
        {a_bunch_of_country_options}
      </select>
    <div>
  )
}

To summarize, your <select> element will set the selected state variable. When selected changes, it triggers the useEffect , which calls your api and does whatever you want with the data. When the data returns, the effect checks the reference data to get the latlng of the selected country. setCenter then sets the state variable center to that latlng, which is passed to the map. The map should respond by adjusting its center.

This is just a basic outline of how you would accomplish your goal. The primary issue with what I've written is that it only sets the center of the map. Probably the effect you're looking for is to set the map view to show the country. In order to do that, you need not just the center latlng of the country, but the entire LatLngBounds of the selected country. Getting this kind of data is not quite so straightforward. Take a look at this thread in the GIS stack exchange about getting that data.

Let's say you are able to get a datasource that can give you the bounds of a country based on the country's name or 2/3 letter code. For example:

[
  {
    "country" : "Albania",
    "alpha2" : "AL",
    "alpha3" : "ALB",
    bounds: [ // made up
      {
        lat: 40.712, 
        lng: -74.227
      },
      {
        lat: 42.712, 
        lng: -72.227
      },  
  }
  ... // all the other countries
]

You can use the same method I described above, but instead of doing 

```javascript
const [center, setCenter] = useState(initialCenter)

you would do

const [bounds, setBounds] = useState()

Then you can set the bounds prop of the MapContainer in your useEffect:


  const [bounds, setBounds] = useState()

  useEffect(() => {
    if (selected){
      fetch(`/v3/covid-19/countries/${selected}`)
        .then(res => {
          const countryData = countrycodes.ref_country_codes.filter(country => 
            country.alpha3 === selected
          )[0]
          setBounds(country.bounds)
        })
    }
  }, [selected])
  

  return (
    <div>
      <Map center={someInitialCenter} bounds={bounds} />
      ...
    <div>
  )

This would create the effect that once the user selects the dropdown, the map fits the country's bounds, and the country is in frame. Of course you need the right datasource, and finding that is a task unto itself beyond the scope of your question.

In conclusion, there's nothing built in to leaflet or react-leaflet that will find the right coordinates on the map just based on the country name. You need a way to geocode the country's coordinates based on its name, then harness that in your map. Hope this gets your started.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM