Navigation control with Drag sequence Dragger

This is totally unfinished, but tests pass, and it is only meant to give the map a Navigation control.
This commit is contained in:
ahocevar
2012-06-21 14:08:30 +02:00
parent 8fc1e9cc98
commit 6213e07f96
9 changed files with 198 additions and 97 deletions

View File

@@ -3,8 +3,9 @@ goog.require('ol.bounds');
goog.require('ol.control.Control');
goog.require('ol.control.Navigation');
goog.require('ol.event');
goog.require('ol.event.Drag');
goog.require('ol.event.Events');
goog.require('ol.event.drag');
goog.require('ol.event.Sequence');
goog.require("ol.map");
goog.require("ol.loc");
goog.require("ol.feature");

View File

@@ -4,6 +4,8 @@ goog.require('ol.Loc');
goog.require('ol.Projection');
goog.require('ol.event');
goog.require('ol.event.Events');
goog.require('ol.event.Drag');
goog.require('ol.control.Control');
@@ -78,7 +80,7 @@ ol.Map = function() {
* @type {ol.event.Events}
*/
this.events_ = new ol.event.Events(
this, undefined, true, [ol.event.drag()]
this, undefined, true, [new ol.event.Drag()]
);
/**
@@ -109,6 +111,11 @@ ol.Map.ZOOM_FACTOR = 2;
@type {number}
*/
ol.Map.DEFAULT_TILE_SIZE = 256;
/**
@const
@type {Array.<string>}
*/
ol.Map.DEFAULT_CONTROLS = ["Navigation", "Zoom"];
/**
* @return {ol.Loc} Location.
@@ -288,14 +295,19 @@ ol.Map.prototype.setLayers = function(layers) {
};
/**
* @param {Array.<ol.control.Control>} controls
* @param {Array.<ol.control.Control>|undefined} opt_controls
*/
ol.Map.prototype.setControls = function(controls) {
ol.Map.prototype.setControls = function(opt_controls) {
if (!this.controls_) {
for (var i=0, ii=controls.length; i<ii; ++i) {
controls[i].setMap(this);
var control;
for (var i=0, ii=opt_controls.length; i<ii; ++i) {
control = opt_controls[i];
if (!(control instanceof ol.control.Control)) {
control = new ol.control[control]();
}
control.setMap(this);
}
this.controls_ = controls;
this.controls_ = opt_controls;
}
};

View File

@@ -1,7 +1,24 @@
goog.provide('ol.control');
goog.provide('ol.control.Control');
goog.require('ol.Map');
/**
* @type {Object}
* @private
*/
ol.control.registry_ = {};
/**
* @param {Function} Control
* @param {string} id
*/
ol.control.register = function(Control, id) {
ol.control.registry_[id] = Control;
};
ol.control.fromRegistry = function(id) {
return ol.control.registry_[id];
};
/**
* @constructor

View File

@@ -5,7 +5,7 @@ goog.require('ol.control.Control');
/**
* @constructor
* @extends ol.control.Control
* @extends {ol.control.Control}
* @param {boolean|undefined} opt_autoActivate
*/
ol.control.Navigation = function(opt_autoActivate) {
@@ -19,6 +19,18 @@ ol.control.Navigation = function(opt_autoActivate) {
*/
this.autoActivate_ =
goog.isDef(opt_autoActivate) ? opt_autoActivate : true;
/**
* type {number}
* @private
*/
this.oldX = undefined;
/**
* type {number}
* @private
*/
this.oldY = undefined;
};
goog.inherits(ol.control.Navigation, ol.control.Control);
@@ -45,5 +57,7 @@ ol.control.Navigation.prototype.deactivate = function() {
* @param {Event} evt
*/
ol.control.Navigation.prototype.moveMap = function(evt) {
this.getMap().moveByPx(evt.dx, evt.xy);
this.getMap().moveByPx(evt.clientX - oldX, evt.clientY - oldY);
oldX = evt.clientX;
oldY = evt.clientY;
};

57
src/ol/event/Drag.js Normal file
View File

@@ -0,0 +1,57 @@
goog.provide('ol.event.Drag');
goog.require('ol.event.Sequence');
goog.require('goog.fx.Dragger');
goog.require('goog.fx.Dragger.EventType');
/**
* @constructor
* @extends {ol.event.Sequence}
* @export
*/
ol.event.Drag = function() {
goog.base(this);
/** @inheritDoc */
this.eventType_ = {
DRAGSTART: 'dragstart',
DRAG: 'drag',
DRAGEND: 'dragend'
};
var providedEvents = this.getProvidedEvents(),
oldX, oldY;
providedEvents[this.eventType_.DRAGSTART] = {};
providedEvents[this.eventType_.DRAGSTART]
[goog.fx.Dragger.EventType.START] = function(evt) {
oldX = evt.screenX;
oldY = evt.screenY;
};
providedEvents[this.eventType_.DRAG] = {};
providedEvents[this.eventType_.DRAG]
[goog.fx.Dragger.EventType.DRAG] = function(evt) {
evt.dx = evt.screenX - oldX;
evt.dy = evt.screenY - oldY;
oldX = evt.screenX;
oldY = evt.screenY;
};
providedEvents[this.eventType_.DRAGEND] = {};
providedEvents[this.eventType_.DRAGEND]
[goog.fx.Dragger.EventType.END] = true;
};
goog.inherits(ol.event.Drag, ol.event.Sequence);
/** @inheritDoc */
ol.event.Drag.prototype.setElement = function(element) {
goog.base(this, 'setElement', element);
if (goog.isDefAndNotNull(element)) {
this.dragger_ = new goog.fx.Dragger(element);
} else if (this.dragger_) {
this.dragger_.dispose();
}
};

View File

@@ -37,8 +37,8 @@ ol.event.isMultiTouch = function(evt) {
* @constructor
* @extends {goog.events.EventTarget}
* @param {Object} object The object we are creating this instance for.
* @param {!EventTarget=} opt_element An optional element that we want to listen to
* browser events on.
* @param {!EventTarget=} opt_element An optional element that we want to
* listen to browser events on.
* @param {boolean=} opt_includeXY Should the 'xy' property automatically be
* created for browser pointer events? In general, this should be false. If
* it is true, then pointer events will automatically generate an 'xy'
@@ -75,14 +75,25 @@ ol.event.Events = function(object, opt_element, opt_includeXY, opt_sequences) {
/**
* @private
* @type {Array.<Object>}
* @type {!Array.<Object>}
*/
this.sequences_ = goog.isDef(opt_sequences) ? opt_sequences : [];
this.sequences_ = [];
this.setElement(opt_element);
this.setSequences(opt_sequences);
};
goog.inherits(ol.event.Events, goog.events.EventTarget);
/**
* @param {Array.<ol.event.Sequence>} sequences
*/
ol.event.Events.prototype.setSequences = function(sequences) {
this.sequences_ = sequences || [];
for (var i=0, ii=this.sequences_.length; i<ii; ++i) {
this.sequences_[i].setElement(this.element_);
}
};
/**
* @return {Object} The object that this instance is bound to.
* @export
@@ -112,13 +123,15 @@ ol.event.Events.prototype.getElement = function() {
* Attach this instance to a DOM element. When called, all browser events fired
* on the provided element will be relayed by this instance.
*
* @param {EventTarget=} opt_element A DOM element to attach
* @param {EventTarget} element A DOM element to attach
* browser events to. If called without this argument, all browser events
* will be detached from the element they are currently attached to.
* @export
*/
ol.event.Events.prototype.setElement = function(opt_element) {
var t, types = goog.events.EventType;
ol.event.Events.prototype.setElement = function(element) {
var t, types = {};
goog.object.extend(types, goog.events.EventType);
goog.object.extend(types, goog.fx.Dragger.EventType);
if (this.element_) {
for (t in types) {
// register the event cross-browser
@@ -128,15 +141,16 @@ ol.event.Events.prototype.setElement = function(opt_element) {
}
delete this.element_;
}
if (goog.isDef(opt_element)) {
this.element_ = opt_element;
this.element_ = element || null;
if (goog.isDefAndNotNull(element)) {
for (t in types) {
// register the event cross-browser
goog.events.listen(
opt_element, types[t], this.handleBrowserEvent, false, this
element, types[t], this.handleBrowserEvent, false, this
);
}
}
this.setSequences(this.sequences_);
};
/**
@@ -216,15 +230,18 @@ ol.event.Events.prototype.triggerEvent = function(type, evt) {
ol.event.Events.prototype.handleSequences = function(evt) {
var sequences = this.sequences_,
type = evt.type,
sequenceEvt,
sequence, browserEvent, providedEventType;
sequenceEvt, browserEvent, handled, providedEvents, providedEventType;
for (var i=0, ii=sequences.length; i<ii; ++i) {
sequence = sequences[i];
for (providedEventType in sequence) {
providedEvents = sequences[i].getProvidedEvents();
for (providedEventType in providedEvents) {
// clone the original event
sequenceEvt = {}; goog.object.extend(sequenceEvt, evt);
browserEvent = sequence[providedEventType];
if (browserEvent[type] && browserEvent[type](evt)) {
browserEvent = providedEvents[providedEventType];
handled = browserEvent[type];
if (goog.typeOf(handled) === "function") {
handled = handled(evt);
}
if (handled) {
sequenceEvt.type = providedEventType;
this.dispatchEvent(sequenceEvt);
}

40
src/ol/event/Sequence.js Normal file
View File

@@ -0,0 +1,40 @@
goog.provide('ol.event.Sequence');
/**
* @constructor
*/
ol.event.Sequence = function() {
/**
@private
@type {Element}
*/
this.element_ = null;
/**
* Event types provided by this sequence.
* @enum {string}
*/
this.eventTypes_ = {};
/**
* Event mappings provided by this sequence.
* @enum {Object}
*/
this.providedEvents_ = {};
};
/**
@param {Element} element
*/
ol.event.Sequence.prototype.setElement = function(element) {
this.element_ = element;
};
/**
@return {Object}
*/
ol.event.Sequence.prototype.getProvidedEvents = function() {
return this.providedEvents_;
};

View File

@@ -1,61 +0,0 @@
goog.provide('ol.event.drag');
/**
* @return {Object} A drag sequence with dragstart, drag and dragend events.
* @export
*/
ol.event.drag = function() {
var previous = null;
/**
* @param {Event} evt
*/
function dragstart(evt) {
if (!previous) {
evt.dx = 0;
evt.dy = 0;
previous = {screenX: evt.screenX, screenY: evt.screenY};
// don't start a drag sequence on other elements.
evt.stopPropagation();
return true;
}
}
/**
* @param {Event} evt
*/
function drag(evt) {
if (previous) {
evt.dx = evt.screenX - previous.screenX;
evt.dy = evt.screenY - previous.screenY;
previous = {screenX: evt.screenX, screenY: evt.screenY};
return true;
}
}
/**
* @param {Event} evt
*/
function dragend(evt) {
if (previous) {
previous = null;
return true;
}
}
return {
'dragstart': {
'mousedown': dragstart,
'touchstart': dragstart
},
'drag': {
'mousemove': drag,
'touchmove': drag
},
'dragend': {
'mouseup': dragend,
'touchend': dragend
}
};
};

View File

@@ -42,7 +42,7 @@ describe("ol.event.Events", function() {
expect(log.length).toBe(1);
// detach from the element
events.setElement();
events.setElement(null);
element.dispatchEvent("click");
expect(log.length).toBe(1);
@@ -126,24 +126,28 @@ describe("ol.event.Events", function() {
it("can map browser events to sequences", function() {
var element = document.createElement("div"),
events = new ol.event.Events(
"foo", element, false, [ol.event.drag()]
);
"foo", element, false, [new ol.event.Drag()]
),
mockEvt;
// mock dom object
goog.object.extend(element, new goog.events.EventTarget());
log = [];
events.register('dragstart', logFn);
events.register('start', logFn);
events.register('drag', logFn);
events.register('dragend', logFn);
events.register('end', logFn);
element.dispatchEvent("mousedown");
element.dispatchEvent("mousemove");
element.dispatchEvent("mouseup");
mockEvt = new goog.events.BrowserEvent({type: "start", button: null});
element.dispatchEvent(mockEvt);
mockEvt = new goog.events.BrowserEvent({type: "drag", button: null});
element.dispatchEvent(mockEvt);
mockEvt = new goog.events.BrowserEvent({type: "end", button: null});
element.dispatchEvent(mockEvt);
expect(log[0].evt.type).toBe("dragstart");
expect(log[0].evt.type).toBe("start");
expect(log[1].evt.type).toBe("drag");
expect(log[2].evt.type).toBe("dragend");
expect(log[2].evt.type).toBe("end");
events.destroy();
});