react-leaflet#Polygon TypeScript Examples

The following examples show how to use react-leaflet#Polygon. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
SiteMap = ({
  siteId,
  spotterPosition,
  polygon,
  surveyPoints,
  selectedPointId,
  surveyPointEditModeEnabled,
  editPointLatitude,
  editPointLongitude,
  onEditPointCoordinatesChange,
  classes,
}: SiteMapProps) => {
  const dispatch = useDispatch();
  const mapRef = useRef<Map>(null);
  const markerRef = useRef<Marker>(null);
  const editPointMarkerRer = useRef<Marker>(null);
  const draftSite = useSelector(siteDraftSelector);
  const user = useSelector(userInfoSelector);
  const [focusedPoint, setFocusedPoint] = useState<SurveyPoints>();

  const reverseCoords = (coordArray: Position[]): [Position[]] => {
    return [coordArray.map((coords) => [coords[1], coords[0]])];
  };

  const selectedSurveyPoint = surveyPoints.find(
    (item) => item.id === selectedPointId
  );

  const setCenter = (
    inputMap: L.Map,
    latLng: [number, number],
    zoom: number
  ) => {
    const maxZoom = Math.max(inputMap.getZoom() || 15, zoom);
    const pointBounds = L.latLngBounds(latLng, latLng);
    inputMap.flyToBounds(pointBounds, {
      maxZoom,
      duration: 2,
      paddingTopLeft: L.point(0, 200),
    });
  };

  // Fit the polygon constructed by the site's center and its survey points
  const fitSurveyPointsPolygon = useCallback(
    (inputMap: L.Map, siteCenter: Point) => {
      inputMap.fitBounds(
        L.polygon([
          [siteCenter.coordinates[1], siteCenter.coordinates[0]],
          ...surveyPoints
            .filter((item) => item.polygon?.type === "Point")
            .map((item) => {
              const coords = item.polygon?.coordinates as Position;
              // Reverse coordinates since they come as [lng, lat]
              return [coords[1], coords[0]] as LatLngTuple;
            }),
        ]).getBounds()
      );
    },
    [surveyPoints]
  );

  useEffect(() => {
    if (
      mapRef?.current?.leafletElement &&
      focusedPoint?.polygon?.type === "Point"
    ) {
      const [lng, lat] = focusedPoint.polygon.coordinates;
      setCenter(mapRef.current.leafletElement, [lat, lng], 15);
    }
  }, [focusedPoint]);

  useEffect(() => {
    const { current } = mapRef;
    if (current?.leafletElement) {
      const map = current.leafletElement;
      // Initialize map's position to fit the given polygon
      if (polygon.type === "Polygon") {
        map.fitBounds(L.polygon(polygon.coordinates).getBounds());
      } else if (draftSite?.coordinates) {
        map.panTo(
          new L.LatLng(
            draftSite.coordinates.latitude || polygon.coordinates[1],
            draftSite.coordinates.longitude || polygon.coordinates[0]
          )
        );
      } else if (some(surveyPoints, (item) => item.polygon?.type === "Point")) {
        fitSurveyPointsPolygon(map, polygon);
      } else {
        map.panTo(new L.LatLng(polygon.coordinates[1], polygon.coordinates[0]));
      }
    }
  }, [draftSite, fitSurveyPointsPolygon, polygon, surveyPoints]);

  const handleDragChange = () => {
    const { current } = markerRef;
    if (current?.leafletElement) {
      const mapMarker = current.leafletElement;
      const { lat, lng } = mapMarker.getLatLng().wrap();
      dispatch(
        setSiteDraft({
          coordinates: {
            latitude: lat,
            longitude: lng,
          },
        })
      );
    }
  };

  const handleEditPointDragChange = () => {
    const { current } = editPointMarkerRer;
    if (current && current.leafletElement && onEditPointCoordinatesChange) {
      const mapMarker = current.leafletElement;
      const { lat, lng } = mapMarker.getLatLng().wrap();
      onEditPointCoordinatesChange(lat.toString(), lng.toString());
    }
  };

  return (
    <Map
      ref={mapRef}
      minZoom={1}
      maxZoom={17}
      zoom={13}
      dragging
      scrollWheelZoom={false}
      className={classes.map}
      tap={false}
      maxBoundsViscosity={1.0}
      maxBounds={mapConstants.MAX_BOUNDS}
    >
      <TileLayer url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}" />
      {polygon.type === "Polygon" ? (
        <Polygon positions={reverseCoords(...polygon.coordinates)} />
      ) : (
        <>
          {/* Marker to listen to survey point drag changes on edit mode */}
          {surveyPointEditModeEnabled && (
            <Marker
              ref={editPointMarkerRer}
              draggable={surveyPointEditModeEnabled}
              ondragend={handleEditPointDragChange}
              icon={surveyPointIcon(true)}
              zIndexOffset={100}
              position={[
                editPointLatitude ||
                  (selectedSurveyPoint?.polygon?.type === "Point" &&
                    selectedSurveyPoint.polygon.coordinates[1]) ||
                  polygon.coordinates[1],
                editPointLongitude ||
                  (selectedSurveyPoint?.polygon?.type === "Point" &&
                    selectedSurveyPoint.polygon.coordinates[0]) ||
                  polygon.coordinates[0],
              ]}
            />
          )}
          <Marker
            ref={markerRef}
            draggable={Boolean(draftSite)}
            ondragend={handleDragChange}
            icon={pinIcon}
            position={[
              draftSite?.coordinates?.latitude || polygon.coordinates[1],
              draftSite?.coordinates?.longitude || polygon.coordinates[0],
            ]}
          />
          {surveyPoints.map(
            (point) =>
              point?.polygon?.type === "Point" &&
              !samePosition(polygon, point.polygon) &&
              (point.id !== selectedPointId || !surveyPointEditModeEnabled) && ( // Hide selected survey point marker if it is in edit mode
                <Marker
                  key={point.id}
                  icon={surveyPointIcon(point.id === selectedPointId)}
                  position={[
                    point.polygon.coordinates[1],
                    point.polygon.coordinates[0],
                  ]}
                  onclick={() => setFocusedPoint(point)}
                >
                  <SurveyPointPopup siteId={siteId} point={point} />
                </Marker>
              )
          )}
        </>
      )}
      {!draftSite && spotterPosition && isManager(user) && (
        <Marker
          icon={buoyIcon}
          position={[
            spotterPosition.latitude.value,
            spotterPosition.longitude.value,
          ]}
        />
      )}
    </Map>
  );
}
Example #2
Source File: Map.tsx    From covid19map with MIT License 4 votes vote down vote up
Map = ({
  center,
  zoom,
  markers = [],
  clusters = {},
  onMarkerClick,
  maxCases,
  outerBounds,
  innerBounds,
  location
}: {
  center: any;
  zoom: number;
  markers: any[];
  clusters: any;
  onMarkerClick: any;
  maxCases: number;
  outerBounds: any;
  innerBounds: any;
  location: any;
}) => {
  const theme = useTheme();
  const mapRef = useRef<any>(null);
  const [currentLocation, setCurrentLocation] = useState<string>();
  const [currentZoom, setCurrentZoom] = useState(100);

  useEffect(() => {
    mapRef?.current?.leafletElement.fitBounds(innerBounds);
  }, [mapRef.current]);

  useEffect(() => {
    mapRef?.current?.leafletElement.closePopup();
    setCurrentLocation('');
  }, [location]);

  const getRegionIcon = (
    className: string,
    totalCases: number,
    name: string
  ) => {
    const iconSize = 24;
    return L.divIcon({
      className: `marker ${className}`,
      iconSize: [iconSize, iconSize],
      html: `<div>${
        name === 'Managed Isolation' ? 'MIQ: ' : ''
      }${totalCases}</div>`
    });
  };

  const getClusterIcon = (className: string, totalCases: number) => {
    const normalise = totalCases / 100;
    const iconSize = 24 + normalise * 15;
    return L.divIcon({
      className: `marker ${className}`,
      iconSize: [iconSize, iconSize],
      html: `<div></div>`
    });
  };

  const onLocationClick = (name: string) => {
    setCurrentLocation(name);
    onMarkerClick(name);
  };

  const onZoomend = () => {
    if (mapRef.current) {
      setCurrentZoom(mapRef.current?.leafletElement.getZoom());
    }
  };

  return (
    <div style={{ position: 'relative' }}>
      <LeafletMap
        // onClick={() => onLocationClick('')}
        ref={mapRef}
        maxBounds={outerBounds}
        center={center}
        zoom={zoom}
        maxZoom={7}
        minZoom={5}
        zoomControl={true}
        doubleClickZoom={true}
        scrollWheelZoom={true}
        dragging={true}
        animate={true}
        easeLinearity={0.35}
        onZoomend={onZoomend}
      >
        <TileLayer
          url="//{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png"
          attribution='&copy; <a href="//www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
        />
        {markers.map(
          (
            {
              name,
              latlng,
              boundary,
              totalCases,
              active,
              recovered,
              deaths,
              inHospital,
              level
            },
            i
          ) => (
            <>
              {latlng && (
                <FeatureGroup key={i}>
                  <Marker
                    position={latlng}
                    icon={getRegionIcon(
                      `region ${inHospital > 0 ? 'hospital' : ''}`,
                      active,
                      name
                    )}
                    zIndexOffset={100}
                    // onClick={() => {
                    //   onLocationClick(name);
                    //   gtag.event('Marker', 'Map', name);
                    // }}
                  />
                  <Popup>
                    <StyledPopup>
                      <div className="location">{name}</div>
                      <div className="cases">
                        {active} active case{active > 1 && 's'}
                        <br />
                        {recovered} recovered
                        <br />
                        {totalCases} total case{totalCases > 1 && 's'}
                        {deaths > 0 && (
                          <>
                            <br />
                            {deaths} death{deaths > 1 && 's'}
                          </>
                        )}
                      </div>
                      {inHospital > 0 && (
                        <div className="cases">{inHospital} in hospital</div>
                      )}
                    </StyledPopup>
                  </Popup>
                  {boundary && (
                    <Polygon
                      color={currentLocation === name ? 'white' : 'black'}
                      opacity={currentLocation === name ? 1 : 0.2}
                      weight={currentLocation === name ? 3 : 1}
                      fillColor={theme[alertColours[level - 1]]}
                      // fillOpacity={((active || 0) - -10) / (maxCases + 10 - 1)}
                      // fillOpacity={(level - 1) / (4 - 1)}
                      fillOpacity={0.8}
                      positions={boundary[0]}
                      // smoothFactor={10}
                      // onClick={() => {
                      //   onLocationClick(name);
                      //   gtag.event('Region', 'Map', name);
                      // }}
                    />
                  )}
                </FeatureGroup>
              )}
            </>
          )
        )}
        {Object.keys(clusters).map((regionName: string, j: number) =>
          Object.keys(clusters[regionName]).map(
            (clustLocName: string, k: number) => {
              const { latlng, count, items } = clusters[regionName][
                clustLocName
              ];

              return items.filter((x: any) => x.ongoing === 'Yes').length >
                0 ? (
                <Marker
                  key={k}
                  position={latlng}
                  icon={getClusterIcon('cluster', count)}
                  // onClick={() => gtag.event('Cluster', 'Map', clustLocName)}
                >
                  <Popup>
                    <StyledPopup>
                      <div className="head">
                        {clustLocName} cluster{items.length > 1 && 's'}
                      </div>
                      {items
                        .filter((x: any) => x.ongoing === 'Yes')
                        .map(
                          (
                            {
                              name,
                              totalCases
                            }: { name: string; totalCases: number },
                            l: number
                          ) => (
                            <div className="cluster-desc" key={l}>
                              <div className="location">{name}</div>
                              <div className="cases">{totalCases} cases</div>
                            </div>
                          )
                        )}
                    </StyledPopup>
                  </Popup>
                </Marker>
              ) : (
                <div key={k} />
              );
            }
          )
        )}
      </LeafletMap>
      <Styles currentZoom={currentZoom} />
    </div>
  );
}