0

I use Mapbox in an Svelte-Sapper application, according to the Context API example in the Svelte Tutorial. I want to use Mapbox-Draw for drawing polygons to limit an area to search for objects, based on their coordinates. I have extended the example-code to add the Draw functionality:

mapbox.js:

import mapbox from 'mapbox-gl';
import mapboxDraw from "@mapbox/mapbox-gl-draw";
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';

mapbox.accessToken = '...';

const key = {};

export { mapbox, mapboxDraw, key };

Map.svelte:

<script>
    import { onMount, setContext } from 'svelte';
    import { mapbox, mapboxDraw, key } from '../routes/_mapbox.js';

    setContext(key, {
        getMap: () => map
    });

    export let lat;
    export let lon;
    export let zoom;

    let container;
    let map;
    let draw;

    onMount(() => {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = 'https://unpkg.com/mapbox-gl/dist/mapbox-gl.css';

        link.onload = () => {
            map = new mapbox.Map({
                container,
                style: 'mapbox://styles/mapbox/streets-v10',
                center: [lon, lat],
                zoom
            });
            draw = new mapboxDraw({
                displayControlsDefault: false,
                controls: {
                polygon: true,
                trash: true
                }
            });
            map.addControl(draw, 'top-left');
        };
  
        document.head.appendChild(link);
    });

    ...

</script>

The map works fine, and drawing polygons on the map too. But I don't succeed in reading the coordinates of a polygon - for instance on a button-press - in the parent component of Map-svelte. I have tried many things, but nothing even came close. What is the best way to do this?

The parent component looks like this:

<script>
    import Map from '../../components/Map.svelte';
    import MapMarker from '../../components/MapMarker.svelte';  
    import { storedCoordinates } from '../stores.js';
    ...
    let coords = $storedCoordinates;
</script>

<div class="col border mt-1 ml-1 mr-1 fullheight scrolldiv" style="padding:0px">
    <Map lat={52.2} lon={5.7} zoom={6.5}>
        {#each coords as coord}
            <MapMarker 
                lat={coord[0][0]} 
                lon={coord[0][1]}
                label='<div style="width:300px; ">
                           {coord[1][0][0]} <a href="items/{coord[1][0][1]}">
                           <b>&nbsp;&gt;&gt;&nbsp;</b></a>
                       </div>'                                      
            />
        {/each}
    </Map>
</div>

The coordinates ('coords') come via an api from a MongoDB store. The polygon is drawn on the map around a subset of their markers. Then the coordinates of the polygon is send back via the api to retrieve the data of that subset. Everything works okay, except that I couldn't find a way the read the polygon coordinates - I tried it in different ways with draw.getAll(), but no succes...

Molda
  • 5,619
  • 2
  • 23
  • 39
haenf
  • 1
  • 3
  • Can you show the parent component code? How do you get the coordinates of a polygon? Where do you assign the coordinates values to lon/lat variables? – Molda Mar 22 '21 at 16:06
  • @Molda, I answered in the edit (I hope that is the good way...?) – haenf Mar 23 '21 at 19:39

1 Answers1

0

My own answer: in the end the solution was rather simple (as usual :- ). I store the coordinates from draw in a store. Then the parent component can read from the store. Problem solved...

Map.svelte:

<script>
    import { onMount, setContext } from 'svelte';
    import { mapbox, mapboxDraw, key } from '../routes/_mapbox.js';
    import { selectedCoords } from '../routes/stores.js';

    setContext(key, {
        getMap: () => map
    });

    export let lat;
    export let lon;
    export let zoom;

    let container;
    let map;
    let draw;

    onMount(() => {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = 'https://unpkg.com/mapbox-gl/dist/mapbox-gl.css';

        link.onload = () => {
            map = new mapbox.Map({
                container,
                style: 'mapbox://styles/mapbox/streets-v10',
                center: [lon, lat],
                zoom
            });
            draw = new mapboxDraw({
                displayControlsDefault: false,
                controls: {
                polygon: true,
                trash: true
                }
            });
            map.addControl(draw, 'top-left');
            map.on('draw.create', getCoords);
            map.on('draw.delete', getCoords);
            map.on('draw.update', getCoords);

            function getCoords(e) {
                let data = draw.getAll();
                selectedCoords.set(data['features'][0]['geometry']['coordinates'][0]);
            }
        }; 
        document.head.appendChild(link);

    }); 
</script>


<div bind:this={container}>
    {#if map}
        <slot></slot>
    {/if}
</div>


<style>
    div {
        width: 100%;
        height: 100%;
    }

</style>
haenf
  • 1
  • 3