1

I am trying to make that an ol.overlay is draggable, but I am not able to do it. I have found this example (http://openlayers.org/en/v3.2.1/examples/drag-features.html?q=drag), but it is done using ol.Features and what I need is an overlay, since I can use a custom -html div- for showing what I need. I have also found a very interesting example that is able to do what I want, but it is done using google maps v3 and I need it for ol3.
Thanks in advance.

Jonatas Walker
  • 13,583
  • 5
  • 53
  • 82
Alberto
  • 13
  • 1
  • 3

3 Answers3

4

You can simply register a 'mousedown' event listener on the overlay's div. Inside that listener, register 'mousemove' and 'mouseup' events on the window. To update the position on 'mousemove', use the ol.Map#getEventPixel() method, which takes the 'mousemove' event as argument. On 'mouseup', you just unregister the window listeners.

marker_el.addEventListener('mousedown', function(evt) {
  function move(evt) {
    marker.setPosition(map.getEventCoordinate(evt));
  }
  function end(evt) {
    window.removeEventListener('mousemove', move);
    window.removeEventListener('mouseup', end);
  }
  window.addEventListener('mousemove', move);
  window.addEventListener('mouseup', end);
});

See http://jsfiddle.net/rnzgfg89/6/ for a working example.

ahocevar
  • 5,448
  • 15
  • 29
0

UPDATE:

There's no need of this ol.Map.prototype.forEachOverlayAtPixel method (see https://github.com/openlayers/ol3/issues/5760).

Just register a mousedown listener on the DOM overlay element and you're good to go. Fiddle updated.


ol.Overlay is a poor type in OL3 but with some work, yes, you can achieve it. ol.Feature is the all-powerful and if you really need ol.Overlay I came up this demo fiddle.

The idea is:

  • Listen for pointerdown map event and check if there's a overlay at the clicked pixel;

    • ol.Map.prototype.forEachOverlayAtPixel - just created for question
  • Deactivate ol.interaction.DragPan - map panning;

  • Listen for pointermove and set the overlay position;

  • Listen for pointerup and restore ol.interaction.DragPan;

Jonatas Walker
  • 13,583
  • 5
  • 53
  • 82
0

Thought I'd add a little bit to the discussion. I loved Jonatas' solution, but if the overlay isn't tiny, it jumps a little unless you click exactly in the center of the overlay, so I've improved his solution somewhat by finding the distance between the click and the current position of the overlay element. Then when setting the position these distances are used so that the mouse position on the overlay doesn't change as you drag the overlay.

let deltaX, deltaY

const getAdjustedCoords = coordinate => {
  const resultCoord = [coordinate[0] - deltaX, coordinate[1] - deltaY] 
  return resultCoord
}

marker_el.addEventListener('mousedown', function(evt) {
  dragPan.setActive(false);
  let markerpos = marker.getPosition();
  let clickPixel = [evt.x, evt.y]
  let clickCoords = map.getCoordinateFromPixel(clickPixel)
  
  deltaX = clickCoords[0] - markerpos[0]
  deltaY = clickCoords[1] - markerpos[1]
  marker.set('dragging', true);
  console.info('start dragging');
});

map.on('pointermove', function(evt) {
  if (marker.get('dragging') === true) {
    marker.setPosition(getAdjustedCoords(evt.coordinate));
  }
});

map.on('pointerup', function(evt) {
  if (marker.get('dragging') === true) {
    console.info('stop dragging');
    dragPan.setActive(true);
    marker.set('dragging', false);
  }
});

Here's my fiddle: https://jsfiddle.net/sxc24re8/

Cheers!

LucasY
  • 64
  • 10