user3128376
user3128376

Reputation: 994

How to Drag Custom Icons Mapbox GL JS

I'm currently using Mapbox GL JS and I have custom icons like this example and I want to be able to drag the icons.

I'm doing it similar to draggable point example where I have mouseDown, onMove, and onUp functions. However the part I'm stuck is in onMove, I'm not sure how to set the custom icons, which are div to update its positions throughout the dragging process. I'm updating the new coordinates (lng & lat) of the icons but I'm not sure how to actually move them as right now the icons won't move/drag.

In the original draggable point example it has map.getSource('point').setData(geojson); which updates the geojson to allow the point moving on the map.

So basically I just want to be able to drag the custom icons in Mapbox GL JS.

Thanks.

Upvotes: 2

Views: 2352

Answers (1)

Anders
Anders

Reputation: 121

I ran into a similar problem and after many hours, managed to combine the two examples and export the coordinates to form fields. Try this snippet (use your own accessToken, map style and marker image)

$(document).ready(function() {
    // ===============================================
    // mapbox
    // ===============================================
    // Holds mousedown state for events. if this
    // flag is active, we move the point on `mousemove`.
    var isDragging;

    // Is the cursor over a point? if this
    // flag is active, we listen for a mousedown event.
    var isCursorOverPoint;

  
  
mapboxgl.accessToken = '############# Add your own accessToken here ##########';
    var map = new mapboxgl.Map({
        container: 'map-one',
        style: 'mapbox://############# Add your own style here ##########',
        center: [5.037913, 52.185175],
        pitch: 0,
        zoom: 12
    });
    
    var nav = new mapboxgl.Navigation({
        position: 'top-left'
    });

    map.addControl(nav);

    var canvas = map.getCanvasContainer();

    var geojson = {
        "type": "FeatureCollection",
        "features": [{
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [5.067, 52.1923]
            },
			"properties": {
				"title": "Afspreekpunt",
				"marker-symbol": "dimmle-marker"
			}
        }]
    };

    function mouseDown() {
        if (!isCursorOverPoint) return;

        isDragging = true;

        // Set a cursor indicator
        canvas.style.cursor = 'grab';

        // Mouse events
        map.on('mousemove', onMove);
        map.on('mouseup', onUp);
    }

    function onMove(e) {
        if (!isDragging) return;
        var coords = e.lngLat;

        // Set a UI indicator for dragging.
        canvas.style.cursor = 'grabbing';

        // Update the Point feature in `geojson` coordinates
        // and call setData to the source layer `point` on it.
        geojson.features[0].geometry.coordinates = [coords.lng, coords.lat];
        map.getSource('point').setData(geojson);
    }

    function onUp(e) {
        if (!isDragging) return;
        var coords = e.lngLat;

        canvas.style.cursor = '';
        isDragging = false;

        // Update form fields with coordinates
        $('#latitude').val(coords.lat);
        $('#longitude').val(coords.lng);
    }


    // Mapbox map-accordion fix
    $('#accordion').on('hidden.bs.collapse', function () {
        map.resize();
    })
    $('#accordion').on('shown.bs.collapse', function () {
        map.resize();
    })


    // After the map style has loaded on the page, add a source layer and default
    // styling for a single point.
    map.on('load', function() {

        // Add a single point to the map
        map.addSource('point', {
            "type": "geojson",
            "data": geojson
        });

        map.addLayer({
            "id": "point",
            "type": "symbol",
            "source": "point",
            "layout": {
              // ##############################################
              // NOTE: this is my marker, change it
              // to the marker you uploaded in your map style
              // - you will likely need different 
              //   offset/translate values
              // ##############################################
				"icon-image": "my-marker",
                "icon-size": 0.3,
				"text-field": "",
				"text-offset": [0, 0.6],
				"text-anchor": "top",
                "text-size": 14
			},
			"paint": {
                "icon-translate": [-6, -34],
			}
        });

        // If a feature is found on map movement,
        // set a flag to permit a mousedown events.
        map.on('mousemove', function(e) {
            var features = map.queryRenderedFeatures(e.point, { layers: ['point']         });

            // Change point and cursor style as a UI indicator
            // and set a flag to enable other mouse events.
            if (features.length) {
                canvas.style.cursor = 'move';
                isCursorOverPoint = true;
                map.dragPan.disable();
            } else {
                //map.setPaintProperty('point', 'circle-color', '#3887be');
                canvas.style.cursor = '';
                isCursorOverPoint = false;
                map.dragPan.enable();
            }
        });

        // Set `true` to dispatch the event before other functions call it. This
        // is necessary for disabling the default map dragging behaviour.
        map.on('mousedown', mouseDown, true);


    });
}); // end document ready
.map { border: 1px solid #ccc }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
   <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.25.1/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.25.1/mapbox-gl.css' rel='stylesheet' />

<div id='map-one' class='map' style='height: 360px;'></div>
<input id="latitude"> <input id="longitude">

Upvotes: 3

Related Questions