Etiquetas

React-Leafet(Busqueda y localizacion)

 

Este blog tiene como finalidad de compartir conocimientos y aportar un granito más de información. Comparto mis apuntes e información que he encontrado por Internet, teniendo en cuenta que muchas ideas escritas no son propias, en la parte inferior coloco la url de los sitios donde esta la idea original ... espero que les sea de utilidad. 


Busqueda en archivo json para presentarlo en capa

Codigo de App.js


import './App.css';

import MapView from './components/MapView';
function App() {
  return (
    <div>
      <p>mapa</p>
      <MapView/>
    </div>
  );
}

export default App;


Codigo de MapView.js

import React, { useState, useRef } from 'react';
import {
  TileLayer,
  MapContainer,
  LayerGroup,
} from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import { BusquedaBoton } from "./busquedaBoton";
import EstadosMunicipiosFuerza from './estadosMunicipiosFuerza';
import { ZoomDisplay } from './evento_mapa'
import { CapturaClick } from './capturaCiclk'
import {UbicarCoordenada} from './ubicarCoordenada'


const MapView = () => {
  const [position, setPosition] = useState([0, 0]);
  const mapRef = useRef(null);
  const layerGroupRef = useRef(null);

  const ResetMapButton = ({ layerGroupRef }) => {
    const handleResetClick = () => {
      if (mapRef.current) {

        layerGroupRef.current.clearLayers();
        /*  mapRef.current.setView([20.521602, -99.893896], 5); */

      }
    };

    return (
      <button
        onClick={handleResetClick}
        style={{
          position: 'absolute',
          top: '10px',
          left: '60px',
          zIndex: 1000,
        }}
      >
        Restablecer Mapa
      </button>
    );
  };

  const handleMapClick = (e) => {
    const { lat, lng } = e.latlng;
    setPosition([lat, lng]);
  };

  const handleMapReady = (map) => {
    map.on("click", handleMapClick);
    mapRef.current = map;
  };


  return (
    <>
      <MapContainer
        center={[20.521602, -99.893896]}
        zoom={10}
        scrollWheelZoom={true}
        whenReady={({ target: map }) => handleMapReady(map)}
        style={{ height: "100vh", width: "100%" }}
      >
        <TileLayer url="https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}" />
       
        <ZoomDisplay />        
        <LayerGroup ref={layerGroupRef}>
        <CapturaClick layerGroupRef={layerGroupRef}/>
        </LayerGroup>
      </MapContainer>

      <ResetMapButton layerGroupRef={layerGroupRef}  />
      <EstadosMunicipiosFuerza punto={position} layerGroupRef={layerGroupRef} />
      <BusquedaBoton layerGroupRef={layerGroupRef} mapRef={mapRef} />
      <UbicarCoordenada layerGroupRef={layerGroupRef} mapRef={mapRef} />
    </>
  )
}
export default MapView  

Codigo de estadosMunicipiosFuerza.js

import React from 'react';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import mun from "./municipios_js/municipios_sep"

import {
    point,
    polygon,
    booleanPointInPolygon,
} from '@turf/turf';

const createPolygons = (coordinatesArray) => {
    return coordinatesArray.map(coords => polygon([coords]));
};

const EstadosMunicipiosFuerza = ({ punto, layerGroupRef }) => {

    let estadolocalizado = "";
    let coordenadasEstado = [];
    let municipiolocalizado = "";
    let coordenadasMunicipio = [];
    const pointObj = point([punto[0], punto[1]]);

    if (punto[0] === 0) { return null; }
    mun?.forEach((estado) => {
        let polygonObj = polygon(estado.COORDINATES);
        const isPointInsidePolygon = booleanPointInPolygon(pointObj, polygonObj);
        if (isPointInsidePolygon) {
            estadolocalizado = estado.NOM
            coordenadasEstado = estado.COORDINATES
            estado.MUNICIPYES?.forEach(element => {
                let polygonObjmun = createPolygons(element.coordinates);
                polygonObjmun.forEach((polygon, index) => {
                    const isPointInsidePolygonmun = booleanPointInPolygon(pointObj, polygon);
                    if (isPointInsidePolygonmun) {
                        municipiolocalizado = element.properties.NOM_MUN
                        coordenadasMunicipio = element.coordinates
                    }
                });
            })
        }
    })
    if(municipiolocalizado !==''){
    layerGroupRef.current.clearLayers();

    const newPolygonEstado = new L.Polygon(coordenadasEstado,{
        color: "#ff0000",
        weight: 1,
        opacity: 0.3,
        fillColor: "#ff7800",
        fillOpacity: 0.3
      });
    layerGroupRef.current.addLayer(newPolygonEstado);
   
    const newPolygonMunicipio = new L.Polygon(coordenadasMunicipio,{
        color: "#641e16",
        weight: 2,
        opacity: 0.5,
        fillColor: "#e6b0aa",
        fillOpacity: 0.5
      })/* .bindPopup("<b> Estado </b> : <br>" + estadolocalizado + " <br> <b>Municipio</b> : <br>" + municipiolocalizado) */;
    layerGroupRef.current.addLayer(newPolygonMunicipio);
    }else{
       
        alert("coordenadas fuera del territorio nacional  ****  click ***");
        layerGroupRef.current.clearLayers();
    }
    return (null);

};
export default EstadosMunicipiosFuerza

Codigo de busquedaBoton.js

import React, { useState, useEffect } from 'react';
import { Buscar } from "./buscar";
import L from 'leaflet';
import { polygon, centroid } from '@turf/turf';
import 'leaflet/dist/leaflet.css';

export const BusquedaBoton = ({ layerGroupRef, mapRef}) => {
  const [texBuscar, setTexBuscar] = useState('');
  const [resuelto, setResuelto] = useState('');
  const [centroide, setCentroide] = useState([0,0]);
  const [zoomapa, setZoomapa]=useState(0);
 
  const handleBuscar = async () => {
    const coordenadas = await Buscar({ texBuscar });
    setResuelto(coordenadas);
    setTexBuscar('');
  }

  useEffect(() => {
    if (layerGroupRef.current) {
      layerGroupRef.current.clearLayers();
    }

    if (resuelto.estado && resuelto.estado.length > 0) {
      const newPolygonEstado = new L.Polygon(resuelto.estado, {
        color: "#1b4f72",
        weight: 1,
        opacity: 0.9,
        fillColor: "#85c1e9",
        fillOpacity: 0.7
      });
      layerGroupRef.current.addLayer(newPolygonEstado);
      const estadoPolygon = polygon(resuelto.estado);
      const estadoCentroide = centroid(estadoPolygon).geometry.coordinates;
      setCentroide(estadoCentroide);
      setZoomapa(7);
    }

    if (resuelto.municipio && resuelto.municipio.length > 0) {
      const newPolygonMunicipio = new L.Polygon(resuelto.municipio, {
        color: "#4a235a",
        weight: 2,
        opacity: 0.5,
        fillColor: "#bb8fce",
        fillOpacity: 0.5
      });
      layerGroupRef.current.addLayer(newPolygonMunicipio);
      const municipioPolygon = polygon(resuelto.municipio);
      const municipioCentroide = centroid(municipioPolygon).geometry.coordinates;
      setCentroide(municipioCentroide);
      setZoomapa(11);
    }

  }, [resuelto, layerGroupRef]);

  useEffect(() => {
    if (centroide[0]>1) {
      mapRef.current.setView(centroide,zoomapa);

    }
  },[centroide,mapRef,zoomapa]);

  return (
    <>
      <div style={{
        position: 'absolute',
        top: '30px',
        left: '60px',
        zIndex: 1000,

      }}>
        <input
          type="text"
          value={texBuscar}
          onChange={(x) => setTexBuscar(x.target.value)}
          placeholder="Estado, Municipio"

        />
        <button onClick={handleBuscar}>Buscar capa</button>
      </div>
    </>
  );
};


Codigo buscar.js

import mun from "./municipios_js/municipios_sep"

const operacionBusqueda = ({ texBuscar }) => {

  return new Promise((resolve) => {
    const parts = texBuscar.split(',').map(part => part.trim());

    if(parts.length>1){
      mun?.forEach((estado) => {
        if (estado.NOM.toUpperCase() === parts[0].toUpperCase()) {
          estado.MUNICIPYES?.forEach(element => {
            if (element.properties.NOM_MUN.toUpperCase() === parts[1].toUpperCase()) {
              resolve({ estado: estado.COORDINATES,nomestado:estado.NOM,municipio: element.coordinates, nommunicipio: element.properties.NOM_MUN});
            }
          })
        }
      });
    }else{
      mun?.forEach((estado) => {
        if (estado.NOM.toUpperCase() === parts[0].toUpperCase()) {          
            resolve({ estado: estado.COORDINATES,nomestado:estado.NOM});
          }
      });
    }
  });

};

export const Buscar = async ({ texBuscar }) => {
  try {
    const data = await operacionBusqueda({ texBuscar });
    return data;
  } catch (err) {
    console.log("error", texBuscar, " ### ", err);
  } finally {
    console.log("finaliza", texBuscar);
  }

};


Codigo capturar click.js

import React, { useState, useEffect } from 'react';
import { useMapEvent } from 'react-leaflet';
import L from 'leaflet';
import icon from "./icon";

export const CapturaClick = ({ layerGroupRef }) => {
    const [coordenadas, setCoordenadas] = useState([]);
    const [click, setClick] = useState([]);

    useMapEvent('mousemove', (event) => {
        if (event.latlng) {
            setCoordenadas([event.latlng.lat, event.latlng.lng]);
        }
    });

    useMapEvent('click', () => {
        if (coordenadas.length > 0) {
            setClick(coordenadas);
        }
    });

    useEffect(() => {
        if (click.length > 0 && layerGroupRef.current) {
            const newMarker = new L.Marker(click,{icon:icon}).bindPopup("Coordenadas : <br>"+click);
            layerGroupRef.current.addLayer(newMarker);
        }
    }, [click, layerGroupRef]);

    return (null);
};

Codigo icon.js
import L from "leaflet"
const icon = L.icon({
  iconSize: [25, 41],
  iconAnchor: [15, 41],
  popupAnchor: [2, -40],
  iconUrl: "https://unpkg.com/leaflet@1.7/dist/images/marker-icon.png",
  shadowUrl: "https://unpkg.com/leaflet@1.7/dist/images/marker-shadow.png"
});

export default icon;

Codigo ubicarCoordenada

import React, { useState, useEffect } from 'react';
import icon from "./icon";
import L from 'leaflet';
import mun from "./municipios_js/municipios_sep"
import { point, polygon, booleanPointInPolygon } from '@turf/turf';

const createPolygons = (coordinatesArray) => {
    return coordinatesArray.map(coords => polygon([coords]));
};

const BuscarPoligono = ({ coordenadas }) => {
    const pointObj = point([coordenadas[0], coordenadas[1]]);
    let polygonObj;
    let isPointInsidePolygon
    let polygonObjmun
    let isPointInsidePolygonmun
    let objcoordenadas = null;

    mun?.forEach((estado) => {
        polygonObj = polygon(estado.COORDINATES);
        isPointInsidePolygon = booleanPointInPolygon(pointObj, polygonObj);
        if (isPointInsidePolygon) {
            estado.MUNICIPYES?.forEach(element => {
                polygonObjmun = createPolygons(element.coordinates);
                polygonObjmun.forEach((polygon) => {
                    isPointInsidePolygonmun = booleanPointInPolygon(pointObj, polygon);
                    if (isPointInsidePolygonmun) {
                        objcoordenadas = { estado: estado.NOM, cooestado: estado.COORDINATES, municipio: element.properties.NOM_MUN, coomunicipio: element.coordinates };
                    }
                });
            })
        }
    });
    console.log("salida de la busqueda",objcoordenadas)
    return objcoordenadas;
}

export const UbicarCoordenada = ({ layerGroupRef, mapRef }) => {
    const [coordenadasBuscar, setCoordenadasBuscar] = useState('');
    const [coordenadas, setCoordenadas] = useState([]);
    const [bandera, setbandera]=useState(null);

    const handleUbicar = () => {
        if(coordenadasBuscar!==''){
        const partes = coordenadasBuscar.split(',').map(part => part.trim());
        setCoordenadas(partes);
        setCoordenadasBuscar('');
        }
    }

    useEffect(() => {
        if (coordenadas.length > 0 && layerGroupRef.current) {
            const coordenadasPoligono = BuscarPoligono({ coordenadas });
            setbandera(coordenadasPoligono);
            if(coordenadasPoligono!==null){
                layerGroupRef.current.clearLayers();
                const newPolygonEstado = new L.Polygon(coordenadasPoligono.cooestado, {
                    color: "#424949",
                    weight: 1,
                    opacity: 1,
                    fillColor: "#eaeded",
                    fillOpacity: 0.3
                });
                layerGroupRef.current.addLayer(newPolygonEstado);

                const newPolygonMunicipio = new L.Polygon(coordenadasPoligono.coomunicipio, {
                    color: "#7b7d7d",
                    weight: 2,
                    opacity: 1,
                    fillColor: "#858de9  ",
                    fillOpacity: 0.3
                });
                layerGroupRef.current.addLayer(newPolygonMunicipio);
                const newMarker = new L.Marker(coordenadas, { icon: icon }).bindPopup("Ubicacion : <br>" + coordenadas + "<br><b> Estado :</b><br>" + coordenadasPoligono.estado + "<br> <b>Municipio :</b><br>" + coordenadasPoligono.municipio);
                layerGroupRef.current.addLayer(newMarker);
            }
        }
    }, [layerGroupRef, coordenadas]);

    useEffect(() => {
        if (coordenadas.length>1 && bandera!= null ) {
            mapRef.current.setView(coordenadas, 13);
            setbandera(null);      
        }
    }, [mapRef,coordenadas,bandera]);

    return (
        <>
            <div style={{
                position: 'absolute',
                top: '55px',
                left: '60px',
                zIndex: 1000,

            }}>
                <input
                    type="text"
                    value={coordenadasBuscar}
                    onChange={(x) => setCoordenadasBuscar(x.target.value)}
                    placeholder="00.00000000 , 00.00000000"

                />
                <button onClick={handleUbicar}>Ubicar</button>
            </div>
        </>
    );
}


Codigo de ubicarCoordenadasdms

mport React, { useState, useEffect } from 'react';
import icon from "./icon";
import L from 'leaflet';
import mun from "./municipios_js/municipios_sep"
import { point, polygon, booleanPointInPolygon } from '@turf/turf';

const createPolygons = (coordinatesArray) => {
    return coordinatesArray.map(coords => polygon([coords]));
};

const BuscarPoligono = ({ coordenadas }) => {
    const pointObj = point([coordenadas[0], coordenadas[1]]);
    let polygonObj;
    let isPointInsidePolygon
    let polygonObjmun
    let isPointInsidePolygonmun
    let objcoordenadas = null;

    mun?.forEach((estado) => {
        polygonObj = polygon(estado.COORDINATES);
        isPointInsidePolygon = booleanPointInPolygon(pointObj, polygonObj);
        if (isPointInsidePolygon) {
            estado.MUNICIPYES?.forEach(element => {
                polygonObjmun = createPolygons(element.coordinates);
                polygonObjmun.forEach((polygon) => {
                    isPointInsidePolygonmun = booleanPointInPolygon(pointObj, polygon);
                    if (isPointInsidePolygonmun) {
                        objcoordenadas = { estado: estado.NOM, cooestado: estado.COORDINATES, municipio: element.properties.NOM_MUN, coomunicipio: element.coordinates };
                    }
                });
            })
        }
    });
    console.log("salida de la busqueda",objcoordenadas)
    return objcoordenadas;
}

export const UbicarCoordenadadms = ({ layerGroupRef, mapRef }) => {
    const [coordenadas, setCoordenadas] = useState([]);
    const [bandera, setbandera]=useState(null);
    const [dms, setDms] = useState({ degrees: '', minutes: '', seconds: '' });
    const [dmsw, setDmsw] = useState({ degreesw: '', minutesw: '', secondsw: '' });
    const [decimal, setDecimal] = useState(0);
    const [decimalw, setDecimalw] = useState(0);



    const handleDmsChange = (e) => {
        setDms({
            ...dms,
            [e.target.name]: parseFloat(e.target.value)
        });
    };

    const handleDmsChangew = (x) => {
        setDmsw({
            ...dmsw,
            [x.target.name]: parseFloat(x.target.value)
        });
    };

    const dmsToDecimal = (degrees, minutes, seconds) => {
        const decimal = Math.abs(degrees) + (minutes / 60) + (seconds / 3600);
        return decimal;
    }

    const convertDmsToDecimal = () => {
        const { degrees, minutes, seconds } = dms;
        const { degreesw, minutesw, secondsw } = dmsw;
        setDecimal(dmsToDecimal(degrees, minutes, seconds));
        setDecimalw(dmsToDecimal(degreesw, minutesw, secondsw)*-1);
        setCoordenadas([decimal,decimalw]);
    };

   

    useEffect(() => {
        if (coordenadas.length > 0 && layerGroupRef.current) {
            const coordenadasPoligono = BuscarPoligono({ coordenadas });
            setbandera(coordenadasPoligono);
            if(coordenadasPoligono!==null){
                layerGroupRef.current.clearLayers();
                const newPolygonEstado = new L.Polygon(coordenadasPoligono.cooestado, {
                    color: "#424949",
                    weight: 1,
                    opacity: 1,
                    fillColor: "#eaeded",
                    fillOpacity: 0.3
                });
                layerGroupRef.current.addLayer(newPolygonEstado);

                const newPolygonMunicipio = new L.Polygon(coordenadasPoligono.coomunicipio, {
                    color: "#7b7d7d",
                    weight: 2,
                    opacity: 1,
                    fillColor: "#858de9  ",
                    fillOpacity: 0.3
                });
                layerGroupRef.current.addLayer(newPolygonMunicipio);
                const newMarker = new L.Marker(coordenadas, { icon: icon }).bindPopup("Ubicacion : <br>" + coordenadas + "<br><b> Estado :</b><br>" + coordenadasPoligono.estado + "<br> <b>Municipio :</b><br>" + coordenadasPoligono.municipio);
                layerGroupRef.current.addLayer(newMarker);
            }
        }
    }, [layerGroupRef, coordenadas]);

    useEffect(() => {
        if (coordenadas.length>1 && bandera!= null ) {
            mapRef.current.setView(coordenadas, 13);
            setbandera(null);      
        }
    }, [mapRef,coordenadas,bandera]);

    return (
        <>
 
            <div style={{
                position: 'absolute',
                top: '80px',
                left: '60px',
                zIndex: 1000,

            }}>
           
            <input
                type="number"
                name="degrees"
                value={dms.degrees}
                onChange={handleDmsChange}
                placeholder="Grados"
            />
            <input
                type="number"
                name="minutes"
                value={dms.minutes}
                onChange={handleDmsChange}
                placeholder="Minutos"
            />
            <input
                type="number"
                name="seconds"
                value={dms.seconds}
                onChange={handleDmsChange}
                placeholder="Segundos"
            />
            <label> N </label>

        </div>

        <div style={{
                position: 'absolute',
                top: '105px',
                left: '60px',
                zIndex: 1000,

            }}>
           
            <input
                type="number"
                name="degreesw"
                value={dmsw.degreesw}
                onChange={handleDmsChangew}
                placeholder="Grados"
            />
            <input
                type="number"
                name="minutesw"
                value={dmsw.minutesw}
                onChange={handleDmsChangew}
                placeholder="Minutos"
            />
            <input
                type="number"
                name="secondsw"
                value={dmsw.secondsw}
                onChange={handleDmsChangew}
                placeholder="Segundos"
            />
            <label> W </label>
            <button onClick={convertDmsToDecimal}>Ubicar DMS</button>
        </div>

       
        </>
    );
}


Codigo evento_mapa.js
import React, { useState } from 'react'
import { useMapEvent } from 'react-leaflet'

export const ZoomDisplay = () => {
    const [zoom, setZoom] = useState(null);
   
    useMapEvent('zoomend', (event) => {
        setZoom(event.target.getZoom());
    });

    return (
        <div className="custom-label">
            <div className="leaflet-top leaflet-right">
                {zoom !== null && `zoom: ${zoom}`}              
            </div>
        </div>
    );
  };

Codigo municipios_sep.js

import aguascalientes from "./aguascalientes_mun";
import bajaCalifornia from "./bajaCalifornia_mun";
import bajaCaliforniaSur from "./bajaCaliforniaSur_mun";
import campeche from "./campeche_mun";
import chiapas from "./chiapas_mun";
import chihuahua from "./chihuahua_mun";
import cdmx from "./cdmx_mun";
import coahuila from "./coahuila_mun";
import colima from "./colima_mun";
import durango from "./durango_mun";
import mexico from "./mexico_mun";
import guanajuato from "./guanajuato_mun";
import guerrero from "./guerrero_mun";
import hidalgo from "./hidalgo_mun";
import jalisco from "./jalisco_mun";
import michoacan from "./michoacan_mun";
import morelos from "./morelos_mun";
import nayarit from "./nayarit_mun";
import nuevoLeon from "./nuevoLeon_mun";
import oaxaca from "./oaxaca_prue";
import puebla from "./puebla_prue";
import queretaro from "./queretaro_mun";
import quintanaroo from "./quintanaroo_mun";
import sanLuisPotosi from "./sanLuisPotosi_mun";
import sinaloa from "./sinaloa_mun";
import sonora from "./sonora_mun";
import tabasco from "./tabasco_mun";
import tamaulipas from "./tamaulipas_mun";
import tlaxcala from "./tlaxcala_mun";
import veracruz from "./veracruz_prue";
import yucatan from "./yucatan_mun";
import zacatecas from "./zacatecas_mun";

const mun = [

    aguascalientes,
    bajaCalifornia,
    bajaCaliforniaSur,
    campeche,
    chiapas,
    chihuahua,
    cdmx,
    coahuila,
    colima,
    durango,
    mexico,
    guanajuato,
    guerrero,
    hidalgo,
    jalisco,
    michoacan,
    morelos,
    nayarit,
    nuevoLeon,
    oaxaca,
    puebla,
    queretaro,
    quintanaroo,
    sanLuisPotosi,
    sinaloa,
    sonora,
    tabasco,
    tamaulipas,
    tlaxcala,
    veracruz,
    yucatan,
    zacatecas,

]
export default mun;


Por el espacio del blog no se puede cargar los datos del los archivos de los estados ... la estructura del archivo de los estados seria esta :

export const aguascalientes = {
  "CVE_ENT": "01",
  "NOM": "Aguascalientes",
  "CLAVES": "01000",
  "DATA_ENT": [],
  "COORDINATES": [[
    [   21.79620484 ,   -102.0645076    ],
    [   21.79620484 ,   -102.0645076    ],
  ]],
  "MUNICIPYES": [
   
    {"properties": { "CVE_ENT": "01", "CVE_MUN": "005", "NOM_MUN": "Jesus Maria", "Claves": "01005" },
     "data":"1",
     "coordinates": [[
        [   22.05066522 ,   -102.3356776    ], 
        [   22.05171803 ,   -102.3357788    ],
        [   22.05066522 ,   -102.3356776    ]

     ]]
    }
    ]
}

export default aguascalientes;


Vista del mapa