Draw on Mapbox map

Hi everybody

I would like to use Mapbox with the additional draw library to make it possible for a user to draw things like polygons on a map. The “drawing” should then return the coordinates of the points. Here is a screenshot of such a drawing (this was prototyped using Leaflet). If this is not possible with Mapbox and weweb. Should I create a custom component?

@Joyce or @Quentin do you think this is possible?

Sorry I can’t help with this, but I’m also curious to know whether this could be used for geofencing?
I.e. a client can set a perimeter on their site and trigger a workflow when users are inside/outside the perimeter?

Hi, you probably can try with this documentation => Draw a polygon and calculate its area | Mapbox GL JS | Mapbox

You will have to import the required script with a global workflow first =>

  if(!wwLib.getFrontWindow()["ww-mapbox-script"]) {
    wwLib.getFrontWindow()["ww-mapbox-script"] = true;
    const script1 = wwLib.getFrontDocument().createElement('script');
    script1.src = 'https://unpkg.com/@turf/turf@6/turf.min.js';
    wwLib.getFrontDocument().body.appendChild(script1);

    const script2 = wwLib.getFrontDocument().createElement('script');
    script2.src = 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.4.3/mapbox-gl-draw.js';
    wwLib.getFrontDocument().body.appendChild(script2);

    const script3 = wwLib.getFrontDocument().createElement('link');
    script3.href = 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.4.3/mapbox-gl-draw.js';
    script3.rel = "stylesheet"
    script3.type = "text/css"
    wwLib.getFrontDocument().body.appendChild(script3);
  }

As you have access to the mapbox instance you can you can call methods and do the required stuff I guess :thinking:

Another possibility is to get ride of the mapbox element and use the HTML element, copy/paste the code from the documentation inside and try to make it works, could be a way to have a first version before developing a custom code component, you could even wrap it inside a nocode component

2 Likes

thank you very much for the inputs! will try this out and will give an update here

Hi @jayjay13 - Did you ever get this to work? I am trying to do something similar.

Hey @willmccartney

I actually stayed with Leaflet. It’s way easier to implement and free… And with ChatGPT you can create the whole logic…
It just takes some custom code:

Import this in the head of the page:

<link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet">
<link href="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.css" rel="stylesheet">
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.js"></script>

Then add a div with the id=mapid (make sure to give it some width and height. Then add the following js right before the Body tag:

<script>
    var mymap = L.map('mapid', {
        maxBounds: [
            [45.817995, 5.955911], // Southwest coordinates
            [47.808455, 10.492340]  // Northeast coordinates
        ],
        maxBoundsViscosity: 1.0  // Prevents users from dragging outside the bounds
    }).setView([46.8182, 8.2275], 8); // Centered on Switzerland

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {}).addTo(mymap);

    var drawnItems = new L.FeatureGroup();
    mymap.addLayer(drawnItems);

    var drawControl = new L.Control.Draw({
        draw: {
            polygon: true,
            polyline: false,
            rectangle: false,
            circle: false,
            marker: false
        }
    });
    mymap.addControl(drawControl);

    // Function to handle the creation of a new polygon
    function handlePolygonCreation(layer) {
    // Clear existing polygons
    drawnItems.clearLayers();
    
    // Add new layer
    drawnItems.addLayer(layer);

    // Get the coordinates of the polygon and convert them to objects
    var coordinates = layer.getLatLngs()[0].map(function(latlng) {
        return { lat: latlng.lat, lng: latlng.lng };
    });

    // Update the variable using WeWeb.io's method
    wwLib.wwVariable.updateValue("e301ff65-a460-45af-96f8-b482b596e89e", coordinates);

    // Log the updated variable for debugging
    console.log('Polygon Coordinates Updated:', coordinates);
}


    // Listen for when a new shape is drawn
    mymap.on(L.Draw.Event.CREATED, function(event) {
        var layer = event.layer;
        if (layer instanceof L.Polygon) {
            handlePolygonCreation(layer);
        }
    });
</script>

As you see in the script, there is a variable that gets updated with the coordinates in there:
wwLib.wwVariable.updateValue("e301ff65-a460-45af-96f8-b482b596e89e", coordinates);

Make sure to change the variable UUID to the UUID of your variable (needs to be a variable of type array). With this, you have the values back in a weweb variable, and you can do other stuff with it in weweb… :slight_smile:

Only downside is, that you can only test everything when you have published the app… In the editor, custom JS doesn’t work. (little hint there, implement the JS part in an external service like codesandbox for development and then link the js file before the Body tag. That way, you don’t have to republish every time you make changes to the JS.)

2 Likes

Wow, thanks very much @jayjay13! I’ll try to implement this now.

@jayjay13 - This solution has been great so far. Only issue is that when I visit my page in production, the map appears for a split second before turning grey. Did you run into this issue? Here is a video showing the issue: Loom | Free Screen & Video Recording Software | Loom

I’m thinking it may be due to where I am pasting the 2nd portion of code. When you say to “add the following js right before the Body tag:”, can you send a screenshot of exactly where you paste this code?

Thank you!

We did similiar custom component, but we’ve used google maps instead of Mapbox. We’re using it to filter object in a drawn location.