Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to change the initial custom styling of a feature after we draw it? #1298

Open
alamenai opened this issue Oct 1, 2024 · 0 comments
Open

Comments

@alamenai
Copy link

alamenai commented Oct 1, 2024

Hi everyone,

In the image below I draw roofs on the the top of the building:

image

This how I draw the roof :

  const createRoofPolygonFeature = (roofSurface: RoofSurface): Feature => {
    const polygon = turf.polygon([roofSurface.coords])
    const roofCoordinates = polygon.geometry.coordinates

    if (roofSurface.holes) {
      roofSurface.holes.forEach((hole: Position[]) => {
        roofCoordinates.push(hole)
      })
    }

    const feature = {
      type: "Feature",
      properties: {
        id: roofSurface.id,
        user_color: "#16a34a", // Default color with 'user_' prefix
      },
      geometry: {
        type: "Polygon",
        coordinates: roofCoordinates,
      },
    }

    // Store the draw instance in the mapRef
    if (mapRef.current) {
      const current = mapRef.current as MapWithDraw
      current.draw.add(feature as Feature)

      // // Add a new layer for the holes
      // if (roofSurface.holes && roofSurface.holes.length > 0) {
      //   roofSurface.holes.forEach((hole, index) => {
      //     const holeFeature = {
      //       type: "Feature",
      //       properties: {},
      //       geometry: {
      //         type: "Polygon",
      //         coordinates: [hole],
      //       },
      //     }

      //     const holeId = `hole-${roofSurface.id}-${index}`

      //     current.addSource(holeId, {
      //       type: "geojson",
      //       data: holeFeature,
      //     })

      //     current.addLayer({
      //       id: holeId,
      //       type: "fill",
      //       source: holeId,
      //       paint: {
      //         "fill-color": "red",
      //         "fill-opacity": 0.3,
      //       },
      //     })
      //   })
      // }
    }

    return feature as Feature
  }

I created a map instance :

  const createDrawInstance = (modes: { [key: string]: DrawCustomMode }, styles: any): MapboxDraw => {
    return new MapboxDraw({
      displayControlsDefault: false,
      touchEnabled: true,
      modes,
      styles,
      boxSelect: true,
      userProperties: true,
    })
  }

I defined the styles using this function:

  const createDrawStyles = () => {
    return [
      // ACTIVE (being drawn)
      // line stroke
      {
        id: "gl-draw-line",
        type: "line",
        filter: ["all", ["==", "$type", "LineString"], ["!=", "mode", "static"]],
        layout: {
          "line-cap": "round",
          "line-join": "round",
        },
        paint: {
          "line-color": ["get", "color"],
          "line-width": 2,
        },
      },
      // polygon fill
      {
        id: "gl-draw-polygon-fill",
        type: "fill",
        filter: ["all", ["==", "$type", "Polygon"], ["!=", "mode", "static"]],
        paint: {
          "fill-color": "#84cc16",
          "fill-outline-color": "#84cc16",
          "fill-opacity": 0.1, // Semi-opaque fill
        },
      },

      // vertex point halos
      {
        id: "gl-draw-polygon-and-line-vertex-halo-active",
        type: "circle",
        filter: ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"], ["!=", "mode", "static"]],
        paint: {
          "circle-radius": 10,
          "circle-color": "#FFF", // White color for vertex halo
        },
      },
      // vertex points
      {
        id: "gl-draw-polygon-and-line-vertex-active",
        type: "circle",
        filter: ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"], ["!=", "mode", "static"]],
        paint: {
          "circle-radius": 8,
          "circle-color": "#84cc16", // Red color for vertex points
        },
      },
      // Inactive polygon fill
      {
        id: "gl-draw-polygon-fill-static",
        type: "fill",
        filter: ["all", ["==", "$type", "Polygon"], ["==", "mode", "static"]],
        paint: {
          "fill-color": "#3b82f6", // Blue color for inactive polygon fill
          "fill-outline-color": "#3b82f6", // Blue outline
          "fill-opacity": 0.1, // Semi-opaque fill
        },
      },
      // Inactive polygon outline stroke
      {
        id: "gl-draw-polygon-stroke-static",
        type: "line",
        filter: ["all", ["==", "$type", "Polygon"], ["==", "mode", "static"]],
        layout: {
          "line-cap": "round",
          "line-join": "round",
        },
        paint: {
          "line-color": "#16a34a", // inactive polygon outline
          "line-width": 3, // Line width
        },
      },
      // Inactive vertex points
      {
        id: "gl-draw-polygon-and-line-vertex-static",
        type: "circle",
        filter: ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"], ["==", "mode", "static"]],
        paint: {
          "circle-radius": 3,
          "circle-color": "#3BB2D0", // Blue color for inactive vertex points
        },
      },
      // polygon outline stroke
      // This doesn't style the first edge of the polygon, which uses the line stroke styling instead
      {
        id: "gl-draw-polygon-stroke-active",
        type: "line",
        filter: ["all", ["==", "$type", "Polygon"], ["!=", "mode", "static"]],
        paint: {
          "line-color": ["get", "color"],
          "line-width": 2,
        },
      },
    ]
  }

Everything works as expected but when I click on the roof ID ( circle ID), I want to change the color of that selected roof (feature) to red but Mapbox gl does not influence the change:

c0c91e36-12f5-43ea-8ed6-f3ce538f93c3.webm

This is the method I use:

 // Update roof line color
    if (mapRef.current) {
      const current = mapRef.current as MapWithDraw
      const feature = current.draw.get(roofSurface.id as string) as Feature
      if (feature) {
        feature.properties = {
          ...feature.properties,
          user_color: selectStatus ? "#16a34a" : "#ef4444", // Green when selected, red when deselected
        }
        current.draw.add(feature)
      }
    }

I did not understand how to use the property userProperties Is it possible to change the color of each feature?

I appreciate any example that you can provide.

Example: drawing to polygons in the first rendering and when I click on one of them, it will change its color.

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant