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.

- 13,583
- 5
- 53
- 82

- 13
- 1
- 3
3 Answers
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.

- 5,448
- 15
- 29
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 restoreol.interaction.DragPan
;

- 13,583
- 5
- 53
- 82
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!

- 64
- 10