perliedman / leaflet-routing-machine

Control for routing in Leaflet
https://www.liedman.net/leaflet-routing-machine/
Other
1.06k stars 347 forks source link

How to Add Layer in React Leaflet & Routing Machine and Filter by Vehicle Code #667

Closed Ynsinan closed 1 year ago

Ynsinan commented 1 year ago

Same Question in Stackoverflow https://stackoverflow.com/questions/73404013/how-to-add-layer-in-react-leaflet-routing-machine-and-filter-by-vehicle-code

You can see the component I created in the picture. Here are the different vehicles and their latitude and longitude values. I am routing according to these values. What I want to add at this stage is that there is a layer button on the top right of the map and I want my vehicle codes in the popup that opens when I click on this layer button. Vehicle24, Vehicle30... When I click on vehicle24 from the popup that opens, I want only vehicle24's routes to appear. Is this possible, I can't make any progress. Thanks in advance for your help. I will add the codes I used below

TrackingMap.tsx

import { useState } from 'react';
//Third Party imports
import 'leaflet/dist/leaflet.css';
import { MapContainer, TileLayer } from 'react-leaflet';
import L from 'leaflet';

//Components imports
import Routing from './Routing';

//Utils import
import { MapWithPopupdatav2 } from './fakeData2';
import { CoordinatInterface, EachPointforRouting } from 'types/Map';

interface DefaultMapWithPopupProps {
  // dataSource: RootMapWithPopupData;
  height?: string;
  width?: string;
}

const TrackingMap = ({ height }: DefaultMapWithPopupProps) => {
  const [markersDataSource, setMarkersDataSource] = useState(
    MapWithPopupdatav2.data.map(item => item.gridData.data.map(item => item))
  );

  const [routeWayColor, setRouteWayColor] = useState<string[]>(
    MapWithPopupdatav2.data.map(item => item.color)
  );

  const [dataForRouting, setDataForRouting] = useState<EachPointforRouting[][]>(
    MapWithPopupdatav2.data.map(eachPoint =>
      eachPoint.gridData.data.map(point =>
        L.latLng(point.latitude, point.longitude)
      )
    )
  );

  const markersLatLon: CoordinatInterface[][] = MapWithPopupdatav2.data.map(
    eachPoint =>
      eachPoint.gridData.data.map(point => ({
        latitude: point.latitude,
        longitude: point.longitude,
      }))
  );
  function centerMapDataCalculate(data: CoordinatInterface[][]) {
    let newArray: CoordinatInterface[] = [];
    data.forEach(item => {
      item.map(point => {
        newArray.push(point);
      });
    });
    return newArray;
  }

  const markersCoordinatesForMapCentering: CoordinatInterface[] =
    centerMapDataCalculate(markersLatLon);
  return (
    <MapContainer scrollWheelZoom={true} style={{ height: `${height}` }}>
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      {dataForRouting.map((eachPoint, index) => {
        return (
          <Routing
            key={index}
            eachPoint={eachPoint}
            dataSource={markersDataSource[index]}
            color={routeWayColor[index]}
            bounds={markersCoordinatesForMapCentering}
          />
        );
      })}
    </MapContainer>
  );
};

export default TrackingMap;

Routing.tsx

import { useEffect } from 'react';
//Third Party İmports
import L, { latLngBounds } from 'leaflet';
import 'leaflet-routing-machine/dist/leaflet-routing-machine.css';
import 'leaflet-routing-machine';
import { useMap } from 'react-leaflet';
//Components

//Utils import
import { RoutingPropsforTrackingMap } from 'types/Map';
import { MarkerSVG } from 'utils/markerSVG';
import { closePopUpIconOptions } from 'utils/closePopUpIconOptions';
import { layerGroup } from 'leaflet';

L.Marker.prototype.options.icon = L.icon({
  iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png',
});

const Routing = ({
  eachPoint,
  dataSource,
  color,
  bounds,
}: RoutingPropsforTrackingMap) => {
  const map = useMap();
  let markerBounds = latLngBounds([]);
  const svgIcon = (visitOrder: number, color: string) =>
    L.divIcon({
      html: MarkerSVG(visitOrder, color),
      className: 'markerIcon',
      iconSize: [50, 50],
      iconAnchor: [32, 70],
      popupAnchor: [0, -70],
    });
  useEffect(() => {
    if (!map) return;
    console.log(eachPoint);

    const routingControl = L.Routing.control({
      waypoints: eachPoint,
      createMarker: function (
        waypointIndex: any,
        waypoint: any,
        numberOfWaypoints: any
      ) {
        return L.marker(waypoint.latLng, {
          icon: svgIcon(dataSource[waypointIndex].visitOrder, color),
        })
          .bindPopup(
            `<p><b>Location Code:</b>${dataSource[waypointIndex].locationCode}</p>
          <p><b>Location Type:</b>${dataSource[waypointIndex].locationType}</p>
          <p><b>Visit Order:</b>${dataSource[waypointIndex].visitOrder}</p>
          <p><b>Vehicle Code:</b>${dataSource[waypointIndex].vehicleCode}</p>
          `
          )
          .on('click', function (e: any) {
            closePopUpIconOptions();
          });
      },
      lineOptions: {
        styles: [
          {
            color: color,
            opacity: 1,
            weight: 7,
          },
        ],
      },

      addWaypoints: false,
      draggableWaypoints: false,
      fitSelectedRoutes: false,
      showAlternatives: true,
    }).addTo(map);
    if (bounds.length && bounds.length > 0) {
      bounds.forEach(marker => {
        markerBounds.extend([marker.latitude, marker.longitude]);
      });
      map.fitBounds(markerBounds);
    }

    return () => map.removeControl(routingControl);
  }, [map]);

  return null;
};
export default Routing;

FakeData.ts

export const MapWithPopupdatav2 = {
  data: [
    {
      id: 1,
      vehicleCode: 'Vehicle39',
      vehicleId: 39,
      color: '#0ac282',
      gridData: {
        currentPage: 1,
        firstRowOnPage: 1,
        kind: 0,
        lastRowOnPage: 15,
        pageCount: 1,
        pageSize: 10000,
        totalRowCount: 15,
        data: [
          {
            distanceMatrixId: 245046421,
            duration: 618000,
            endDate: '2019-09-24T11:44:39',
            latitude: 41.021569,
            locationCode: 'S1R1037',
            locationName: '',
            locationType: 'RCM',
            longitude: 29.040992,
            planDayId: 183,
            planResultId: 116894,
            serviceType: 'RCM Replenish',
            startDate: '2019-09-24T11:34:21',
            status: 'To Do',
            vehicleCode: 'Vehicle39',
            vehicleId: 39,
            visitOrder: 1,
          },
          {
            distanceMatrixId: 189364956,
            duration: 1074000,
            endDate: '2019-09-24T12:05:35',
            latitude: 41.018218,
            locationCode: 'S1A2275',
            locationName: '',
            locationType: 'RCM',
            longitude: 29.044254,
            planDayId: 183,
            planResultId: 116906,
            serviceType: 'Fix',
            startDate: '2019-09-24T11:47:41',
            status: 'To Do',
            vehicleCode: 'Vehicle39',
            vehicleId: 39,
            visitOrder: 2,
          },
          {
            distanceMatrixId: 189452735,
            duration: 618000,
            endDate: '2019-09-24T12:47:52',
            latitude: 41.0075,
            locationCode: 'S1R2054',
            locationName: '',
            locationType: 'RCM',
            longitude: 29.035592,
            planDayId: 183,
            planResultId: 116891,
            serviceType: 'RCM Replenish',
            startDate: '2019-09-24T12:37:34',
            status: 'To Do',
            vehicleCode: 'Vehicle39',
            vehicleId: 39,
            visitOrder: 3,
          },
        ],
      },
    },
    {
      id: 2,
      vehicleCode: 'Vehicle24',
      vehicleId: 24,
      color: '#807ACD',
      gridData: {
        currentPage: 1,
        firstRowOnPage: 1,
        kind: 0,
        lastRowOnPage: 6,
        pageCount: 1,
        pageSize: 10000,
        totalRowCount: 6,
        data: [
          {
            distanceMatrixId: 245857071,
            duration: 696000,
            endDate: '2019-09-24T12:13:45',
            latitude: 40.999569,
            locationCode: '0405',
            locationName: 'Branch48',
            locationType: 'Branch',
            longitude: 29.095666,
            planDayId: 183,
            planResultId: 117530,
            serviceType: 'Cash pickup & Delivery',
            startDate: '2019-09-24T12:02:09',
            status: 'To Do',
            vehicleCode: 'Vehicle24',
            vehicleId: 24,
            visitOrder: 1,
          },
          {
            distanceMatrixId: 276074744,
            duration: 696000,
            endDate: '2019-09-24T14:11:36',
            latitude: 40.992341,
            locationCode: '0022',
            locationName: 'Branch10',
            locationType: 'Branch',
            longitude: 29.101693,
            planDayId: 183,
            planResultId: 117529,
            serviceType: 'Cash pickup & Delivery',
            startDate: '2019-09-24T14:00:00',
            status: 'To Do',
            vehicleCode: 'Vehicle24',
            vehicleId: 24,
            visitOrder: 2,
          },
          {
            distanceMatrixId: 242141750,
            duration: 696000,
            endDate: '2019-09-24T16:11:36',
            latitude: 40.98491,
            locationCode: '0610',
            locationName: 'Branch70',
            locationType: 'Branch',
            longitude: 29.092627,
            planDayId: 183,
            planResultId: 117528,
            serviceType: 'Cash pickup & Delivery',
            startDate: '2019-09-24T16:00:00',
            status: 'To Do',
            vehicleCode: 'Vehicle24',
            vehicleId: 24,
            visitOrder: 3,
          },
        ],
      },
    },
    {
      id: 3,
      vehicleCode: 'Vehicle36',
      vehicleId: 24,
      color: '#F38876',
      gridData: {
        currentPage: 1,
        firstRowOnPage: 1,
        kind: 0,
        lastRowOnPage: 28,
        pageCount: 1,
        pageSize: 10000,
        totalRowCount: 28,
        data: [
          {
            distanceMatrixId: 245046567,
            duration: 1074000,
            endDate: '2019-09-24T11:38:01',
            latitude: 40.980517,
            locationCode: 'S1A4960',
            locationName: '',
            locationType: 'ATM',
            longitude: 29.075156,
            planDayId: 183,
            planResultId: 117282,
            serviceType: 'Fix',
            startDate: '2019-09-24T11:20:07',
            status: 'To Do',
            vehicleCode: 'Vehicle36',
            vehicleId: 36,
            visitOrder: 1,
          },
          {
            distanceMatrixId: 189328693,
            duration: 444000,
            endDate: '2019-09-24T11:49:35',
            latitude: 40.979788,
            locationCode: 'S1A7396',
            locationName: '',
            locationType: 'ATM',
            longitude: 29.067378,
            planDayId: 183,
            planResultId: 117281,
            serviceType: 'ATM Replenish',
            startDate: '2019-09-24T11:42:11',
            status: 'To Do',
            vehicleCode: 'Vehicle36',
            vehicleId: 36,
            visitOrder: 2,
          },
          {
            distanceMatrixId: 191205228,
            duration: 1074000,
            endDate: '2019-09-24T12:14:55',
            latitude: 40.974639,
            locationCode: 'S1A9243',
            locationName: '',
            locationType: 'RCM',
            longitude: 29.05792,
            planDayId: 183,
            planResultId: 117280,
            serviceType: 'Fix',
            startDate: '2019-09-24T11:57:01',
            status: 'To Do',
            vehicleCode: 'Vehicle36',
            vehicleId: 36,
            visitOrder: 3,
          },
        ],
      },
    },
    {
      id: 4,
      vehicleCode: 'Vehicle30',
      vehicleId: 30,
      color: '#008EA9',
      gridData: {
        currentPage: 1,
        firstRowOnPage: 1,
        kind: 0,
        lastRowOnPage: 23,
        pageCount: 1,
        pageSize: 10000,
        totalRowCount: 23,
        data: [
          {
            distanceMatrixId: 271855562,
            duration: 618000,
            endDate: '2019-09-24T12:46:37',
            latitude: 41.025808,
            locationCode: 'S1R2206',
            locationName: '',
            locationType: 'RCM',
            longitude: 29.015655,
            planDayId: 183,
            planResultId: 117165,
            serviceType: 'RCM Replenish',
            startDate: '2019-09-24T12:36:19',
            status: 'To Do',
            vehicleCode: 'Vehicle30',
            vehicleId: 30,
            visitOrder: 1,
          },
          {
            distanceMatrixId: 245814193,
            duration: 1074000,
            endDate: '2019-09-24T11:18:01',
            latitude: 41.022554,
            locationCode: 'S1C2293',
            locationName: '',
            locationType: 'ATM',
            longitude: 29.015923,
            planDayId: 183,
            planResultId: 117170,
            serviceType: 'Fix',
            startDate: '2019-09-24T11:00:07',
            status: 'To Do',
            vehicleCode: 'Vehicle30',
            vehicleId: 30,
            visitOrder: 2,
          },
          {
            distanceMatrixId: 273658538,
            duration: 444000,
            endDate: '2019-09-24T11:32:59',
            latitude: 41.018628,
            locationCode: 'S1C1902',
            locationName: '',
            locationType: 'ATM',
            longitude: 29.011041,
            planDayId: 183,
            planResultId: 117169,
            serviceType: 'ATM Replenish',
            startDate: '2019-09-24T11:25:35',
            status: 'To Do',
            vehicleCode: 'Vehicle30',
            vehicleId: 30,
            visitOrder: 3,
          },
          {
            distanceMatrixId: 272746632,
            duration: 618000,
            endDate: '2019-09-24T11:47:01',
            latitude: 41.01522,
            locationCode: 'S1R2650',
            locationName: '',
            locationType: 'RCM',
            longitude: 29.011577,
            planDayId: 183,
            planResultId: 117168,
            serviceType: 'RCM Replenish',
            startDate: '2019-09-24T11:36:43',
            status: 'To Do',
            vehicleCode: 'Vehicle30',
            vehicleId: 30,
            visitOrder: 4,
          },
        ],
      },
    },
  ],
};

// export interface Datum2 {
//   distanceMatrixId: number;
//   duration: number;
//   endDate: Date;
//   latitude: number;
//   locationCode: string;
//   locationName: string;
//   locationType: string;
//   longitude: number;
//   planDayId: number;
//   planResultId: number;
//   serviceType: string;
//   startDate: string;
//   status: string;
//   vehicleCode: string;
//   vehicleId: number;
//   visitOrder: number;
// }

// export interface GridData {
//   currentPage: number;
//   firstRowOnPage: number;
//   kind: number;
//   lastRowOnPage: number;
//   pageCount: number;
//   pageSize: number;
//   totalRowCount: number;
//   data: Datum2[];
// }

// export interface Datum {
//   id: number;
//   vehicleCode: string;
//   vehicleId: number;
//   color: string;
//   gridData: GridData;
// }

// export interface RootObject {
//   data: Datum[];
// }
curtisy1 commented 1 year ago

See my answer on StackOverflow. Basically you'll want a custom control that handles map interaction with react-leaflet and updates the route accordingly, like in this fiddle