Search code examples
leafletreact-leaflet

React Leaflet - Draw pluscode areas as a grid


I am trying to figure out a way to draw Pluscodes (OLC) on React Leaflet. I can get it to draw normal grids by extending GridLayer class just fine, but couldn't draw pluscodes accordingly. I am yet to figure out how it works completely.

How can I achieve this? Is GridLayer suitable for this task or should I be looking for something else? Also pluscodes should show higher levels as I zoom in.

https://codesandbox.io/s/pluscode-grid-problem-40fho?file=/src/App.jsx

// Grid.jsx
import { useEffect } from "react";
import L from "leaflet";
import { useLeafletContext } from "@react-leaflet/core";

const PlusCodeGrid = () => {
  const { layerContainer, map } = useLeafletContext();

  const createLeafletElement = () => {
    const Grid = L.GridLayer.extend({
      createTile: function (coords) {
        const tile = L.DomUtil.create("canvas", "leaflet-tile");

        tile.style.outline = "1px solid black";

        return tile;
      }
    });
    return new Grid({ tileSize: 100 });
  };

  useEffect(() => {
    layerContainer.addLayer(createLeafletElement());
  }, []);

  return null;
};

export default PlusCodeGrid;

// App.jsx
import React, { useState } from "react";
import { MapContainer, TileLayer, LayersControl } from "react-leaflet";
import PlusCodeGrid from "./Grid";
import { OpenLocationCode } from "open-location-code";

const getBoundariesFromPluscode = (plusCode) => {
  const geocoder = new OpenLocationCode();
  const { latitudeHi, latitudeLo, longitudeHi, longitudeLo } = geocoder.decode(
    plusCode
  );

  const boundary = [
    [latitudeLo, longitudeLo],
    [latitudeHi, longitudeHi]
  ];

  return boundary;
};

const App = () => {
  const [map, setMap] = useState(null);

  const plusCodeExample = "8FHJJMX2+R8";
  const plusCodeBoundaries = getBoundariesFromPluscode(plusCodeExample);

  console.log(plusCodeBoundaries);

  return (
    <div className="leaflet-container">
      <MapContainer
        className="map-container"
        whenCreated={setMap}
        zoom={15}
        scrollWheelZoom={true}
      >
        <LayersControl>
          <TileLayer url="http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
          <LayersControl.Overlay checked name="Pluscode Grid">
            <PlusCodeGrid />
          </LayersControl.Overlay>
        </LayersControl>
      </MapContainer>
    </div>
  );
};

export default App;


Solution

  • Unbeliveable, the answer was right there in the page I sourced in the question... Once again I choose to skim through documentations quickly to save few minutes only to lose days in the process.

    Anyways, grid.plus.codes provides a grid service for plus codes which can easily be used with React leaflet like so:

    import { useEffect } from 'react';
    import L from 'leaflet';
    import { useLeafletContext } from '@react-leaflet/core';
    
    const PlusCodeGrid = () => {
      const { layerContainer, map } = useLeafletContext();
    
      useEffect(() => {
        layerContainer.addLayer(
          L.tileLayer('https://{s}-grid.plus.codes/grid/tms/{z}/{x}/{y}.png', {
            tms: true,
            attribution: 'grid by plus codes',
          }).addTo(map)
        );
      }, []);
    
      return null;
    };
    
    export default PlusCodeGrid;