OpenLayers 3: "movestart" event on map
Asked Answered
G

2

11

OpenLayers3 API has a map.on("moveend") , however I cannot find a movestart. Any one know how I can achieve this? Is there a equivalent event?

OpenLayers 2 had a movestart event on map. I am looking an exact parallel in OpenLayers3

Here's a basic jsFiddle. If someone want's to play around. I did add a movestart event there, to show what I want, but it doesn't actually exist I think.

Use Case! one might ask: I have stops on maps that have nearly fullscreen infowindows. Users can switch to next marker from infowindow. I make the windows translucent to show the map panning underneath, so users get a context of where next location is. This work's great in OpenLayers2 with movestart and moveend events. But in the new OL3 version of the map, I can't get the movestart event.

Update: I did answer the question my self, but I am still offering bounty if anyone would like to propose a better solution.

Gilbertogilbertson answered 8/8, 2015 at 16:48 Comment(6)
What's wrong with your own solution?Lomond
The code just smells. This could be something much simple if the callback was supported. Any easy way to inject such a callback in the OL3 library would be nice answer to have. Either that, or I am just looking for some different view points here i guess.Gilbertogilbertson
I guess you need to use the precompose event. See my jsFiddle: jsfiddle.net/j2cP4/116Rah
can't you just pretend to treat that as a canvas and detect the mousedown event? Like this? (check console): jsfiddle.net/j2cP4/117Ledge
@GuyT, can't use precompose as it is not specifically targeted for move action. It will get triggered for any kind of map render, like for eg. a layer change.Gilbertogilbertson
Need this for a historyControl. Using an array of moveend states is a pain.Marchpast
G
7

UPDATE v4.2.0 now supports native movestart and moveend events

map.on('movestart', function(event) {

    //To Remove after first use: ol.Observable.unByKey(event);
});

map.on('moveend', function(event) {

    //To Remove after first use:  ol.Observable.unByKey(event);
});

For OpenLayers 3 versions before release of v4.2.0

Okay so in the mean while without the movestart event, and with the moveend only triggering if there is a actual movement in map, here's how I was able to achive movestart and moveend behavior.

jsFiddle:

var pan = ol.animation.pan({
    duration: 700,
    source: this.map.getView().getCenter()
});
map.beforeRender(function(map, frameState) {
    var stillPanning = pan(map, frameState); // returns false panning is done
    if (stillPanning) {
        // do movestart stuff here
        if (!everDone) {
            doSomething();
            everDone = true;
        }
    } else {
        // do move end stuff here
        undoSomething();
        everDone = false;
    }
    return stillPanning;
});
map.getView().setCenter(geom);

So why this works?

  1. ol.animation.pan returns a ol.PreRenderFunction, which returns false if animation is not complete

  2. Writing custom function and providing it to map.renderBefore can be now used to write a wrapper around pan animation as shown above

  3. The whole business with everDone is because, stillPanning section will get called multiple times. This is okay if what you want to do there can take repeated calls, but if you want to toggle something then you want to do it only once.

behavior of 'moveend' moveend callback is only triggered if map actually moves. This is fine, but it prevents us from doing pre-animation activities, by just doing them before animation done. If you had a scenario where map doesn't actually move, then what ever you did before animation will never undo because that behavior is in moveend which never gets called!

Hope this helps someone. I had to spend good two hours to get it to work for me, because a movestart callback is absent :(

UPDATE

Upon more discussion on this thread there is another solution as suggested by @ahocevar. That is to use the propertychange event on the view like so:

function onpropertychange() {
  map.dispatchEvent('movestart');
  var view = map.getView();
  view.un('propertychange', onpropertychange);
  map.on('moveend', function() {
    view.on('propertychange', onpropertychange);
  });
};
map.getView().on('propertychange', onpropertychange);

Here's a working example of this approach: jsFiddle

Gilbertogilbertson answered 8/8, 2015 at 19:3 Comment(0)
M
2

you could use the pointerdrag or pointermove event, but you will want to debounce them. I did so here with a variable called dragStarted

http://jsfiddle.net/sean9999/j2cP4/115/

http://openlayers.org/en/v3.8.2/apidoc/ol.MapBrowserEvent.html

Mceachern answered 18/8, 2015 at 5:57 Comment(1)
Right,but problem with this approach is it depends on mouse actions. That's not what I am after. Openlayers can be made to pan or zoom programatically and that's when callbacks are most useful. This however is a pretty good approach for people who are looking to tap into mouse actions on map.Gilbertogilbertson

© 2022 - 2024 — McMap. All rights reserved.