简体   繁体   中英

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[];
// }

react-leaflet supports adding custom controls . Using such custom control, you can add a basic list that handles selecting a vehicle, saving its index in state and changing the route accordingly.

Here's a working fiddle that places a very basic custom control in the bottom-left corner. This is because once the routing control is appended to the DOM, your top-right corner would be occupied.

Apart from the custom control and useState() hook, you'll also want to modify the useEffect hook in the Routing.tsx to be exhaustive. As for why this is, I recommend giving Dan Abramov's deep-dive a read. Basically, with just the map in your deps, your component will never update, even if the underlying coordinates change. For clarity, I left the markerBounds out of the dependency list in the sample. You should see yellow squiggly lines saying the list is missing that (so in your code, you would add it in there)

Also as a side note, although I'm sure this is just for testing purposes, I would advise against re-instantiating the whole routing machine in the useEffect hook and rather update the coordinates there and then reroute. This would remove the need to call addTo() and removeControl() on every render

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