Breno Augusto
Breno Augusto

Reputation: 21

React-leaflet center of an array of positions

Helllo! I'm trying to set the center of the map based the following array:

[[-23.568767,-46.649907],[-23.565972,-46.650859],[-23.563703,-46.653542],[-23.616359,-46.664749],[-23.624203,-46.683369],[-23.565972,-46.650859],[-23.572424,-46.65384],[-23.610235,-46.69591],[-23.609215,-46.69753],[-23.608786,-46.697448],[-23.617262,-46.674802],[-23.620757,-46.673658],[-23.625349,-46.692239],[-23.565972,-46.650859],[-23.564909,-46.654558],[-23.642676,-46.672727],[-23.608786,-46.697448],[-23.610652,-46.686046],[-23.573285,-46.689102],[-23.609215,-46.667182],[-23.609215,-46.667182],[-23.60997,-46.667902],[-23.584718,-46.675473],[-23.584718,-46.675473],[-23.607909,-46.692784],[-23.594718,-46.635473],[-23.564552,-46.654713],[-23.573263,-46.695077],[-23.633372,-46.680053],[-23.64717,-46.727572],[-23.576715,-46.68747],[-23.609215,-46.667182],[-23.609215,-46.667182],[-23.52631,-46.616194],[-23.614064,-46.668883],[-23.608786,-46.697448],[-23.587921,-46.6767],[-23.573691,-46.643678],[-23.573691,-46.643678],[-23.627158,-46.675183],[-23.573263,-46.695077],[-23.573263,-46.695077],[-23.572269,-46.689863],[-23.573263,-46.695077],[-23.628932,-46.665837],[-23.61506,-46.659242],[-23.528071,-46.586955],[-23.595269,-46.669645],[-23.596066,-46.686917],[-23.627158,-46.675183]]

I've tried get the bounds with Leaflet.latLngBounds:

const bounds = L.latLngBounds(latLngs);

and got the following errors:

leaflet-src.js:1658 Uncaught TypeError: Cannot read property 'lat' of null at Object.project (leaflet-src.js:1658) at Object.latLngToPoint (leaflet-src.js:1497) at NewClass.project (leaflet-src.js:3931) at NewClass._getNewPixelOrigin (leaflet-src.js:4425) at NewClass._move (leaflet-src.js:4173) at NewClass._resetView (leaflet-src.js:4135) at NewClass.setView (leaflet-src.js:3190) at NewClass.initialize (leaflet-src.js:3132) at new NewClass (leaflet-src.js:300) at Map.createLeafletElement (Map.js:99)

Uncaught TypeError: Cannot read property 'off' of undefined at Map.componentWillUnmount (Map.js:258) at callComponentWillUnmountWithTimer (react-dom.development.js:15784) at HTMLUnknownElement.callCallback (react-dom.development.js:149) at Object.invokeGuardedCallbackDev (react-dom.development.js:199) at invokeGuardedCallback (react-dom.development.js:256) at safelyCallComponentWillUnmount (react-dom.development.js:15791) at commitUnmount (react-dom.development.js:16159) at commitNestedUnmounts (react-dom.development.js:16190) at unmountHostComponents (react-dom.development.js:16446) at commitDeletion (react-dom.development.js:16498)

The above error occurred in the component: in Map (created by ShopMap) in ShopMap (created by App) in div (created by Context.Consumer) in StyledComponent (created by styled.div) in div (created by App) in div (created by Context.Consumer) in StyledComponent (created by styled.div) in App (created by AppContainer) in AppContainer (created by Connect(AppContainer)) in Connect(AppContainer) in Provider

Uncaught Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. at Object.invokeGuardedCallbackDev (react-dom.development.js:210) at invokeGuardedCallback (react-dom.development.js:256) at commitRoot (react-dom.development.js:17442) at completeRoot (react-dom.development.js:18898) at performWorkOnRoot (react-dom.development.js:18827) at performWork (react-dom.development.js:18735) at performSyncWork (react-dom.development.js:18709) at requestWork (react-dom.development.js:18578) at scheduleWork (react-dom.development.js:18387) at scheduleRootUpdate (react-dom.development.js:19055)

Then I tried create a FeatureGroup and add Markers based on the array:

const group = new L.FeatureGroup();

positions.forEach((latitude, longitude) => {
  L.marker([latitude, longitude]).addTo(group);
});

But results on the following:

LatLngBounds {}

And the Map component:

const ShopMap = ({ shops }) => {
  const positions = shops.reduce((newArray, shop) => {
    return [
      ...newArray,
      {
        latitude: shop.latitude,
        longitude: shop.longitude
      }
    ]
  }, []);

  return (
    <Map center={getLatLngBounds(positions)} zoom={15}>
      <TileLayer
        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      {shops &&
        shops.map(({ latitude, longitude, revenueLowerThanExpected, name }) => {
          return (
            <Marker
              key={name}
              icon={revenueLowerThanExpected ? redMarker : blueMarker}
              position={[
                latitude,
                longitude
              ]}
            />
          );
        })}
    </Map>
  );
};

Someone could help me with this?

Upvotes: 1

Views: 3483

Answers (1)

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59328

Map.center property expects a latLng value but what you are after is Map.bounds property which:

A rectangle for the map to contain. It will be centered, and the map will zoom in as close as it can while still showing the full bounds

In case of Map.bounds value, it could be provided as an array of {lat,lng} values, in your case

const getLatLngBounds = () => {
  return  [
    [-23.568767, -46.649907],
    [-23.565972, -46.650859],
    [-23.563703, -46.653542],
    [-23.616359, -46.664749],
    [-23.624203, -46.683369],
    ...
  ];
} 




 <Map bounds={getLatLngBounds()} >
    <TileLayer 
      url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'/>
</Map>

Refer this example for a more details.

Or as L.latLngBounds value, here is a demo for your reference.

Upvotes: 2

Related Questions