Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Openlayers and catching drag event

Im using OpenLayers and i need to be able to tell difference between when map has been moved by my own scrip or by user. Yeah im aware that i can use moveend. But it also triggers when the same script is moving or repositioning map based on incoming data from ajax calls. So moveend or other map events wont work.

I did some googling and found OpenLayers.Hander.Drag. But all that i managed with it was to stop users from dragging map.

My script:

this.dragger = new OpenLayers.Handler.Drag('',{
        'dragStart': function(evt){
            this.userdragged = true;
            console.log('drag');
        }},{
        'map':this.mymap
        });
this.dragger.activate();

As you can see, i tried to set userdragged variable to true to use this same variable in moveend event later. Unfortunately all this did was to stop my map from beeing draggable.

Can someone assist me please?

Alan

like image 603
Odif Yltsaeb Avatar asked Apr 07 '11 14:04

Odif Yltsaeb


3 Answers

Got it!

What got it working was :

dragcontrol = new OpenLayers.Control.DragPan({'map':this.mymap, 'panMapDone':function(evt){
    this.userdragged  = true;
    console.log('drag');
}});
dragcontrol.draw();
this.mymap.addControl(dragcontrol);
dragcontrol.activate();

Booyaka!

Edit: Actually this.userdragged wont work in there... the scope of this is different there. you would need to do something like var that = this; before that object initialization and use that.userdragged = true....

Edit2: I later found, that this panMapDone function overwrites DragPans own method which has same name. With just my previous example, you can end up with map that results in vector features going out of sync with map, when user drags map. To stop that from happening, you should copy the original functionality into that function too... to make it look something like that:

dragcontrol = new OpenLayers.Control.DragPan({'map':this.mymap, 'panMapDone':function(xy){
        if(this.panned) {
            var res = null;
            if (this.kinetic) {
                res = this.kinetic.end(xy);
            }
            this.map.pan(
                this.handler.last.x - xy.x,
                this.handler.last.y - xy.y,
                {dragging: !!res, animate: false}
            );
            if (res) {
                var self = this;
                this.kinetic.move(res, function(x, y, end) {
                    self.map.pan(x, y, {dragging: !end, animate: false});
                });
            }
            this.panned = false;
        }
        that.userdragged  = true;
            // do whatever you want here
    }});
    dragcontrol.draw();
    this.mymap.addControl(dragcontrol);
    dragcontrol.activate();

Alan

like image 105
Odif Yltsaeb Avatar answered Oct 18 '22 14:10

Odif Yltsaeb


Looking at the documentation on Drag handlers, it states that it's supposed to be used with a Control object. Are you using it that way? Maybe the code snippet doesn't show it?

"If a handler is being used without a control, the handlers setMap method must be overridden to deal properly with the map."

I haven't tried it, but it seems as you should go for something like this:

var myControl = new OpenLayers.Control();

var dragger = new OpenLayers.Handler.Drag{
    control: myControl,
    callbacks: { 'done': function() { // do something }},
    options: {}
}

myMap.addControl(myControl);
myControl.activate();
like image 22
Niklas Wulff Avatar answered Oct 18 '22 12:10

Niklas Wulff


Just posting an example here of executing an arbitrary function when the user drag the map, without interfering with the normal click-drag used to pan the map, because this page was the most frequent result during my search to find how to do that.

var CustomDragControl = OpenLayers.Class(OpenLayers.Control, {

    defaultHandlerOptions: {
        'stopDown': false
        /* important, otherwise it prevent the click-drag event from 
           triggering the normal click-drag behavior on the map to pan it */
    },

    initialize: function(options) {
        this.handlerOptions = OpenLayers.Util.extend(
            {}, this.defaultHandlerOptions
        );
        OpenLayers.Control.prototype.initialize.apply(
            this, arguments
        ); 
        this.handler = new OpenLayers.Handler.Drag(
            this, {
                'down': this.onDown //could be also 'move', 'up' or 'out'
            }, this.handlerOptions
        );
    }, 

    onDown: function(evt) {
        // do something when the user clic on the map (so on drag start)
        console.log('user clicked down on the map');
    }
});

then add the control to you map's controls list when creating the map instance, or with a map.addControl(), with

new CustomDragControl ({'autoActivate': true})
like image 39
user2286522 Avatar answered Oct 18 '22 13:10

user2286522