How to get borders for the react-leaflet map and check markers inside the map?
Asked Answered
W

1

3

My code is here:

import React, { useState, useEffect, useRef } from 'react';
import restaurantsInfo from "./RestaurantsList.json";
import "./App.css";
import { MapContainer, Marker, Popup, TileLayer, useMapEvents } from "react-leaflet";
import { Icon, latLng } from "leaflet";
import Restaurants from "./Restaurants.js";
import LocationMarker from "./LocationMarker.js";
import L from 'leaflet';

export default function App() {
    function LocationMarker() {
        const [position, setPosition] = useState(null);
        const [bbox, setBbox] = useState([]);
    
        const map = useMap();
    
        useEffect(() => {
          map.locate().on("locationfound", function (e) {
            setPosition(e.latlng);
            map.flyTo(e.latlng, map.getZoom());
            const radius = e.accuracy;
            const circle = L.circle(e.latlng, radius);
            circle.addTo(map);
            setBbox(e.bounds.toBBoxString().split(","));
          });
        }, [map]);
    
        return position === null ? null : (
          <Marker position={position} icon={icon}>
            <Popup>
              You are here. <br />
              Map bbox: <br />
              <b>Southwest lng</b>: {bbox[0]} <br />
              <b>Southwest lat</b>: {bbox[1]} <br />
              <b>Northeast lng</b>: {bbox[2]} <br />
              <b>Northeast lat</b>: {bbox[3]}
            </Popup>
          </Marker>
        );
      }
  return (
    <div class="container">
    <div style={{height: '400px', width: '500px'}} class="map">
    <MapContainer 
    center={[49.1951, 16.6068]} 
    zoom={defaultZoom} 
    scrollWheelZoom={false}>
    <TileLayer
      attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    />
<MapContainer/>

My question is, how can I use bbox to check if some of my markers is inside the map? When I try to apply:

if (bbox.contains(marker.getPosition())===true) 

or this:

if ((bbox[1] < marker.lat< bbox[3])&& (bbox[2] <marker.long <bbox[4]))

I faced the error: bbox is not defined

I don’t know how to return bbox from function LocationMarker(). I would be grateful for any help. Thank you.

Waltman answered 6/3, 2021 at 18:23 Comment(0)
K
2

You need to follow a slight different approach then:

Declare bbox variable on the parent component(App) and store the instance. You will need it to be able to use contains method later. you can pass bbox and setBbox as props on LocationMarker comp. Doing that you will have the communication between the two components.

Also move the LocationMarker comp outside the App.

Here is the LcoationMarker component:

function LocationMarker({ bbox, setBbox }) {
  const [position, setPosition] = useState(null);

  const map = useMap();

  useEffect(() => {
    map.locate().on("locationfound", function (e) {
      setPosition(e.latlng);
      map.flyTo(e.latlng, map.getZoom());
      const radius = e.accuracy;
      const circle = L.circle(e.latlng, radius);
      circle.addTo(map);
      setBbox(e.bounds);
    });
  }, [map,setBbox]);

  const boundingBox = bbox ? bbox.toBBoxString().split(",") : null;

  if (!position || !bbox) return null;
  return (
    <Marker position={position} icon={icon}>
      <Popup>
        You are here. <br />
        Map bbox: <br />
        <b>Southwest lng</b>: {boundingBox[0]} <br />
        <b>Southwest lat</b>: {boundingBox[1]} <br />
        <b>Northeast lng</b>: {boundingBox[2]} <br />
        <b>Northeast lat</b>: {boundingBox[3]}
      </Popup>
    </Marker>
  );
}

Here is the App component. You can use bbox isntance in this example via a button. Make sure to check that bbox is defined before using it.

function App() {
  const [bbox, setBbox] = useState(null);

  const handleClick = () => {
    if (bbox) alert(bbox.contains([49.1951, 16.6068]));
  };

  return (
    <>
      <MapContainer ...>
     ...
        <LocationMarker bbox={bbox} setBbox={setBbox} />
      </MapContainer>
      <button onClick={handleClick}>bbox contains</button>
    </>
  );
}

Here is a demo with all the pieces together

Kristakristal answered 6/3, 2021 at 19:13 Comment(11)
Thank you, it looks great, but I have more complicated app. I need to use bbox in another component. Please, take a look: github.com/AlonaVa/Restaurants Or would be better to create another question?Waltman
I saw your github repo and I think you already adjusted my answer to your code on Restaurants component. Do you want to use bbox variable elsewhere? By passing bbox as a prop it should be ok I guess with a first glance. Yes, if you have another question based on the given answer you should create another question.Kristakristal
Thank you for your time! The result of your alert from handleClick function is always “false”. Is it correct? I am afraid that it is some problem in communication between different components, because I got such errors-‘ bbox.toBBoxString is not a function’ for LocationMarker.js and -‘ bbox.contains is not a function’ for Restaurnts.jsWaltman
Are you sure you used a position that is included inside the bbox? If you get an error like the one you mention indeed there is a problem with the component communication. You should use bbox like in the demo. I will try to run the code from your github repo and let you know.Kristakristal
It would be great if you will manage to fix connections between the components. Yes, this position is inside the map, so if I got it right Bbox is not a border of the map but the border of the circle. We could try to apply bounds = map.getBounds() , but the problem with connections between the components will remain.Waltman
I went through your code and I have to say there are many many many errors. I fixed some of them but more keep coming up. You really need to fix all these errors so first you are able to work with this app and then to be able to help you more. Some notices. Your json is not a json but an array of objects instead. Remove json extension to the file and just export from inside. Moreover, remove all the code that is not used. there is plenty of that.Kristakristal
I have uploaded the working version of my app here: github.com/AlonaVa/NewRestaurants I just commented parts, that don’t work (there are functions for finding bounds and condition in Restaurants.js) Thank you very much for your time! You help me so much!Waltman
Check this demo. The problem was the initial value of bbox. You had it as [] and should be null. Now to get true the marker should be inside the bbox. If you have more questions you should create a new thread.Kristakristal
Wonderful! It works!!! You are a genius! Thank you very much!Waltman
I have the very last question. How can I automatically update bbounds with the change of the map position? Thank youWaltman
Sure, it is here: #66562568Waltman

© 2022 - 2024 — McMap. All rights reserved.