Ala Eddine Menai
Ala Eddine Menai

Reputation: 2880

How to apply mask (transparent area) in mapboxGL?

I have a Map where I draw polygons for the coordinates that define the roofs:

enter image description here

However, I struggle to disable specific areas on the roofs by making them transparent ( the gray area ) where these should not colored.

Example:

enter image description here

I tried to use the Turf Mask but it does not have supported types in TypeScript.

Code:


"use client";

import mapboxGL from "mapbox-gl";
import { useEffect } from "react";

import * as turf from "@turf/turf";

mapboxGL.accessToken =
  "pk.eyJ1IjoibWVuYWktYWxhLWVkZGluZSIsImEiOiJjbHVicnFzc2swZWVvMm1wOTMxeDIzODEwIn0.Eyhkr7IB2xn7t7qu81lZdQ";

const roofs = [
  {
    id: 1,
    coords: [
      [
        [13.39064959480109, 52.502411506536646],
        [13.390677477503317, 52.502266943310815],
        [13.391043798518297, 52.50229152494538],
        [13.391029771613262, 52.502425707597695],
        [13.390945162035308, 52.502404052414676],
        [13.39064959480109, 52.502411506536646],
      ],
    ],

    panelsCoords: [
      [
        [13.391003158801936, 52.5023203928001],
        [13.391003158801936, 52.50230342787046],
        [13.391031554050215, 52.50230342787046],
        [13.391031554050215, 52.5023203928001],
        [13.391003158801936, 52.5023203928001],
      ],
      [
        [13.390966384830506, 52.502318394483325],
        [13.390966384830506, 52.502301339310236],
        [13.390994831868682, 52.502301339310236],
        [13.390994831868682, 52.502318394483325],
        [13.390966384830506, 52.502318394483325],
      ],
      [
        [13.390919224917724, 52.5023165822366],
        [13.390919224917724, 52.502298657033435],
        [13.390949197666572, 52.502298657033435],
        [13.390949197666572, 52.5023165822366],
        [13.390919224917724, 52.5023165822366],
      ],
    ],
    floorplanCoords: [
      [
        [13.390796619117907, 52.50227312401066],
        [13.390811606839435, 52.50216060100934],
        [13.390931508610208, 52.50216820392353],
        [13.390912773958291, 52.502280726905866],
        [13.390796619117907, 52.50227312401066], // Closed loop
      ],
    ],
  },
  {
    id: 2,
    coords: [
      [
        [13.391047919266668, 52.502284415735176],
        [13.390678637916295, 52.502259059516746],
        [13.390709077593073, 52.502108872386145],
        [13.391069547458784, 52.50213276582787],
        [13.391047919266668, 52.502284415735176],
      ],
    ],
    panelsCoords: [
      [
        [13.390988642150461, 52.50227125005367],
        [13.390988642150461, 52.50225320812541],
        [13.39102709226978, 52.50225320812541],
        [13.39102709226978, 52.50227125005367],
        [13.390988642150461, 52.50227125005367],
      ],
    ],
  },
];

const BuildingMap = () => {
  useEffect(() => {
    const map = new mapboxGL.Map({
      container: "map-container",
      style: "mapbox://styles/mapbox/satellite-v9",
      zoom: 20,
      center: [13.390853194154147, 52.50235398440585], // Adjust as needed
      antialias: true,
    });

    map.on("load", function () {
      roofs.forEach((roof) => {
        // Process the main roof polygon (if needed)
        // For each roof, add its main polygon
        
        if (roof.coords) {
          const polygon = turf.polygon(roof.coords, { name: "roof" });

          map.addSource(`roof-${roof.id}`, {
            type: "geojson",
            data: polygon,
          });

          map.addLayer({
            id: `roof-${roof.id}`,
            type: "fill",
            source: `roof-${roof.id}`,
            paint: {
              "fill-color": "green", // Example roof color
              "fill-opacity": 0.6,
            },
          });

          map.addSource(`floorplan-${roof.id}`, {
            type: "geojson",
            data: {
              type: "FeatureCollection",
              features: [
                {
                  type: "Feature",
                  properties: {},
                  geometry: {
                    coordinates: [
                      [
                        [13.390796619117907, 52.50227312401066],
                        [13.390811606839435, 52.50216060100934],
                        [13.390931508610208, 52.50216820392353],
                        [13.390912773958291, 52.502280726905866],
                        [13.390796619117907, 52.50227312401066],
                      ],
                    ],
                    type: "Polygon",
                  },
                },
              ],
            },
          });

          map.addLayer({
            id: `floorplan-${roof.id}`,
            type: "fill",
            source: `floorplan-${roof.id}`,
            paint: {
              "fill-color": "gray", // Example panel color, adjust as needed
              "fill-opacity": 0.8,
            },
          });
        }

        // Process panels if they exist
        if (roof.panelsCoords) {
          const panelFeatures: GeoJSON.Feature<GeoJSON.Geometry>[] =
            roof.panelsCoords.map((panelCoords, index) => {
              // Create a Turf.js polygon for the current panel
              const panelPolygon = turf.polygon([panelCoords]);

              // Calculate the area of the panel using Turf.js
              const area = turf.area(panelPolygon);

              // Return a feature with the area included in properties
              return {
                type: "Feature",
                properties: {
                  panelId: index,
                  area: area, // Add the calculated area to the feature properties
                },
                geometry: {
                  type: "Polygon",
                  coordinates: [panelCoords],
                },
              };
            });

          if (panelFeatures) {
            map.addSource(`panels-${roof.id}`, {
              type: "geojson",
              data: {
                type: "FeatureCollection",
                features: panelFeatures,
              },
            });
            map.addLayer({
              id: `panels-${roof.id}`,
              type: "fill",
              source: `panels-${roof.id}`,
              paint: {
                "fill-color": "red", // Example panel color, adjust as needed
                "fill-opacity": 0.8,
              },
            });
          }
        }
      });
    });

    return () => {
      map.remove();
    };

    // map.on("click", "polygon", function (e) {
    //   const polygon = map.getPaintProperty("polygon", "fill-color");

    //   // e.target.setPadding({left:4,top:4})

    //   if (polygon === "green") {
    //     map.setPaintProperty("polygon", "fill-color", "transparent");
    //     map.setPaintProperty("polygon", "fill-outline-color", "green");

    //     // Change the fill color to red
    //     // Change the fill color to red
    //     return;
    //   } else {
    //     map.setPaintProperty("polygon", "fill-color", "green"); // Change the fill color to red
    //   }
    //   // You can add your custom logic here for when the polygon is clicked
    //   // For example, display an alert or a custom popup
    // });

    // // Change the cursor to a pointer when the mouse is over the polygon
    // map.on("mouseenter", "polygon", function () {
    //   map.getCanvas().style.cursor = "pointer";
    // });

    // // Change it back to the default when it leaves.
    // map.on("mouseleave", "polygon", function () {
    //   map.getCanvas().style.cursor = "";
    // });
  }, []);

  return (
    <div id="map-container" style={{ width: "100vw", height: "100vh" }}></div>
  );
};

export default BuildingMap;

My question is how to apply the example of Mask by Turf using MapboxGL?

Upvotes: 0

Views: 88

Answers (0)

Related Questions