Merge pull request #1840 from tsauerwein/pointerevents
Use pointer events
This commit is contained in:
@@ -51,8 +51,8 @@ var map = new ol.Map({
|
||||
layers: [vector],
|
||||
interactions: ol.interaction.defaults({
|
||||
altShiftDragRotate: false,
|
||||
dragPan: false,
|
||||
touchRotate: false
|
||||
pan: false,
|
||||
rotate: false
|
||||
}).extend([new ol.interaction.DragPan({kinetic: false})]),
|
||||
renderer: 'canvas',
|
||||
target: olMapDiv,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.interaction');
|
||||
|
||||
@@ -369,6 +369,30 @@
|
||||
* supported.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interactions for the map. Default is `true` for all options.
|
||||
* @typedef {Object} olx.interaction.DefaultsOptions
|
||||
* @property {boolean|undefined} altShiftDragRotate Whether Alt-Shift-drag
|
||||
* rotate is desired. Default is `true`.
|
||||
* @property {boolean|undefined} doubleClickZoom Whether double click zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} keyboard Whether keyboard interaction is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} mouseWheelZoom Whether mousewheel zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} shiftDragZoom Whether Shift-drag zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} dragPan Whether drag pan is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} pinchRotate Whether pinch rotate is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} pinchZoom Whether pinch zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {number|undefined} zoomDelta Zoom delta.
|
||||
* @property {number|undefined} zoomDuration Zoom duration.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.DoubleClickZoomOptions
|
||||
* @property {number|undefined} duration Animation duration in milliseconds. Default is `250`.
|
||||
@@ -386,19 +410,18 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.DragPanOptions
|
||||
* @property {ol.Kinetic|undefined} kinetic Kinetic inertia to apply to the pan.
|
||||
* @typedef {Object} olx.interaction.DragBoxOptions
|
||||
* @property {ol.events.ConditionType|undefined} condition A conditional
|
||||
* modifier (i.e. Shift key) that determines if the interaction is active
|
||||
* or not, default is no modifiers.
|
||||
* or not, default is always.
|
||||
* @property {ol.style.Style} style Style for the box.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.DragRotateOptions
|
||||
* @property {ol.events.ConditionType|undefined} condition A conditional
|
||||
* modifier (i.e. Shift key) that determines if the interaction is active
|
||||
* or not, default is both shift and alt keys.
|
||||
* @typedef {Object} olx.interaction.DragPanOptions
|
||||
* @property {ol.Kinetic|undefined} kinetic Kinetic inertia to apply to the
|
||||
* pan.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
@@ -411,11 +434,10 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.DragBoxOptions
|
||||
* @typedef {Object} olx.interaction.DragRotateOptions
|
||||
* @property {ol.events.ConditionType|undefined} condition A conditional
|
||||
* modifier (i.e. Shift key) that determines if the interaction is active
|
||||
* or not, default is always.
|
||||
* @property {ol.style.Style} style Style for the box.
|
||||
* or not, default is both shift and alt keys.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
@@ -428,29 +450,6 @@
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interactions for the map. Default is `true` for all options.
|
||||
* @typedef {Object} olx.interaction.DefaultsOptions
|
||||
* @property {boolean|undefined} altShiftDragRotate Whether Alt-Shift-drag
|
||||
* rotate is desired. Default is `true`.
|
||||
* @property {boolean|undefined} doubleClickZoom Whether double click zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} dragPan Whether drag-pan is desired. Default is `true`.
|
||||
* @property {boolean|undefined} keyboard Whether keyboard interaction is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} mouseWheelZoom Whether mousewheel zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} shiftDragZoom Whether Shift-drag zoom is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} touchPan Whether touch pan is
|
||||
* desired. Default is `true`.
|
||||
* @property {boolean|undefined} touchRotate Whether touch rotate is desired. Default is `true`.
|
||||
* @property {boolean|undefined} touchZoom Whether touch zoom is desired. Default is `true`.
|
||||
* @property {number|undefined} zoomDelta Zoom delta.
|
||||
* @property {number|undefined} zoomDuration Zoom duration.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.DrawOptions
|
||||
* @property {ol.Collection|undefined} features Destination collection for the drawn features.
|
||||
@@ -486,12 +485,33 @@
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.ModifyOptions
|
||||
* @property {number|undefined} pixelTolerance Pixel tolerance for considering
|
||||
* the pointer close enough to a vertex for editing. Default is 20 pixels.
|
||||
* @property {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction|undefined} style FeatureOverlay style.
|
||||
* @property {ol.Collection} features The features the interaction works on.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.MouseWheelZoomOptions
|
||||
* @property {number|undefined} duration Animation duration in milliseconds. Default is `250`.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.PinchRotateOptions
|
||||
* @property {number|undefined} threshold Minimal angle in radians to start a rotation.
|
||||
* Default is `0.3`.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.PinchZoomOptions
|
||||
* @property {number|undefined} duration Animation duration in milliseconds. Default is `400`.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.SelectOptions
|
||||
* @property {ol.events.ConditionType|undefined} addCondition A conditional
|
||||
@@ -511,34 +531,6 @@
|
||||
* @property {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction|undefined} style FeatureOverlay style.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.TouchPanOptions
|
||||
* @property {ol.Kinetic|undefined} kinetic Kinetic inertia to apply to the
|
||||
* pan.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.ModifyOptions
|
||||
* @property {number|undefined} pixelTolerance Pixel tolerance for considering
|
||||
* the pointer close enough to a vertex for editing. Default is 20 pixels.
|
||||
* @property {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction|undefined} style FeatureOverlay style.
|
||||
* @property {ol.Collection} features The features the interaction works on.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.TouchRotateOptions
|
||||
* @property {number|undefined} threshold Minimal angle in radians to start a rotation.
|
||||
* Default is `0.3`.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.interaction.TouchZoomOptions
|
||||
* @property {number|undefined} duration Animation duration in milliseconds. Default is `400`.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} olx.layer.BaseOptions
|
||||
* @property {number|undefined} brightness Brightness. Default is `0`.
|
||||
|
||||
@@ -159,7 +159,25 @@ ol.BrowserFeature.HAS_GEOLOCATION = 'geolocation' in goog.global.navigator;
|
||||
*/
|
||||
ol.BrowserFeature.HAS_TOUCH = ol.ASSUME_TOUCH ||
|
||||
(goog.global.document &&
|
||||
'ontouchstart' in goog.global.document.documentElement) ||
|
||||
'ontouchstart' in goog.global.document.documentElement);
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports pointer events.
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.BrowserFeature.HAS_POINTER = 'PointerEvent' in goog.global;
|
||||
|
||||
|
||||
/**
|
||||
* True if browser supports ms pointer events (IE 10).
|
||||
* @const
|
||||
* @type {boolean}
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.BrowserFeature.HAS_MSPOINTER =
|
||||
!!(goog.global.navigator.msPointerEnabled);
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ goog.require('goog.asserts');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.MapBrowserPointerEvent');
|
||||
|
||||
|
||||
/**
|
||||
@@ -120,3 +121,17 @@ ol.events.condition.targetNotEditable = function(mapBrowserEvent) {
|
||||
tagName !== goog.dom.TagName.SELECT &&
|
||||
tagName !== goog.dom.TagName.TEXTAREA);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event originates from a mouse device.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.events.condition.mouseOnly = function(mapBrowserEvent) {
|
||||
goog.asserts.assertInstanceof(mapBrowserEvent, ol.MapBrowserPointerEvent);
|
||||
/* pointerId must be 1 for mouse devices,
|
||||
* see: http://www.w3.org/Submission/pointer-events/#pointerevent-interface
|
||||
*/
|
||||
return mapBrowserEvent.pointerEvent.pointerId == 1;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ goog.require('goog.asserts');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('ol.events.ConditionType');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.interaction.Drag');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
goog.require('ol.render.Box');
|
||||
|
||||
|
||||
@@ -62,8 +62,14 @@ goog.inherits(ol.DragBoxEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* Allows the user to zoom the map by clicking and dragging on the map,
|
||||
* normally combined with an {@link ol.events.condition} that limits
|
||||
* it to when the shift key is held down.
|
||||
*
|
||||
* This interaction is only supported for mouse devices.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.DragBoxOptions=} opt_options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
@@ -99,13 +105,17 @@ ol.interaction.DragBox = function(opt_options) {
|
||||
options.condition : ol.events.condition.always;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.DragBox, ol.interaction.Drag);
|
||||
goog.inherits(ol.interaction.DragBox, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragBox.prototype.handleDrag = function(mapBrowserEvent) {
|
||||
ol.interaction.DragBox.prototype.handlePointerDrag = function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
|
||||
};
|
||||
|
||||
@@ -129,23 +139,36 @@ ol.interaction.DragBox.prototype.onBoxEnd = goog.nullFunction;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragBox.prototype.handleDragEnd =
|
||||
ol.interaction.DragBox.prototype.handlePointerUp =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.box_.setMap(null);
|
||||
if (this.deltaX * this.deltaX + this.deltaY * this.deltaY >=
|
||||
|
||||
var deltaX = mapBrowserEvent.pixel[0] - this.startPixel_[0];
|
||||
var deltaY = mapBrowserEvent.pixel[1] - this.startPixel_[1];
|
||||
|
||||
if (deltaX * deltaX + deltaY * deltaY >=
|
||||
ol.DRAG_BOX_HYSTERESIS_PIXELS_SQUARED) {
|
||||
this.onBoxEnd(mapBrowserEvent);
|
||||
this.dispatchEvent(new ol.DragBoxEvent(ol.DragBoxEventType.BOXEND,
|
||||
mapBrowserEvent.coordinate));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragBox.prototype.handleDragStart =
|
||||
ol.interaction.DragBox.prototype.handlePointerDown =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) {
|
||||
this.startPixel_ = mapBrowserEvent.pixel;
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
goog.provide('ol.interaction.Drag');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for interactions that drag the map.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Interaction}
|
||||
*/
|
||||
ol.interaction.Drag = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.dragging_ = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.startX = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.startY = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.deltaX = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.deltaY = 0;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.startCenter = null;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.startCoordinate = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Drag, ol.interaction.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether we're dragging.
|
||||
*/
|
||||
ol.interaction.Drag.prototype.getDragging = function() {
|
||||
return this.dragging_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDrag = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDragEnd = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
* @return {boolean} Capture dragging.
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDragStart = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleDown = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Drag.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
var map = mapBrowserEvent.map;
|
||||
if (!map.isDef()) {
|
||||
return true;
|
||||
}
|
||||
var stopEvent = false;
|
||||
var view = map.getView();
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DOWN) {
|
||||
goog.asserts.assertInstanceof(browserEvent, goog.events.BrowserEvent);
|
||||
this.handleDown(mapBrowserEvent);
|
||||
}
|
||||
if (this.dragging_) {
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAG) {
|
||||
goog.asserts.assertInstanceof(browserEvent, goog.events.BrowserEvent);
|
||||
this.deltaX = browserEvent.clientX - this.startX;
|
||||
this.deltaY = browserEvent.clientY - this.startY;
|
||||
this.handleDrag(mapBrowserEvent);
|
||||
} else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAGEND) {
|
||||
goog.asserts.assertInstanceof(browserEvent, goog.events.BrowserEvent);
|
||||
this.deltaX = browserEvent.clientX - this.startX;
|
||||
this.deltaY = browserEvent.clientY - this.startY;
|
||||
this.dragging_ = false;
|
||||
this.handleDragEnd(mapBrowserEvent);
|
||||
}
|
||||
} else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAGSTART) {
|
||||
goog.asserts.assertInstanceof(browserEvent, goog.events.BrowserEvent);
|
||||
var view2DState = view.getView2D().getView2DState();
|
||||
this.startX = browserEvent.clientX;
|
||||
this.startY = browserEvent.clientY;
|
||||
this.deltaX = 0;
|
||||
this.deltaY = 0;
|
||||
this.startCenter = view2DState.center;
|
||||
this.startCoordinate = mapBrowserEvent.coordinate;
|
||||
var handled = this.handleDragStart(mapBrowserEvent);
|
||||
if (handled) {
|
||||
this.dragging_ = true;
|
||||
mapBrowserEvent.preventDefault();
|
||||
stopEvent = true;
|
||||
}
|
||||
}
|
||||
return !stopEvent;
|
||||
};
|
||||
@@ -1,23 +1,22 @@
|
||||
// FIXME works for View2D only
|
||||
|
||||
goog.provide('ol.interaction.DragPan');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Kinetic');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.PreRenderFunction');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.coordinate');
|
||||
goog.require('ol.events.ConditionType');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.interaction.Drag');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows the user to pan the map by clickng and dragging.
|
||||
* Allows the user to pan the map by dragging the map.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.DragPanOptions=} opt_options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
@@ -27,13 +26,6 @@ ol.interaction.DragPan = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.events.ConditionType}
|
||||
*/
|
||||
this.condition_ = goog.isDef(options.condition) ?
|
||||
options.condition : ol.events.condition.noModifierKeys;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Kinetic|undefined}
|
||||
@@ -46,101 +38,118 @@ ol.interaction.DragPan = function(opt_options) {
|
||||
*/
|
||||
this.kineticPreRenderFn_ = null;
|
||||
|
||||
/**
|
||||
* @type {ol.Pixel}
|
||||
*/
|
||||
this.lastCentroid = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.events.ConditionType}
|
||||
*/
|
||||
this.condition_ = goog.isDef(opt_options.condition) ?
|
||||
opt_options.condition : ol.events.condition.noModifierKeys;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.noKinetic_ = false;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.DragPan, ol.interaction.Drag);
|
||||
goog.inherits(ol.interaction.DragPan, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) {
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.update(
|
||||
mapBrowserEvent.browserEvent.clientX,
|
||||
mapBrowserEvent.browserEvent.clientY);
|
||||
}
|
||||
var map = mapBrowserEvent.map;
|
||||
// FIXME works for View2D only
|
||||
var view = map.getView();
|
||||
goog.asserts.assertInstanceof(view, ol.View2D);
|
||||
var view2DState = view.getView2DState();
|
||||
var newCenter = [
|
||||
-view2DState.resolution * this.deltaX,
|
||||
view2DState.resolution * this.deltaY
|
||||
];
|
||||
ol.coordinate.rotate(newCenter, view2DState.rotation);
|
||||
ol.coordinate.add(newCenter, this.startCenter);
|
||||
newCenter = view.constrainCenter(newCenter);
|
||||
map.render();
|
||||
view.setCenter(newCenter);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) {
|
||||
|
||||
// FIXME works for View2D only
|
||||
|
||||
var map = mapBrowserEvent.map;
|
||||
var view = map.getView();
|
||||
view.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
|
||||
if (this.kinetic_ && this.kinetic_.end()) {
|
||||
var view2D = view.getView2D();
|
||||
ol.interaction.DragPan.prototype.handlePointerDrag = function(mapBrowserEvent) {
|
||||
goog.asserts.assert(this.targetPointers.length >= 1);
|
||||
var centroid =
|
||||
ol.interaction.Pointer.centroid(this.targetPointers);
|
||||
if (!goog.isNull(this.lastCentroid)) {
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.update(centroid[0], centroid[1]);
|
||||
}
|
||||
var deltaX = this.lastCentroid[0] - centroid[0];
|
||||
var deltaY = centroid[1] - this.lastCentroid[1];
|
||||
var map = mapBrowserEvent.map;
|
||||
var view2D = map.getView().getView2D();
|
||||
goog.asserts.assertInstanceof(view2D, ol.View2D);
|
||||
var view2DState = view2D.getView2DState();
|
||||
var distance = this.kinetic_.getDistance();
|
||||
var angle = this.kinetic_.getAngle();
|
||||
this.kineticPreRenderFn_ = this.kinetic_.pan(view2DState.center);
|
||||
map.beforeRender(this.kineticPreRenderFn_);
|
||||
|
||||
var centerpx = map.getPixelFromCoordinate(view2DState.center);
|
||||
var dest = map.getCoordinateFromPixel([
|
||||
centerpx[0] - distance * Math.cos(angle),
|
||||
centerpx[1] - distance * Math.sin(angle)
|
||||
]);
|
||||
dest = view2D.constrainCenter(dest);
|
||||
view2D.setCenter(dest);
|
||||
var center = [deltaX, deltaY];
|
||||
ol.coordinate.scale(center, view2DState.resolution);
|
||||
ol.coordinate.rotate(center, view2DState.rotation);
|
||||
ol.coordinate.add(center, view2DState.center);
|
||||
center = view2D.constrainCenter(center);
|
||||
map.render();
|
||||
view2D.setCenter(center);
|
||||
}
|
||||
map.render();
|
||||
this.lastCentroid = centroid;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) {
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) {
|
||||
ol.interaction.DragPan.prototype.handlePointerUp =
|
||||
function(mapBrowserEvent) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var view2D = map.getView().getView2D();
|
||||
goog.asserts.assertInstanceof(view2D, ol.View2D);
|
||||
if (this.targetPointers.length === 0) {
|
||||
if (!this.noKinetic_ && this.kinetic_ && this.kinetic_.end()) {
|
||||
var distance = this.kinetic_.getDistance();
|
||||
var angle = this.kinetic_.getAngle();
|
||||
var center = view2D.getCenter();
|
||||
goog.asserts.assert(goog.isDef(center));
|
||||
this.kineticPreRenderFn_ = this.kinetic_.pan(center);
|
||||
map.beforeRender(this.kineticPreRenderFn_);
|
||||
var centerpx = map.getPixelFromCoordinate(center);
|
||||
var dest = map.getCoordinateFromPixel([
|
||||
centerpx[0] - distance * Math.cos(angle),
|
||||
centerpx[1] - distance * Math.sin(angle)
|
||||
]);
|
||||
dest = view2D.constrainCenter(dest);
|
||||
view2D.setCenter(dest);
|
||||
}
|
||||
view2D.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
map.render();
|
||||
return false;
|
||||
} else {
|
||||
this.lastCentroid = null;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handlePointerDown =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var view2D = map.getView().getView2D();
|
||||
goog.asserts.assertInstanceof(view2D, ol.View2D);
|
||||
this.lastCentroid = null;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
view2D.setHint(ol.ViewHint.INTERACTING, 1);
|
||||
}
|
||||
map.render();
|
||||
if (!goog.isNull(this.kineticPreRenderFn_) &&
|
||||
map.removePreRenderFunction(this.kineticPreRenderFn_)) {
|
||||
view2D.setCenter(mapBrowserEvent.frameState.view2DState.center);
|
||||
this.kineticPreRenderFn_ = null;
|
||||
}
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.begin();
|
||||
this.kinetic_.update(browserEvent.clientX, browserEvent.clientY);
|
||||
}
|
||||
var map = mapBrowserEvent.map;
|
||||
map.getView().setHint(ol.ViewHint.INTERACTING, 1);
|
||||
map.render();
|
||||
// No kinetic as soon as more than one pointer on the screen is
|
||||
// detected. This is to prevent nasty pans after pinch.
|
||||
this.noKinetic_ = this.targetPointers.length > 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragPan.prototype.handleDown = function(mapBrowserEvent) {
|
||||
var map = mapBrowserEvent.map;
|
||||
// FIXME works for View2D only
|
||||
var view = map.getView();
|
||||
goog.asserts.assertInstanceof(view, ol.View2D);
|
||||
goog.asserts.assert(!goog.isNull(mapBrowserEvent.frameState));
|
||||
if (!goog.isNull(this.kineticPreRenderFn_) &&
|
||||
map.removePreRenderFunction(this.kineticPreRenderFn_)) {
|
||||
map.render();
|
||||
view.setCenter(mapBrowserEvent.frameState.view2DState.center);
|
||||
this.kineticPreRenderFn_ = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7,8 +7,8 @@ goog.require('goog.math.Vec2');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.events.ConditionType');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.interaction.Drag');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
|
||||
|
||||
/**
|
||||
@@ -23,9 +23,12 @@ ol.interaction.DRAGROTATEANDZOOM_ANIMATION_DURATION = 400;
|
||||
* on the map. By default, this interaction is limited to when the shift
|
||||
* key is held down.
|
||||
*
|
||||
* This interaction is not included in the default interactions.
|
||||
* This interaction is only supported for mouse devices.
|
||||
*
|
||||
* And this interaction is not included in the default interactions.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.DragRotateAndZoomOptions=} opt_options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
@@ -61,14 +64,19 @@ ol.interaction.DragRotateAndZoom = function(opt_options) {
|
||||
this.lastScaleDelta_ = 0;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.DragRotateAndZoom, ol.interaction.Drag);
|
||||
goog.inherits(ol.interaction.DragRotateAndZoom,
|
||||
ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotateAndZoom.prototype.handleDrag =
|
||||
ol.interaction.DragRotateAndZoom.prototype.handlePointerDrag =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = mapBrowserEvent.map;
|
||||
var size = map.getSize();
|
||||
var offset = mapBrowserEvent.pixel;
|
||||
@@ -101,8 +109,12 @@ ol.interaction.DragRotateAndZoom.prototype.handleDrag =
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotateAndZoom.prototype.handleDragEnd =
|
||||
ol.interaction.DragRotateAndZoom.prototype.handlePointerUp =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var map = mapBrowserEvent.map;
|
||||
// FIXME works for View2D only
|
||||
var view = map.getView();
|
||||
@@ -115,15 +127,19 @@ ol.interaction.DragRotateAndZoom.prototype.handleDragEnd =
|
||||
undefined, ol.interaction.DRAGROTATEANDZOOM_ANIMATION_DURATION,
|
||||
direction);
|
||||
this.lastScaleDelta_ = 0;
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotateAndZoom.prototype.handleDragStart =
|
||||
ol.interaction.DragRotateAndZoom.prototype.handlePointerDown =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.condition_(mapBrowserEvent)) {
|
||||
mapBrowserEvent.map.getView().setHint(ol.ViewHint.INTERACTING, 1);
|
||||
this.lastAngle_ = undefined;
|
||||
@@ -133,3 +149,15 @@ ol.interaction.DragRotateAndZoom.prototype.handleDragStart =
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotateAndZoom.prototype.shouldStopEvent =
|
||||
function(hasHandledEvent) {
|
||||
/* Stop the event if it was handled, so that interaction `DragZoom`
|
||||
* does not interfere.
|
||||
*/
|
||||
return hasHandledEvent;
|
||||
};
|
||||
|
||||
@@ -4,8 +4,8 @@ goog.require('goog.asserts');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.events.ConditionType');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.interaction.Drag');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
|
||||
|
||||
/**
|
||||
@@ -19,8 +19,11 @@ ol.interaction.DRAGROTATE_ANIMATION_DURATION = 250;
|
||||
* Allows the user to rotate the map by clicking and dragging on the map,
|
||||
* normally combined with an {@link ol.events.condition} that limits
|
||||
* it to when the alt and shift keys are held down.
|
||||
*
|
||||
* This interaction is only supported for mouse devices.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.DragRotateOptions=} opt_options Options.
|
||||
*/
|
||||
ol.interaction.DragRotate = function(opt_options) {
|
||||
@@ -43,13 +46,18 @@ ol.interaction.DragRotate = function(opt_options) {
|
||||
this.lastAngle_ = undefined;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.DragRotate, ol.interaction.Drag);
|
||||
goog.inherits(ol.interaction.DragRotate, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotate.prototype.handleDrag = function(mapBrowserEvent) {
|
||||
ol.interaction.DragRotate.prototype.handlePointerDrag =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = mapBrowserEvent.map;
|
||||
var size = map.getSize();
|
||||
var offset = mapBrowserEvent.pixel;
|
||||
@@ -71,7 +79,12 @@ ol.interaction.DragRotate.prototype.handleDrag = function(mapBrowserEvent) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotate.prototype.handleDragEnd = function(mapBrowserEvent) {
|
||||
ol.interaction.DragRotate.prototype.handlePointerUp =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var map = mapBrowserEvent.map;
|
||||
// FIXME works for View2D only
|
||||
var view = map.getView();
|
||||
@@ -80,14 +93,19 @@ ol.interaction.DragRotate.prototype.handleDragEnd = function(mapBrowserEvent) {
|
||||
var view2DState = view2D.getView2DState();
|
||||
ol.interaction.Interaction.rotate(map, view2D, view2DState.rotation,
|
||||
undefined, ol.interaction.DRAGROTATE_ANIMATION_DURATION);
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.DragRotate.prototype.handleDragStart =
|
||||
ol.interaction.DragRotate.prototype.handlePointerDown =
|
||||
function(mapBrowserEvent) {
|
||||
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var browserEvent = mapBrowserEvent.browserEvent;
|
||||
if (browserEvent.isMouseActionButton() && this.condition_(mapBrowserEvent)) {
|
||||
var map = mapBrowserEvent.map;
|
||||
|
||||
@@ -17,7 +17,7 @@ goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Circle');
|
||||
goog.require('ol.style.Fill');
|
||||
@@ -59,7 +59,7 @@ goog.inherits(ol.DrawEvent, goog.events.Event);
|
||||
/**
|
||||
* Interaction that allows drawing geometries
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Interaction}
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.DrawOptions} options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
@@ -67,6 +67,12 @@ ol.interaction.Draw = function(options) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {ol.Pixel}
|
||||
* @private
|
||||
*/
|
||||
this.downPx_ = null;
|
||||
|
||||
/**
|
||||
* Target source for drawn features.
|
||||
* @type {ol.source.Vector}
|
||||
@@ -149,8 +155,8 @@ ol.interaction.Draw = function(options) {
|
||||
this.sketchRawPolygon_ = null;
|
||||
|
||||
/**
|
||||
* Squared tolerance for handling click events. If the squared distance
|
||||
* between a down and click event is greater than this tolerance, click events
|
||||
* Squared tolerance for handling up events. If the squared distance
|
||||
* between a down and up event is greater than this tolerance, up events
|
||||
* will not be handled.
|
||||
* @type {number}
|
||||
* @private
|
||||
@@ -168,7 +174,7 @@ ol.interaction.Draw = function(options) {
|
||||
});
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Draw, ol.interaction.Interaction);
|
||||
goog.inherits(ol.interaction.Draw, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
@@ -250,31 +256,40 @@ ol.interaction.Draw.prototype.handleMapBrowserEvent = function(event) {
|
||||
return true;
|
||||
}
|
||||
var pass = true;
|
||||
if (event.type === ol.MapBrowserEvent.EventType.CLICK) {
|
||||
pass = this.handleClick_(event);
|
||||
} else if (event.type === ol.MapBrowserEvent.EventType.MOUSEMOVE) {
|
||||
pass = this.handleMove_(event);
|
||||
if (event.type === ol.MapBrowserEvent.EventType.POINTERMOVE) {
|
||||
pass = this.handlePointerMove_(event);
|
||||
} else if (event.type === ol.MapBrowserEvent.EventType.DBLCLICK) {
|
||||
pass = false;
|
||||
}
|
||||
return pass;
|
||||
return (goog.base(this, 'handleMapBrowserEvent', event) && pass);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle click events.
|
||||
* @param {ol.MapBrowserEvent} event A click event.
|
||||
* Handle down events.
|
||||
* @param {ol.MapBrowserEvent} event A down event.
|
||||
* @return {boolean} Pass the event to other interactions.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Draw.prototype.handleClick_ = function(event) {
|
||||
var downPx = event.map.getEventPixel(event.target.getDown());
|
||||
ol.interaction.Draw.prototype.handlePointerDown = function(event) {
|
||||
this.downPx_ = event.pixel;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle up events.
|
||||
* @param {ol.MapBrowserEvent} event An up event.
|
||||
* @return {boolean} Pass the event to other interactions.
|
||||
*/
|
||||
ol.interaction.Draw.prototype.handlePointerUp = function(event) {
|
||||
var downPx = this.downPx_;
|
||||
var clickPx = event.pixel;
|
||||
var dx = downPx[0] - clickPx[0];
|
||||
var dy = downPx[1] - clickPx[1];
|
||||
var squaredDistance = dx * dx + dy * dy;
|
||||
var pass = true;
|
||||
if (squaredDistance <= this.squaredClickTolerance_) {
|
||||
this.handlePointerMove_(event);
|
||||
if (goog.isNull(this.finishCoordinate_)) {
|
||||
this.startDrawing_(event);
|
||||
} else if (this.mode_ === ol.interaction.DrawMode.POINT ||
|
||||
@@ -290,12 +305,12 @@ ol.interaction.Draw.prototype.handleClick_ = function(event) {
|
||||
|
||||
|
||||
/**
|
||||
* Handle mousemove events.
|
||||
* @param {ol.MapBrowserEvent} event A mousemove event.
|
||||
* Handle move events.
|
||||
* @param {ol.MapBrowserEvent} event A move event.
|
||||
* @return {boolean} Pass the event to other interactions.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Draw.prototype.handleMove_ = function(event) {
|
||||
ol.interaction.Draw.prototype.handlePointerMove_ = function(event) {
|
||||
if (this.mode_ === ol.interaction.DrawMode.POINT &&
|
||||
goog.isNull(this.finishCoordinate_)) {
|
||||
this.startDrawing_(event);
|
||||
|
||||
@@ -9,9 +9,8 @@ goog.require('ol.interaction.DragZoom');
|
||||
goog.require('ol.interaction.KeyboardPan');
|
||||
goog.require('ol.interaction.KeyboardZoom');
|
||||
goog.require('ol.interaction.MouseWheelZoom');
|
||||
goog.require('ol.interaction.TouchPan');
|
||||
goog.require('ol.interaction.TouchRotate');
|
||||
goog.require('ol.interaction.TouchZoom');
|
||||
goog.require('ol.interaction.PinchRotate');
|
||||
goog.require('ol.interaction.PinchZoom');
|
||||
|
||||
|
||||
/**
|
||||
@@ -51,28 +50,6 @@ ol.interaction.defaults = function(opt_options) {
|
||||
}));
|
||||
}
|
||||
|
||||
var touchPan = goog.isDef(options.touchPan) ?
|
||||
options.touchPan : true;
|
||||
if (touchPan) {
|
||||
interactions.push(new ol.interaction.TouchPan({
|
||||
kinetic: kinetic
|
||||
}));
|
||||
}
|
||||
|
||||
var touchRotate = goog.isDef(options.touchRotate) ?
|
||||
options.touchRotate : true;
|
||||
if (touchRotate) {
|
||||
interactions.push(new ol.interaction.TouchRotate());
|
||||
}
|
||||
|
||||
var touchZoom = goog.isDef(options.touchZoom) ?
|
||||
options.touchZoom : true;
|
||||
if (touchZoom) {
|
||||
interactions.push(new ol.interaction.TouchZoom({
|
||||
duration: options.zoomDuration
|
||||
}));
|
||||
}
|
||||
|
||||
var dragPan = goog.isDef(options.dragPan) ?
|
||||
options.dragPan : true;
|
||||
if (dragPan) {
|
||||
@@ -81,6 +58,20 @@ ol.interaction.defaults = function(opt_options) {
|
||||
}));
|
||||
}
|
||||
|
||||
var pinchRotate = goog.isDef(options.pinchRotate) ?
|
||||
options.pinchRotate : true;
|
||||
if (pinchRotate) {
|
||||
interactions.push(new ol.interaction.PinchRotate());
|
||||
}
|
||||
|
||||
var pinchZoom = goog.isDef(options.pinchZoom) ?
|
||||
options.pinchZoom : true;
|
||||
if (pinchZoom) {
|
||||
interactions.push(new ol.interaction.PinchZoom({
|
||||
duration: options.zoomDuration
|
||||
}));
|
||||
}
|
||||
|
||||
var keyboard = goog.isDef(options.keyboard) ?
|
||||
options.keyboard : true;
|
||||
if (keyboard) {
|
||||
|
||||
@@ -18,7 +18,7 @@ goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Drag');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
goog.require('ol.structs.RBush');
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ ol.interaction.SegmentDataType;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.ModifyOptions} options Options.
|
||||
*/
|
||||
ol.interaction.Modify = function(options) {
|
||||
@@ -126,7 +126,7 @@ ol.interaction.Modify = function(options) {
|
||||
};
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Modify, ol.interaction.Drag);
|
||||
goog.inherits(ol.interaction.Modify, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
@@ -158,7 +158,7 @@ ol.interaction.Modify.prototype.addFeature_ = function(evt) {
|
||||
if (goog.isDef(this.SEGMENT_WRITERS_[geometry.getType()])) {
|
||||
this.SEGMENT_WRITERS_[geometry.getType()].call(this, feature, geometry);
|
||||
}
|
||||
this.handleMouseAtPixel_(this.lastPixel_, this.getMap());
|
||||
this.handlePointerAtPixel_(this.lastPixel_, this.getMap());
|
||||
};
|
||||
|
||||
|
||||
@@ -368,7 +368,8 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleDragStart = function(evt) {
|
||||
ol.interaction.Modify.prototype.handlePointerDown = function(evt) {
|
||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
||||
this.dragSegments_ = [];
|
||||
var vertexFeature = this.vertexFeature_;
|
||||
if (!goog.isNull(vertexFeature)) {
|
||||
@@ -408,7 +409,7 @@ ol.interaction.Modify.prototype.handleDragStart = function(evt) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleDrag = function(evt) {
|
||||
ol.interaction.Modify.prototype.handlePointerDrag = function(evt) {
|
||||
var vertex = evt.coordinate;
|
||||
for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
||||
var dragSegment = this.dragSegments_[i];
|
||||
@@ -458,13 +459,14 @@ ol.interaction.Modify.prototype.handleDrag = function(evt) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleDragEnd = function(evt) {
|
||||
ol.interaction.Modify.prototype.handlePointerUp = function(evt) {
|
||||
var segmentData;
|
||||
for (var i = this.dragSegments_.length - 1; i >= 0; --i) {
|
||||
segmentData = this.dragSegments_[i][0];
|
||||
this.rBush_.update(ol.extent.boundingExtent(segmentData.segment),
|
||||
segmentData);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
@@ -474,12 +476,11 @@ ol.interaction.Modify.prototype.handleDragEnd = function(evt) {
|
||||
ol.interaction.Modify.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (!mapBrowserEvent.map.getView().getHints()[ol.ViewHint.INTERACTING] &&
|
||||
!this.getDragging() &&
|
||||
mapBrowserEvent.type == ol.MapBrowserEvent.EventType.MOUSEMOVE) {
|
||||
this.handleMouseMove_(mapBrowserEvent);
|
||||
mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERMOVE) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
goog.base(this, 'handleMapBrowserEvent', mapBrowserEvent);
|
||||
return !this.modifiable_;
|
||||
return (goog.base(this, 'handleMapBrowserEvent', mapBrowserEvent) &&
|
||||
!this.modifiable_);
|
||||
};
|
||||
|
||||
|
||||
@@ -487,9 +488,9 @@ ol.interaction.Modify.prototype.handleMapBrowserEvent =
|
||||
* @param {ol.MapBrowserEvent} evt Event.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) {
|
||||
ol.interaction.Modify.prototype.handlePointerMove_ = function(evt) {
|
||||
this.lastPixel_ = evt.pixel;
|
||||
this.handleMouseAtPixel_(evt.pixel, evt.map);
|
||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
||||
};
|
||||
|
||||
|
||||
@@ -498,7 +499,7 @@ ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) {
|
||||
* @param {ol.Map} map Map.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleMouseAtPixel_ = function(pixel, map) {
|
||||
ol.interaction.Modify.prototype.handlePointerAtPixel_ = function(pixel, map) {
|
||||
var pixelCoordinate = map.getCoordinateFromPixel(pixel);
|
||||
var sortByDistance = function(a, b) {
|
||||
return ol.coordinate.squaredDistanceToSegment(pixelCoordinate, a.segment) -
|
||||
|
||||
1
src/ol/interaction/pinchrotateinteraction.exports
Normal file
1
src/ol/interaction/pinchrotateinteraction.exports
Normal file
@@ -0,0 +1 @@
|
||||
@exportSymbol ol.interaction.PinchRotate
|
||||
@@ -1,18 +1,19 @@
|
||||
// FIXME works for View2D only
|
||||
|
||||
goog.provide('ol.interaction.TouchRotate');
|
||||
goog.provide('ol.interaction.PinchRotate');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.interaction.Touch');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} Animation duration.
|
||||
*/
|
||||
ol.interaction.TOUCHROTATE_ANIMATION_DURATION = 250;
|
||||
ol.interaction.ROTATE_ANIMATION_DURATION = 250;
|
||||
|
||||
|
||||
|
||||
@@ -20,11 +21,11 @@ ol.interaction.TOUCHROTATE_ANIMATION_DURATION = 250;
|
||||
* Allows the user to rotate the map by twisting with two fingers
|
||||
* on a touch screen.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Touch}
|
||||
* @param {olx.interaction.TouchRotateOptions=} opt_options Options.
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.PinchRotateOptions=} opt_options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.interaction.TouchRotate = function(opt_options) {
|
||||
ol.interaction.PinchRotate = function(opt_options) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
@@ -61,19 +62,19 @@ ol.interaction.TouchRotate = function(opt_options) {
|
||||
this.threshold_ = goog.isDef(options.threshold) ? options.threshold : 0.3;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.TouchRotate, ol.interaction.Touch);
|
||||
goog.inherits(ol.interaction.PinchRotate, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchRotate.prototype.handleTouchMove =
|
||||
ol.interaction.PinchRotate.prototype.handlePointerDrag =
|
||||
function(mapBrowserEvent) {
|
||||
goog.asserts.assert(this.targetTouches.length >= 2);
|
||||
goog.asserts.assert(this.targetPointers.length >= 2);
|
||||
var rotationDelta = 0.0;
|
||||
|
||||
var touch0 = this.targetTouches[0];
|
||||
var touch1 = this.targetTouches[1];
|
||||
var touch0 = this.targetPointers[0];
|
||||
var touch1 = this.targetPointers[1];
|
||||
|
||||
// angle between touches
|
||||
var angle = Math.atan2(
|
||||
@@ -97,7 +98,8 @@ ol.interaction.TouchRotate.prototype.handleTouchMove =
|
||||
// FIXME: should be the intersection point between the lines:
|
||||
// touch0,touch1 and previousTouch0,previousTouch1
|
||||
var viewportPosition = goog.style.getClientPosition(map.getViewport());
|
||||
var centroid = ol.interaction.Touch.centroid(this.targetTouches);
|
||||
var centroid =
|
||||
ol.interaction.Pointer.centroid(this.targetPointers);
|
||||
centroid[0] -= viewportPosition.x;
|
||||
centroid[1] -= viewportPosition.y;
|
||||
this.anchor_ = map.getCoordinateFromPixel(centroid);
|
||||
@@ -117,17 +119,19 @@ ol.interaction.TouchRotate.prototype.handleTouchMove =
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchRotate.prototype.handleTouchEnd =
|
||||
ol.interaction.PinchRotate.prototype.handlePointerUp =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.targetTouches.length < 2) {
|
||||
if (this.targetPointers.length < 2) {
|
||||
var map = mapBrowserEvent.map;
|
||||
// FIXME works for View2D only
|
||||
var view = map.getView().getView2D();
|
||||
var view2DState = view.getView2DState();
|
||||
var view = map.getView();
|
||||
view.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
if (this.rotating_) {
|
||||
// FIXME works for View2D only
|
||||
var view2D = view.getView2D();
|
||||
var view2DState = view2D.getView2DState();
|
||||
ol.interaction.Interaction.rotate(
|
||||
map, view, view2DState.rotation, this.anchor_,
|
||||
ol.interaction.TOUCHROTATE_ANIMATION_DURATION);
|
||||
map, view2D, view2DState.rotation, this.anchor_,
|
||||
ol.interaction.ROTATE_ANIMATION_DURATION);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
@@ -139,14 +143,17 @@ ol.interaction.TouchRotate.prototype.handleTouchEnd =
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchRotate.prototype.handleTouchStart =
|
||||
ol.interaction.PinchRotate.prototype.handlePointerDown =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.targetTouches.length >= 2) {
|
||||
if (this.targetPointers.length >= 2) {
|
||||
var map = mapBrowserEvent.map;
|
||||
this.anchor_ = null;
|
||||
this.lastAngle_ = undefined;
|
||||
this.rotating_ = false;
|
||||
this.rotationDelta_ = 0.0;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
map.getView().setHint(ol.ViewHint.INTERACTING, 1);
|
||||
}
|
||||
map.render();
|
||||
return true;
|
||||
} else {
|
||||
1
src/ol/interaction/pinchzoominteraction.exports
Normal file
1
src/ol/interaction/pinchzoominteraction.exports
Normal file
@@ -0,0 +1 @@
|
||||
@exportSymbol ol.interaction.PinchZoom
|
||||
@@ -1,12 +1,13 @@
|
||||
// FIXME works for View2D only
|
||||
|
||||
goog.provide('ol.interaction.TouchZoom');
|
||||
goog.provide('ol.interaction.PinchZoom');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.interaction.Touch');
|
||||
goog.require('ol.interaction.Pointer');
|
||||
|
||||
|
||||
|
||||
@@ -14,11 +15,11 @@ goog.require('ol.interaction.Touch');
|
||||
* Allows the user to zoom the map by pinching with two fingers
|
||||
* on a touch screen.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Touch}
|
||||
* @param {olx.interaction.TouchZoomOptions=} opt_options Options.
|
||||
* @extends {ol.interaction.Pointer}
|
||||
* @param {olx.interaction.PinchZoomOptions=} opt_options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.interaction.TouchZoom = function(opt_options) {
|
||||
ol.interaction.PinchZoom = function(opt_options) {
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
@@ -49,19 +50,19 @@ ol.interaction.TouchZoom = function(opt_options) {
|
||||
this.lastScaleDelta_ = 1;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.TouchZoom, ol.interaction.Touch);
|
||||
goog.inherits(ol.interaction.PinchZoom, ol.interaction.Pointer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchZoom.prototype.handleTouchMove =
|
||||
ol.interaction.PinchZoom.prototype.handlePointerDrag =
|
||||
function(mapBrowserEvent) {
|
||||
goog.asserts.assert(this.targetTouches.length >= 2);
|
||||
goog.asserts.assert(this.targetPointers.length >= 2);
|
||||
var scaleDelta = 1.0;
|
||||
|
||||
var touch0 = this.targetTouches[0];
|
||||
var touch1 = this.targetTouches[1];
|
||||
var touch0 = this.targetPointers[0];
|
||||
var touch1 = this.targetPointers[1];
|
||||
var dx = touch0.clientX - touch1.clientX;
|
||||
var dy = touch0.clientY - touch1.clientY;
|
||||
|
||||
@@ -83,7 +84,8 @@ ol.interaction.TouchZoom.prototype.handleTouchMove =
|
||||
|
||||
// scale anchor point.
|
||||
var viewportPosition = goog.style.getClientPosition(map.getViewport());
|
||||
var centroid = ol.interaction.Touch.centroid(this.targetTouches);
|
||||
var centroid =
|
||||
ol.interaction.Pointer.centroid(this.targetPointers);
|
||||
centroid[0] -= viewportPosition.x;
|
||||
centroid[1] -= viewportPosition.y;
|
||||
this.anchor_ = map.getCoordinateFromPixel(centroid);
|
||||
@@ -99,18 +101,20 @@ ol.interaction.TouchZoom.prototype.handleTouchMove =
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchZoom.prototype.handleTouchEnd =
|
||||
ol.interaction.PinchZoom.prototype.handlePointerUp =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.targetTouches.length < 2) {
|
||||
if (this.targetPointers.length < 2) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var view = map.getView();
|
||||
view.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
// FIXME works for View2D only
|
||||
var view = map.getView().getView2D();
|
||||
var view2DState = view.getView2DState();
|
||||
var view2D = view.getView2D();
|
||||
var view2DState = view2D.getView2DState();
|
||||
// Zoom to final resolution, with an animation, and provide a
|
||||
// direction not to zoom out/in if user was pinching in/out.
|
||||
// Direction is > 0 if pinching out, and < 0 if pinching in.
|
||||
var direction = this.lastScaleDelta_ - 1;
|
||||
ol.interaction.Interaction.zoom(map, view, view2DState.resolution,
|
||||
ol.interaction.Interaction.zoom(map, view2D, view2DState.resolution,
|
||||
this.anchor_, this.duration_, direction);
|
||||
return false;
|
||||
} else {
|
||||
@@ -122,13 +126,16 @@ ol.interaction.TouchZoom.prototype.handleTouchEnd =
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchZoom.prototype.handleTouchStart =
|
||||
ol.interaction.PinchZoom.prototype.handlePointerDown =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.targetTouches.length >= 2) {
|
||||
if (this.targetPointers.length >= 2) {
|
||||
var map = mapBrowserEvent.map;
|
||||
this.anchor_ = null;
|
||||
this.lastDistance_ = undefined;
|
||||
this.lastScaleDelta_ = 1;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
map.getView().setHint(ol.ViewHint.INTERACTING, 1);
|
||||
}
|
||||
map.render();
|
||||
return true;
|
||||
} else {
|
||||
166
src/ol/interaction/pointerinteraction.js
Normal file
166
src/ol/interaction/pointerinteraction.js
Normal file
@@ -0,0 +1,166 @@
|
||||
goog.provide('ol.interaction.Pointer');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.MapBrowserPointerEvent');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for pointer interactions.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Interaction}
|
||||
*/
|
||||
ol.interaction.Pointer = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @protected
|
||||
*/
|
||||
this.handlingDownUpSequence = false;
|
||||
|
||||
/**
|
||||
* @type {Object.<number, ol.pointer.PointerEvent>}
|
||||
* @private
|
||||
*/
|
||||
this.trackedPointers_ = {};
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.pointer.PointerEvent>}
|
||||
* @protected
|
||||
*/
|
||||
this.targetPointers = [];
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Pointer, ol.interaction.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.pointer.PointerEvent>} pointerEvents
|
||||
* @return {ol.Pixel} Centroid pixel.
|
||||
*/
|
||||
ol.interaction.Pointer.centroid = function(pointerEvents) {
|
||||
var length = pointerEvents.length;
|
||||
var clientX = 0;
|
||||
var clientY = 0;
|
||||
for (var i = 0; i < length; i++) {
|
||||
clientX += pointerEvents[i].clientX;
|
||||
clientY += pointerEvents[i].clientY;
|
||||
}
|
||||
return [clientX / length, clientY / length];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @return {boolean} Whether the event is a pointerdown, pointerdrag
|
||||
* or pointerup event.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.isPointerDraggingEvent_ =
|
||||
function(mapBrowserEvent) {
|
||||
var type = mapBrowserEvent.type;
|
||||
return (
|
||||
type === ol.MapBrowserEvent.EventType.POINTERDOWN ||
|
||||
type === ol.MapBrowserEvent.EventType.POINTERDRAG ||
|
||||
type === ol.MapBrowserEvent.EventType.POINTERUP);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.updateTrackedPointers_ =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.isPointerDraggingEvent_(mapBrowserEvent)) {
|
||||
var event = mapBrowserEvent.pointerEvent;
|
||||
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERUP) {
|
||||
delete this.trackedPointers_[event.pointerId];
|
||||
} else if (mapBrowserEvent.type ==
|
||||
ol.MapBrowserEvent.EventType.POINTERDOWN) {
|
||||
this.trackedPointers_[event.pointerId] = event;
|
||||
} else if (event.pointerId in this.trackedPointers_) {
|
||||
// update only when there was a pointerdown event for this pointer
|
||||
this.trackedPointers_[event.pointerId] = event;
|
||||
}
|
||||
this.targetPointers = goog.object.getValues(this.trackedPointers_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.handlePointerDrag =
|
||||
goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
* @return {boolean} Capture dragging.
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.handlePointerUp =
|
||||
goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
* @return {boolean} Capture dragging.
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.handlePointerDown =
|
||||
goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (!(mapBrowserEvent instanceof ol.MapBrowserPointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var stopEvent = false;
|
||||
this.updateTrackedPointers_(mapBrowserEvent);
|
||||
if (this.handlingDownUpSequence) {
|
||||
if (mapBrowserEvent.type ==
|
||||
ol.MapBrowserEvent.EventType.POINTERDRAG) {
|
||||
this.handlePointerDrag(mapBrowserEvent);
|
||||
} else if (mapBrowserEvent.type ==
|
||||
ol.MapBrowserEvent.EventType.POINTERUP) {
|
||||
this.handlingDownUpSequence =
|
||||
this.handlePointerUp(mapBrowserEvent);
|
||||
}
|
||||
}
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERDOWN) {
|
||||
var handled = this.handlePointerDown(mapBrowserEvent);
|
||||
this.handlingDownUpSequence = handled;
|
||||
stopEvent = this.shouldStopEvent(handled);
|
||||
}
|
||||
return !stopEvent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This method allows inheriting classes to stop the event from being
|
||||
* passed to further interactions. For example, this is required for
|
||||
* interaction `DragRotateAndZoom`.
|
||||
*
|
||||
* @protected
|
||||
* @param {boolean} handled Was the event handled by the interaction?
|
||||
* @return {boolean} Should the event be stopped?
|
||||
*/
|
||||
ol.interaction.Pointer.prototype.shouldStopEvent =
|
||||
goog.functions.FALSE;
|
||||
@@ -1,150 +0,0 @@
|
||||
goog.provide('ol.interaction.Touch');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.MapBrowserEvent');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for touch interactions.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Interaction}
|
||||
*/
|
||||
ol.interaction.Touch = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.handled_ = false;
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
this.trackedTouches_ = {};
|
||||
|
||||
/**
|
||||
* @type {Array.<Object>}
|
||||
* @protected
|
||||
*/
|
||||
this.targetTouches = [];
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.Touch, ol.interaction.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Object>} touches TouchEvents.
|
||||
* @return {ol.Pixel} Centroid pixel.
|
||||
*/
|
||||
ol.interaction.Touch.centroid = function(touches) {
|
||||
var length = touches.length;
|
||||
var clientX = 0;
|
||||
var clientY = 0;
|
||||
for (var i = 0; i < length; i++) {
|
||||
clientX += touches[i].clientX;
|
||||
clientY += touches[i].clientY;
|
||||
}
|
||||
return [clientX / length, clientY / length];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @return {boolean} Whether the event is a touchstart, touchmove
|
||||
* or touchend event.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Touch.isTouchEvent_ = function(mapBrowserEvent) {
|
||||
var type = mapBrowserEvent.type;
|
||||
return (
|
||||
type === ol.MapBrowserEvent.EventType.TOUCHSTART ||
|
||||
type === ol.MapBrowserEvent.EventType.TOUCHMOVE ||
|
||||
type === ol.MapBrowserEvent.EventType.TOUCHEND);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Touch.prototype.updateTrackedTouches_ =
|
||||
function(mapBrowserEvent) {
|
||||
if (ol.interaction.Touch.isTouchEvent_(mapBrowserEvent)) {
|
||||
var event = mapBrowserEvent.originalEvent;
|
||||
if (goog.isDef(event.targetTouches)) {
|
||||
// W3C touch events
|
||||
this.targetTouches = event.targetTouches;
|
||||
} else if (goog.isDef(event.pointerId)) {
|
||||
// IE pointer event
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHEND) {
|
||||
delete this.trackedTouches_[event.pointerId];
|
||||
} else {
|
||||
this.trackedTouches_[event.pointerId] = event;
|
||||
}
|
||||
this.targetTouches = goog.object.getValues(this.trackedTouches_);
|
||||
} else {
|
||||
goog.asserts.fail('unknown touch event model');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
ol.interaction.Touch.prototype.handleTouchMove = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
* @return {boolean} Capture dragging.
|
||||
*/
|
||||
ol.interaction.Touch.prototype.handleTouchEnd = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
* @return {boolean} Capture dragging.
|
||||
*/
|
||||
ol.interaction.Touch.prototype.handleTouchStart = goog.functions.FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Touch.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
var view = mapBrowserEvent.map.getView();
|
||||
this.updateTrackedTouches_(mapBrowserEvent);
|
||||
if (this.handled_) {
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHMOVE) {
|
||||
this.handleTouchMove(mapBrowserEvent);
|
||||
} else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHEND) {
|
||||
this.handled_ = this.handleTouchEnd(mapBrowserEvent);
|
||||
if (!this.handled_) {
|
||||
view.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.TOUCHSTART) {
|
||||
var handled = this.handleTouchStart(mapBrowserEvent);
|
||||
if (!this.handled_ && handled) {
|
||||
view.setHint(ol.ViewHint.INTERACTING, 1);
|
||||
}
|
||||
this.handled_ = handled;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
@exportSymbol ol.interaction.TouchPan
|
||||
@@ -1,142 +0,0 @@
|
||||
// FIXME works for View2D only
|
||||
goog.provide('ol.interaction.TouchPan');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Kinetic');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.PreRenderFunction');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.coordinate');
|
||||
goog.require('ol.interaction.Touch');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows the user to pan the map by touching and dragging
|
||||
* on a touch screen.
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Touch}
|
||||
* @param {olx.interaction.TouchPanOptions=} opt_options Options.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.interaction.TouchPan = function(opt_options) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Kinetic|undefined}
|
||||
*/
|
||||
this.kinetic_ = options.kinetic;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?ol.PreRenderFunction}
|
||||
*/
|
||||
this.kineticPreRenderFn_ = null;
|
||||
|
||||
/**
|
||||
* @type {ol.Pixel}
|
||||
*/
|
||||
this.lastCentroid = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.noKinetic_ = false;
|
||||
|
||||
};
|
||||
goog.inherits(ol.interaction.TouchPan, ol.interaction.Touch);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchPan.prototype.handleTouchMove = function(mapBrowserEvent) {
|
||||
goog.asserts.assert(this.targetTouches.length >= 1);
|
||||
var centroid = ol.interaction.Touch.centroid(this.targetTouches);
|
||||
if (!goog.isNull(this.lastCentroid)) {
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.update(centroid[0], centroid[1]);
|
||||
}
|
||||
var deltaX = this.lastCentroid[0] - centroid[0];
|
||||
var deltaY = centroid[1] - this.lastCentroid[1];
|
||||
var map = mapBrowserEvent.map;
|
||||
var view2D = map.getView().getView2D();
|
||||
goog.asserts.assertInstanceof(view2D, ol.View2D);
|
||||
var view2DState = view2D.getView2DState();
|
||||
var center = [deltaX, deltaY];
|
||||
ol.coordinate.scale(center, view2DState.resolution);
|
||||
ol.coordinate.rotate(center, view2DState.rotation);
|
||||
ol.coordinate.add(center, view2DState.center);
|
||||
center = view2D.constrainCenter(center);
|
||||
map.render();
|
||||
view2D.setCenter(center);
|
||||
}
|
||||
this.lastCentroid = centroid;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchPan.prototype.handleTouchEnd =
|
||||
function(mapBrowserEvent) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var view2D = map.getView().getView2D();
|
||||
goog.asserts.assertInstanceof(view2D, ol.View2D);
|
||||
if (this.targetTouches.length === 0) {
|
||||
if (!this.noKinetic_ && this.kinetic_ && this.kinetic_.end()) {
|
||||
var distance = this.kinetic_.getDistance();
|
||||
var angle = this.kinetic_.getAngle();
|
||||
var center = view2D.getCenter();
|
||||
goog.asserts.assert(goog.isDef(center));
|
||||
this.kineticPreRenderFn_ = this.kinetic_.pan(center);
|
||||
map.beforeRender(this.kineticPreRenderFn_);
|
||||
var centerpx = map.getPixelFromCoordinate(center);
|
||||
var dest = map.getCoordinateFromPixel([
|
||||
centerpx[0] - distance * Math.cos(angle),
|
||||
centerpx[1] - distance * Math.sin(angle)
|
||||
]);
|
||||
dest = view2D.constrainCenter(dest);
|
||||
view2D.setCenter(dest);
|
||||
}
|
||||
map.render();
|
||||
return false;
|
||||
} else {
|
||||
this.lastCentroid = null;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.TouchPan.prototype.handleTouchStart =
|
||||
function(mapBrowserEvent) {
|
||||
if (this.targetTouches.length > 0) {
|
||||
var map = mapBrowserEvent.map;
|
||||
var view2D = map.getView().getView2D();
|
||||
goog.asserts.assertInstanceof(view2D, ol.View2D);
|
||||
this.lastCentroid = null;
|
||||
map.render();
|
||||
if (!goog.isNull(this.kineticPreRenderFn_) &&
|
||||
map.removePreRenderFunction(this.kineticPreRenderFn_)) {
|
||||
view2D.setCenter(mapBrowserEvent.frameState.view2DState.center);
|
||||
this.kineticPreRenderFn_ = null;
|
||||
}
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.begin();
|
||||
}
|
||||
// No kinetic as soon as more than one fingers on the screen is
|
||||
// detected. This is to prevent nasty pans after pinch.
|
||||
this.noKinetic_ = this.targetTouches.length > 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
@exportSymbol ol.interaction.TouchRotate
|
||||
@@ -1 +0,0 @@
|
||||
@exportSymbol ol.interaction.TouchZoom
|
||||
@@ -261,7 +261,8 @@ ol.Map = function(options) {
|
||||
goog.events.EventType.DBLCLICK,
|
||||
goog.events.EventType.MOUSEDOWN,
|
||||
goog.events.EventType.TOUCHSTART,
|
||||
goog.events.EventType.MSPOINTERDOWN
|
||||
goog.events.EventType.MSPOINTERDOWN,
|
||||
'pointerdown'
|
||||
], goog.events.Event.stopPropagation);
|
||||
goog.dom.appendChild(this.viewport_, this.overlayContainerStopEvent_);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
goog.provide('ol.MapBrowserEvent');
|
||||
goog.provide('ol.MapBrowserEvent.EventType');
|
||||
goog.provide('ol.MapBrowserEventHandler');
|
||||
goog.provide('ol.MapBrowserPointerEvent');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
@@ -12,6 +13,8 @@ goog.require('goog.object');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.MapEvent');
|
||||
goog.require('ol.Pixel');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
goog.require('ol.pointer.PointerEventHandler');
|
||||
|
||||
|
||||
|
||||
@@ -80,6 +83,30 @@ ol.MapBrowserEvent.prototype.stopPropagation = function() {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.MapBrowserEvent}
|
||||
* @param {string} type Event type.
|
||||
* @param {ol.Map} map Map.
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @param {?oli.FrameState=} opt_frameState Frame state.
|
||||
* @todo stability experimental
|
||||
*/
|
||||
ol.MapBrowserPointerEvent = function(type, map, pointerEvent, opt_frameState) {
|
||||
|
||||
goog.base(this, type, map, pointerEvent.browserEvent, opt_frameState);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.pointer.PointerEvent}
|
||||
*/
|
||||
this.pointerEvent = pointerEvent;
|
||||
|
||||
};
|
||||
goog.inherits(ol.MapBrowserPointerEvent, ol.MapBrowserEvent);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map The map with the viewport to listen to events on.
|
||||
* @constructor
|
||||
@@ -114,24 +141,12 @@ ol.MapBrowserEventHandler = function(map) {
|
||||
*/
|
||||
this.dragListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @type {goog.events.Key}
|
||||
* @private
|
||||
*/
|
||||
this.mousedownListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @type {goog.events.Key}
|
||||
* @private
|
||||
*/
|
||||
this.pointerdownListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @type {goog.events.Key}
|
||||
* @private
|
||||
*/
|
||||
this.touchstartListenerKey_ = null;
|
||||
|
||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
||||
/**
|
||||
* @type {goog.events.Key}
|
||||
@@ -141,46 +156,69 @@ ol.MapBrowserEventHandler = function(map) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {goog.events.BrowserEvent}
|
||||
* @type {ol.pointer.PointerEvent}
|
||||
* @private
|
||||
*/
|
||||
this.down_ = null;
|
||||
|
||||
var element = this.map_.getViewport();
|
||||
|
||||
this.relayedListenerKeys_ = [
|
||||
goog.events.listen(element,
|
||||
goog.events.EventType.MOUSEMOVE,
|
||||
this.relayEvent_, false, this),
|
||||
goog.events.listen(element,
|
||||
goog.events.EventType.CLICK,
|
||||
this.relayEvent_, false, this)
|
||||
];
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.activePointers_ = 0;
|
||||
|
||||
this.mousedownListenerKey_ = goog.events.listen(element,
|
||||
goog.events.EventType.MOUSEDOWN,
|
||||
this.handleMouseDown_, false, this);
|
||||
/**
|
||||
* @type {Object.<number, boolean>}
|
||||
* @private
|
||||
*/
|
||||
this.trackedTouches_ = {};
|
||||
|
||||
this.pointerdownListenerKey_ = goog.events.listen(element,
|
||||
goog.events.EventType.MSPOINTERDOWN,
|
||||
/**
|
||||
* Event handler which generates pointer events for
|
||||
* the viewport element.
|
||||
*
|
||||
* @type {ol.pointer.PointerEventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.pointerEventHandler_ = new ol.pointer.PointerEventHandler(element);
|
||||
|
||||
/**
|
||||
* Event handler which generates pointer events for
|
||||
* the document (used when dragging).
|
||||
*
|
||||
* @type {ol.pointer.PointerEventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.documentPointerEventHandler_ = null;
|
||||
|
||||
this.pointerdownListenerKey_ = goog.events.listen(this.pointerEventHandler_,
|
||||
ol.pointer.EventType.POINTERDOWN,
|
||||
this.handlePointerDown_, false, this);
|
||||
|
||||
this.touchstartListenerKey_ = goog.events.listen(element,
|
||||
goog.events.EventType.TOUCHSTART,
|
||||
this.handleTouchStart_, false, this);
|
||||
this.relayedListenerKey_ = goog.events.listen(this.pointerEventHandler_,
|
||||
ol.pointer.EventType.POINTERMOVE,
|
||||
this.relayEvent_, false, this);
|
||||
|
||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
||||
/*
|
||||
* On legacy IE, double clicks do not produce two mousedown and
|
||||
* mouseup events. That is why a separate DBLCLICK event listener
|
||||
* is used.
|
||||
*/
|
||||
this.ieDblclickListenerKey_ = goog.events.listen(element,
|
||||
goog.events.EventType.DBLCLICK, this.emulateClick_, false, this);
|
||||
goog.events.EventType.DBLCLICK,
|
||||
this.emulateClickLegacyIE_, false, this);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Get the last "down" type event. This will be set on mousedown,
|
||||
* touchstart, and pointerdown.
|
||||
* @return {goog.events.BrowserEvent} The most recent "down" type event (or null
|
||||
* Get the last "down" type event. This will be set on pointerdown.
|
||||
* @return {ol.pointer.PointerEvent} The most recent "down" type event (or null
|
||||
* if none have occurred).
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.getDown = function() {
|
||||
@@ -189,291 +227,224 @@ ol.MapBrowserEventHandler.prototype.getDown = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {goog.events.BrowserEvent} browserEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) {
|
||||
ol.MapBrowserEventHandler.prototype.emulateClickLegacyIE_ =
|
||||
function(browserEvent) {
|
||||
var pointerEvent = this.pointerEventHandler_.wrapMouseEvent(
|
||||
ol.MapBrowserEvent.EventType.POINTERUP,
|
||||
browserEvent
|
||||
);
|
||||
this.emulateClick_(pointerEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
|
||||
if (this.clickTimeoutId_ !== 0) {
|
||||
// double-click
|
||||
goog.global.clearTimeout(this.clickTimeoutId_);
|
||||
this.clickTimeoutId_ = 0;
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent);
|
||||
var newEvent = new ol.MapBrowserPointerEvent(
|
||||
ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
} else {
|
||||
// click
|
||||
|
||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
||||
// In IE 7-8, referring to the original event object after the current
|
||||
// call stack causes "member not found" exceptions, such as in the timeout
|
||||
// we use here.
|
||||
var ev = /** @type {Event} */ (
|
||||
goog.object.clone(browserEvent.getBrowserEvent()));
|
||||
this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
|
||||
this.clickTimeoutId_ = 0;
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_,
|
||||
new goog.events.BrowserEvent(ev, browserEvent.currentTarget));
|
||||
this.dispatchEvent(newEvent);
|
||||
}, this), 250);
|
||||
} else {
|
||||
this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
|
||||
this.clickTimeoutId_ = 0;
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
}, this), 250);
|
||||
}
|
||||
this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
|
||||
this.clickTimeoutId_ = 0;
|
||||
var newEvent = new ol.MapBrowserPointerEvent(
|
||||
ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
}, this), 250);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* Keeps track on how many pointers are currently active.
|
||||
*
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handleMouseUp_ = function(browserEvent) {
|
||||
if (this.down_) {
|
||||
ol.MapBrowserEventHandler.prototype.updateActivePointers_ =
|
||||
function(pointerEvent) {
|
||||
var event = pointerEvent;
|
||||
|
||||
if (event.type == ol.MapBrowserEvent.EventType.POINTERUP ||
|
||||
event.type == ol.MapBrowserEvent.EventType.POINTERCANCEL) {
|
||||
delete this.trackedTouches_[event.pointerId];
|
||||
} else if (event.type == ol.MapBrowserEvent.EventType.POINTERDOWN) {
|
||||
this.trackedTouches_[event.pointerId] = true;
|
||||
}
|
||||
this.activePointers_ = goog.object.getCount(this.trackedTouches_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
|
||||
this.updateActivePointers_(pointerEvent);
|
||||
var newEvent = new ol.MapBrowserPointerEvent(
|
||||
ol.MapBrowserEvent.EventType.POINTERUP, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
goog.asserts.assert(this.activePointers_ >= 0);
|
||||
if (this.activePointers_ === 0) {
|
||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
||||
this.dragListenerKeys_ = null;
|
||||
if (this.dragged_) {
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.DRAGEND, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
} else if (browserEvent.isMouseActionButton()) {
|
||||
this.emulateClick_(browserEvent);
|
||||
}
|
||||
goog.dispose(this.documentPointerEventHandler_);
|
||||
this.documentPointerEventHandler_ = null;
|
||||
}
|
||||
|
||||
// We emulate click event on left mouse button click, touch contact, and pen
|
||||
// contact. isMouseActionButton returns true in these cases (evt.button is set
|
||||
// to 0).
|
||||
// See http://www.w3.org/TR/pointerevents/#button-states
|
||||
if (!this.dragged_ && this.isMouseActionButton_(pointerEvent)) {
|
||||
goog.asserts.assert(!goog.isNull(this.down_));
|
||||
this.emulateClick_(this.down_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @return {boolean} If the left mouse button was pressed.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handleMouseDown_ = function(browserEvent) {
|
||||
if (!goog.isNull(this.pointerdownListenerKey_)) {
|
||||
// mouse device detected - unregister the pointerdown and touchstart
|
||||
// listeners
|
||||
goog.events.unlistenByKey(this.pointerdownListenerKey_);
|
||||
this.pointerdownListenerKey_ = null;
|
||||
|
||||
goog.asserts.assert(!goog.isNull(this.touchstartListenerKey_));
|
||||
goog.events.unlistenByKey(this.touchstartListenerKey_);
|
||||
this.touchstartListenerKey_ = null;
|
||||
ol.MapBrowserEventHandler.prototype.isMouseActionButton_ =
|
||||
function(pointerEvent) {
|
||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
|
||||
return pointerEvent.button == 1;
|
||||
} else {
|
||||
return pointerEvent.button == 0;
|
||||
}
|
||||
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
this.down_ = browserEvent;
|
||||
this.dragged_ = false;
|
||||
this.dragListenerKeys_ = [
|
||||
goog.events.listen(goog.global.document, goog.events.EventType.MOUSEMOVE,
|
||||
this.handleMouseMove_, false, this),
|
||||
goog.events.listen(goog.global.document, goog.events.EventType.MOUSEUP,
|
||||
this.handleMouseUp_, false, this)
|
||||
];
|
||||
// prevent browser image dragging with the dom renderer
|
||||
browserEvent.preventDefault();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) {
|
||||
var newEvent;
|
||||
if (!this.dragged_) {
|
||||
this.dragged_ = true;
|
||||
newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.DRAGSTART, this.map_, this.down_);
|
||||
this.dispatchEvent(newEvent);
|
||||
}
|
||||
newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.DRAG, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
|
||||
function(browserEvent) {
|
||||
if (!goog.isNull(this.mousedownListenerKey_)) {
|
||||
// pointer device detected - unregister the mousedown and touchstart
|
||||
// listeners
|
||||
goog.events.unlistenByKey(this.mousedownListenerKey_);
|
||||
this.mousedownListenerKey_ = null;
|
||||
|
||||
goog.asserts.assert(!goog.isNull(this.touchstartListenerKey_));
|
||||
goog.events.unlistenByKey(this.touchstartListenerKey_);
|
||||
this.touchstartListenerKey_ = null;
|
||||
}
|
||||
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent);
|
||||
function(pointerEvent) {
|
||||
this.updateActivePointers_(pointerEvent);
|
||||
var newEvent = new ol.MapBrowserPointerEvent(
|
||||
ol.MapBrowserEvent.EventType.POINTERDOWN, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
this.down_ = browserEvent;
|
||||
this.down_ = pointerEvent;
|
||||
this.dragged_ = false;
|
||||
this.dragListenerKeys_ = [
|
||||
goog.events.listen(goog.global.document,
|
||||
goog.events.EventType.MSPOINTERMOVE,
|
||||
this.handlePointerMove_, false, this),
|
||||
goog.events.listen(goog.global.document, goog.events.EventType.MSPOINTERUP,
|
||||
this.handlePointerUp_, false, this)
|
||||
];
|
||||
|
||||
if (goog.isNull(this.dragListenerKeys_)) {
|
||||
/* Set up a pointer event handler on the `document`,
|
||||
* which is required when the pointer is moved outside
|
||||
* the viewport when dragging.
|
||||
*/
|
||||
this.documentPointerEventHandler_ =
|
||||
new ol.pointer.PointerEventHandler(document);
|
||||
|
||||
this.dragListenerKeys_ = [
|
||||
goog.events.listen(this.documentPointerEventHandler_,
|
||||
ol.MapBrowserEvent.EventType.POINTERMOVE,
|
||||
this.handlePointerMove_, false, this),
|
||||
goog.events.listen(this.documentPointerEventHandler_,
|
||||
ol.MapBrowserEvent.EventType.POINTERUP,
|
||||
this.handlePointerUp_, false, this),
|
||||
/* Note that the listener for `pointercancel is set up on
|
||||
* `pointerEventHandler_` and not `documentPointerEventHandler_` like
|
||||
* the `pointerup` and `pointermove` listeners.
|
||||
*
|
||||
* The reason for this is the following: `TouchSource.vacuumTouches_()`
|
||||
* issues `pointercancel` events, when there was no `touchend` for a
|
||||
* `touchstart`. Now, let's say a first `touchstart` is registered on
|
||||
* `pointerEventHandler_`. The `documentPointerEventHandler_` is set up.
|
||||
* But `documentPointerEventHandler_` doesn't know about the first
|
||||
* `touchstart`. If there is no `touchend` for the `touchstart`, we can
|
||||
* only receive a `touchcancel` from `pointerEventHandler_`, because it is
|
||||
* only registered there.
|
||||
*/
|
||||
goog.events.listen(this.pointerEventHandler_,
|
||||
ol.MapBrowserEvent.EventType.POINTERCANCEL,
|
||||
this.handlePointerUp_, false, this)
|
||||
];
|
||||
}
|
||||
|
||||
// FIXME check if/when this is necessary
|
||||
// prevent context menu
|
||||
browserEvent.preventDefault();
|
||||
pointerEvent.preventDefault();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
|
||||
function(browserEvent) {
|
||||
function(pointerEvent) {
|
||||
// Fix IE10 on windows Surface : When you tap the tablet, it triggers
|
||||
// multiple pointermove events between pointerdown and pointerup with
|
||||
// the exact same coordinates of the pointerdown event. To avoid a
|
||||
// 'false' touchmove event to be dispatched , we test if the pointer
|
||||
// effectively moved.
|
||||
if (browserEvent.clientX != this.down_.clientX ||
|
||||
browserEvent.clientY != this.down_.clientY) {
|
||||
if (pointerEvent.clientX != this.down_.clientX ||
|
||||
pointerEvent.clientY != this.down_.clientY) {
|
||||
this.dragged_ = true;
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent);
|
||||
var newEvent = new ol.MapBrowserPointerEvent(
|
||||
ol.MapBrowserEvent.EventType.POINTERDRAG, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
||||
|
||||
// We emulate click event on left mouse button click, touch contact, and pen
|
||||
// contact. isMouseActionButton returns true in these cases (evt.button is set
|
||||
// to 0).
|
||||
// See http://www.w3.org/TR/pointerevents/#button-states .
|
||||
if (!this.dragged_ && browserEvent.isMouseActionButton()) {
|
||||
goog.asserts.assert(!goog.isNull(this.down_));
|
||||
this.emulateClick_(this.down_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handleTouchStart_ = function(browserEvent) {
|
||||
if (!goog.isNull(this.mousedownListenerKey_)) {
|
||||
// touch device detected - unregister the mousedown and pointerdown
|
||||
// listeners
|
||||
goog.events.unlistenByKey(this.mousedownListenerKey_);
|
||||
this.mousedownListenerKey_ = null;
|
||||
|
||||
goog.asserts.assert(!goog.isNull(this.pointerdownListenerKey_));
|
||||
goog.events.unlistenByKey(this.pointerdownListenerKey_);
|
||||
this.pointerdownListenerKey_ = null;
|
||||
}
|
||||
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
this.down_ = browserEvent;
|
||||
this.dragged_ = false;
|
||||
|
||||
if (goog.isNull(this.dragListenerKeys_)) {
|
||||
this.dragListenerKeys_ = [
|
||||
goog.events.listen(goog.global.document, goog.events.EventType.TOUCHMOVE,
|
||||
this.handleTouchMove_, false, this),
|
||||
goog.events.listen(goog.global.document, goog.events.EventType.TOUCHEND,
|
||||
this.handleTouchEnd_, false, this)
|
||||
];
|
||||
}
|
||||
|
||||
// FIXME check if/when this is necessary
|
||||
browserEvent.preventDefault();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handleTouchMove_ = function(browserEvent) {
|
||||
this.dragged_ = true;
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
// Some native android browser triggers mousemove events during small period
|
||||
// of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
|
||||
// https://code.google.com/p/android/issues/detail?id=19827
|
||||
// ex: Galaxy Tab P3110 + Android 4.1.1
|
||||
browserEvent.preventDefault();
|
||||
pointerEvent.preventDefault();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* Wrap and relay a pointer event. Note that this requires that the type
|
||||
* string for the MapBrowserPointerEvent matches the PointerEvent type.
|
||||
* @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) {
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
if (browserEvent.getBrowserEvent().targetTouches.length === 0) {
|
||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
||||
this.dragListenerKeys_ = null;
|
||||
}
|
||||
if (!this.dragged_) {
|
||||
goog.asserts.assert(!goog.isNull(this.down_));
|
||||
this.emulateClick_(this.down_);
|
||||
}
|
||||
ol.MapBrowserEventHandler.prototype.relayEvent_ = function(pointerEvent) {
|
||||
this.dispatchEvent(new ol.MapBrowserPointerEvent(
|
||||
pointerEvent.type, this.map_, pointerEvent));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME empty description for jsdoc
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
|
||||
if (!goog.isNull(this.relayedListenerKeys_)) {
|
||||
goog.array.forEach(this.relayedListenerKeys_, goog.events.unlistenByKey);
|
||||
this.relayedListenerKeys_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.mousedownListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.mousedownListenerKey_);
|
||||
this.mousedownListenerKey_ = null;
|
||||
if (!goog.isNull(this.relayedListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.relayedListenerKey_);
|
||||
this.relayedListenerKey_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.pointerdownListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.pointerdownListenerKey_);
|
||||
this.pointerdownListenerKey_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.touchstartListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.touchstartListenerKey_);
|
||||
this.touchstartListenerKey_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.dragListenerKeys_)) {
|
||||
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
|
||||
this.dragListenerKeys_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.documentPointerEventHandler_)) {
|
||||
goog.dispose(this.documentPointerEventHandler_);
|
||||
this.documentPointerEventHandler_ = null;
|
||||
}
|
||||
if (!goog.isNull(this.pointerEventHandler_)) {
|
||||
goog.dispose(this.pointerEventHandler_);
|
||||
this.pointerEventHandler_ = null;
|
||||
}
|
||||
if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE &&
|
||||
!goog.isNull(this.ieDblclickListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.ieDblclickListenerKey_);
|
||||
@@ -483,32 +454,23 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wrap and relay a browser event. Note that this requires that the type
|
||||
* string for the MapBrowserEvent matches the BrowserEvent type.
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.relayEvent_ = function(browserEvent) {
|
||||
this.dispatchEvent(new ol.MapBrowserEvent(
|
||||
browserEvent.type, this.map_, browserEvent));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constants for event names.
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.MapBrowserEvent.EventType = {
|
||||
CLICK: goog.events.EventType.CLICK,
|
||||
DBLCLICK: goog.events.EventType.DBLCLICK,
|
||||
MOUSEMOVE: goog.events.EventType.MOUSEMOVE,
|
||||
DOWN: 'down',
|
||||
DRAGSTART: 'dragstart',
|
||||
DRAG: 'drag',
|
||||
DRAGEND: 'dragend',
|
||||
// derived event types
|
||||
SINGLECLICK: 'singleclick',
|
||||
TOUCHSTART: goog.events.EventType.TOUCHSTART,
|
||||
TOUCHMOVE: goog.events.EventType.TOUCHMOVE,
|
||||
TOUCHEND: goog.events.EventType.TOUCHEND
|
||||
DBLCLICK: goog.events.EventType.DBLCLICK,
|
||||
POINTERDRAG: 'pointerdrag',
|
||||
|
||||
// original pointer event types
|
||||
POINTERMOVE: 'pointermove',
|
||||
POINTERDOWN: 'pointerdown',
|
||||
POINTERUP: 'pointerup',
|
||||
POINTEROVER: 'pointerover',
|
||||
POINTEROUT: 'pointerout',
|
||||
POINTERENTER: 'pointerenter',
|
||||
POINTERLEAVE: 'pointerleave',
|
||||
POINTERCANCEL: 'pointercancel'
|
||||
};
|
||||
|
||||
55
src/ol/pointer/eventsource.js
Normal file
55
src/ol/pointer/eventsource.js
Normal file
@@ -0,0 +1,55 @@
|
||||
goog.provide('ol.pointer.EventSource');
|
||||
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||
* @param {Object.<string, function(goog.events.BrowserEvent)>} mapping
|
||||
* @constructor
|
||||
*/
|
||||
ol.pointer.EventSource = function(dispatcher, mapping) {
|
||||
/**
|
||||
* @type {ol.pointer.PointerEventHandler}
|
||||
*/
|
||||
this.dispatcher = dispatcher;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @const
|
||||
* @type {Object.<string, function(goog.events.BrowserEvent)>}
|
||||
*/
|
||||
this.mapping_ = mapping;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* List of events supported by this source.
|
||||
* @return {Array.<string>} Event names
|
||||
*/
|
||||
ol.pointer.EventSource.prototype.getEvents = function() {
|
||||
return goog.object.getKeys(this.mapping_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a mapping between the supported event types and
|
||||
* the handlers that should handle an event.
|
||||
* @return {Object.<string, function(goog.events.BrowserEvent)>}
|
||||
* Event/Handler mapping
|
||||
*/
|
||||
ol.pointer.EventSource.prototype.getMapping = function() {
|
||||
return this.mapping_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the handler that should handle a given event type.
|
||||
* @param {string} eventType
|
||||
* @return {function(goog.events.BrowserEvent)} Handler
|
||||
*/
|
||||
ol.pointer.EventSource.prototype.getHandlerForEvent = function(eventType) {
|
||||
return this.mapping_[eventType];
|
||||
};
|
||||
255
src/ol/pointer/mousesource.js
Normal file
255
src/ol/pointer/mousesource.js
Normal file
@@ -0,0 +1,255 @@
|
||||
// Based on https://github.com/Polymer/PointerEvents
|
||||
|
||||
// Copyright (c) 2013 The Polymer Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.pointer.MouseSource');
|
||||
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.pointer.EventSource');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||
* @constructor
|
||||
* @extends {ol.pointer.EventSource}
|
||||
*/
|
||||
ol.pointer.MouseSource = function(dispatcher) {
|
||||
var mapping = {
|
||||
'mousedown': this.mousedown,
|
||||
'mousemove': this.mousemove,
|
||||
'mouseup': this.mouseup,
|
||||
'mouseover': this.mouseover,
|
||||
'mouseout': this.mouseout
|
||||
};
|
||||
goog.base(this, dispatcher, mapping);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, goog.events.BrowserEvent|Object>}
|
||||
*/
|
||||
this.pointerMap = dispatcher.pointerMap;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<goog.math.Coordinate>}
|
||||
*/
|
||||
this.lastTouches = [];
|
||||
};
|
||||
goog.inherits(ol.pointer.MouseSource, ol.pointer.EventSource);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.pointer.MouseSource.POINTER_ID = 1;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.pointer.MouseSource.POINTER_TYPE = 'mouse';
|
||||
|
||||
|
||||
/**
|
||||
* Radius around touchend that swallows mouse events.
|
||||
*
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.pointer.MouseSource.DEDUP_DIST = 25;
|
||||
|
||||
|
||||
/**
|
||||
* Detect if a mouse event was simulated from a touch by
|
||||
* checking if previously there was a touch event at the
|
||||
* same position.
|
||||
*
|
||||
* FIXME - Known problem with the native Android browser on
|
||||
* Samsung GT-I9100 (Android 4.1.2):
|
||||
* In case the page is scrolled, this function does not work
|
||||
* correctly when a canvas is used (WebGL or canvas renderer).
|
||||
* Mouse listeners on canvas elements (for this browser), create
|
||||
* two mouse events: One 'good' and one 'bad' one (on other browsers or
|
||||
* when a div is used, there is only one event). For the 'bad' one,
|
||||
* clientX/clientY and also pageX/pageY are wrong when the page
|
||||
* is scrolled. Because of that, this function can not detect if
|
||||
* the events were simulated from a touch event. As result, a
|
||||
* pointer event at a wrong position is dispatched, which confuses
|
||||
* the map interactions.
|
||||
* It is unclear, how one can get the correct position for the event
|
||||
* or detect that the positions are invalid.
|
||||
*
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
* @return {boolean} True, if the event was generated by a touch.
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ =
|
||||
function(inEvent) {
|
||||
var lts = this.lastTouches;
|
||||
var x = inEvent.clientX, y = inEvent.clientY;
|
||||
for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {
|
||||
// simulated mouse events will be swallowed near a primary touchend
|
||||
var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
|
||||
if (dx <= ol.pointer.MouseSource.DEDUP_DIST &&
|
||||
dy <= ol.pointer.MouseSource.DEDUP_DIST) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a copy of the original event that will be used
|
||||
* for the fake pointer event.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||
* @return {Object}
|
||||
*/
|
||||
ol.pointer.MouseSource.prepareEvent = function(inEvent, dispatcher) {
|
||||
var e = dispatcher.cloneEvent(inEvent, inEvent.getBrowserEvent());
|
||||
|
||||
// forward mouse preventDefault
|
||||
var pd = e.preventDefault;
|
||||
e.preventDefault = function() {
|
||||
inEvent.preventDefault();
|
||||
pd();
|
||||
};
|
||||
|
||||
e.pointerId = ol.pointer.MouseSource.POINTER_ID;
|
||||
e.isPrimary = true;
|
||||
e.pointerType = ol.pointer.MouseSource.POINTER_TYPE;
|
||||
|
||||
return e;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `mousedown`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
|
||||
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||
var p = goog.object.containsKey(this.pointerMap,
|
||||
ol.pointer.MouseSource.POINTER_ID.toString());
|
||||
// TODO(dfreedman) workaround for some elements not sending mouseup
|
||||
// http://crbug/149091
|
||||
if (p) {
|
||||
this.cancel(inEvent);
|
||||
}
|
||||
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
|
||||
goog.object.set(this.pointerMap,
|
||||
ol.pointer.MouseSource.POINTER_ID.toString(), inEvent);
|
||||
this.dispatcher.down(e, inEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `mousemove`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.mousemove = function(inEvent) {
|
||||
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
|
||||
this.dispatcher.move(e, inEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `mouseup`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
|
||||
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||
var p = goog.object.get(this.pointerMap,
|
||||
ol.pointer.MouseSource.POINTER_ID.toString());
|
||||
|
||||
if (p && p.button === inEvent.button) {
|
||||
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
|
||||
this.dispatcher.up(e, inEvent);
|
||||
this.cleanupMouse();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `mouseover`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
|
||||
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
|
||||
this.dispatcher.enterOver(e, inEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `mouseout`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
|
||||
if (!this.isEventSimulatedFromTouch_(inEvent)) {
|
||||
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
|
||||
this.dispatcher.leaveOut(e, inEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches a `pointercancel` event.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.cancel = function(inEvent) {
|
||||
var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
|
||||
this.dispatcher.cancel(e, inEvent);
|
||||
this.cleanupMouse();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the mouse from the list of active pointers.
|
||||
*/
|
||||
ol.pointer.MouseSource.prototype.cleanupMouse = function() {
|
||||
goog.object.remove(this.pointerMap,
|
||||
ol.pointer.MouseSource.POINTER_ID.toString());
|
||||
};
|
||||
196
src/ol/pointer/mssource.js
Normal file
196
src/ol/pointer/mssource.js
Normal file
@@ -0,0 +1,196 @@
|
||||
// Based on https://github.com/Polymer/PointerEvents
|
||||
|
||||
// Copyright (c) 2013 The Polymer Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.pointer.MsSource');
|
||||
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.pointer.EventSource');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||
* @constructor
|
||||
* @extends {ol.pointer.EventSource}
|
||||
*/
|
||||
ol.pointer.MsSource = function(dispatcher) {
|
||||
var mapping = {
|
||||
'MSPointerDown': this.msPointerDown,
|
||||
'MSPointerMove': this.msPointerMove,
|
||||
'MSPointerUp': this.msPointerUp,
|
||||
'MSPointerOut': this.msPointerOut,
|
||||
'MSPointerOver': this.msPointerOver,
|
||||
'MSPointerCancel': this.msPointerCancel,
|
||||
'MSGotPointerCapture': this.msGotPointerCapture,
|
||||
'MSLostPointerCapture': this.msLostPointerCapture
|
||||
};
|
||||
goog.base(this, dispatcher, mapping);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, goog.events.BrowserEvent|Object>}
|
||||
*/
|
||||
this.pointerMap = dispatcher.pointerMap;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array.<string>}
|
||||
*/
|
||||
this.POINTER_TYPES = [
|
||||
'',
|
||||
'unavailable',
|
||||
'touch',
|
||||
'pen',
|
||||
'mouse'
|
||||
];
|
||||
};
|
||||
goog.inherits(ol.pointer.MsSource, ol.pointer.EventSource);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a copy of the original event that will be used
|
||||
* for the fake pointer event.
|
||||
*
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
* @return {Object}
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.prepareEvent_ = function(inEvent) {
|
||||
var e = inEvent;
|
||||
if (goog.isNumber(inEvent.getBrowserEvent().pointerType)) {
|
||||
e = this.dispatcher.cloneEvent(inEvent, inEvent.getBrowserEvent());
|
||||
e.pointerType = this.POINTER_TYPES[inEvent.getBrowserEvent().pointerType];
|
||||
}
|
||||
|
||||
return e;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove this pointer from the list of active pointers.
|
||||
* @param {number} pointerId
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.cleanup = function(pointerId) {
|
||||
goog.object.remove(this.pointerMap, pointerId);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msPointerDown`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msPointerDown = function(inEvent) {
|
||||
goog.object.set(this.pointerMap,
|
||||
inEvent.getBrowserEvent().pointerId, inEvent);
|
||||
var e = this.prepareEvent_(inEvent);
|
||||
this.dispatcher.down(e, inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msPointerMove`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msPointerMove = function(inEvent) {
|
||||
var e = this.prepareEvent_(inEvent);
|
||||
this.dispatcher.move(e, inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msPointerUp`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msPointerUp = function(inEvent) {
|
||||
var e = this.prepareEvent_(inEvent);
|
||||
this.dispatcher.up(e, inEvent);
|
||||
this.cleanup(inEvent.getBrowserEvent().pointerId);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msPointerOut`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msPointerOut = function(inEvent) {
|
||||
var e = this.prepareEvent_(inEvent);
|
||||
this.dispatcher.leaveOut(e, inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msPointerOver`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msPointerOver = function(inEvent) {
|
||||
var e = this.prepareEvent_(inEvent);
|
||||
this.dispatcher.enterOver(e, inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msPointerCancel`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msPointerCancel = function(inEvent) {
|
||||
var e = this.prepareEvent_(inEvent);
|
||||
this.dispatcher.cancel(e, inEvent);
|
||||
this.cleanup(inEvent.getBrowserEvent().pointerId);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msLostPointerCapture`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msLostPointerCapture = function(inEvent) {
|
||||
var e = this.dispatcher.makeEvent('lostpointercapture',
|
||||
inEvent.getBrowserEvent(), inEvent);
|
||||
this.dispatcher.dispatchEvent(e);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `msGotPointerCapture`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.MsSource.prototype.msGotPointerCapture = function(inEvent) {
|
||||
var e = this.dispatcher.makeEvent('gotpointercapture',
|
||||
inEvent.getBrowserEvent(), inEvent);
|
||||
this.dispatcher.dispatchEvent(e);
|
||||
};
|
||||
136
src/ol/pointer/nativesource.js
Normal file
136
src/ol/pointer/nativesource.js
Normal file
@@ -0,0 +1,136 @@
|
||||
// Based on https://github.com/Polymer/PointerEvents
|
||||
|
||||
// Copyright (c) 2013 The Polymer Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.pointer.NativeSource');
|
||||
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.pointer.EventSource');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||
* @constructor
|
||||
* @extends {ol.pointer.EventSource}
|
||||
*/
|
||||
ol.pointer.NativeSource = function(dispatcher) {
|
||||
var mapping = {
|
||||
'pointerdown': this.pointerDown,
|
||||
'pointermove': this.pointerMove,
|
||||
'pointerup': this.pointerUp,
|
||||
'pointerout': this.pointerOut,
|
||||
'pointerover': this.pointerOver,
|
||||
'pointercancel': this.pointerCancel,
|
||||
'gotpointercapture': this.gotPointerCapture,
|
||||
'lostpointercapture': this.lostPointerCapture
|
||||
};
|
||||
goog.base(this, dispatcher, mapping);
|
||||
};
|
||||
goog.inherits(ol.pointer.NativeSource, ol.pointer.EventSource);
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `pointerdown`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.pointerDown = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `pointermove`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.pointerMove = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `pointerup`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.pointerUp = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `pointerout`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.pointerOut = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `pointerover`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.pointerOver = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `pointercancel`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.pointerCancel = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `lostpointercapture`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.lostPointerCapture = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `gotpointercapture`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.NativeSource.prototype.gotPointerCapture = function(inEvent) {
|
||||
this.dispatcher.fireNativeEvent(inEvent);
|
||||
};
|
||||
295
src/ol/pointer/pointerevent.js
Normal file
295
src/ol/pointer/pointerevent.js
Normal file
@@ -0,0 +1,295 @@
|
||||
// Based on https://github.com/Polymer/PointerEvents
|
||||
|
||||
// Copyright (c) 2013 The Polymer Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.pointer.PointerEvent');
|
||||
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A class for pointer events.
|
||||
*
|
||||
* This class is used as an abstraction for mouse events,
|
||||
* touch events and even native pointer events.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @param {string} type The type of the event to create.
|
||||
* @param {goog.events.BrowserEvent} browserEvent
|
||||
* @param {Object.<string, ?>=} opt_eventDict An optional dictionary of
|
||||
* initial event properties.
|
||||
*/
|
||||
ol.pointer.PointerEvent = function(type, browserEvent, opt_eventDict) {
|
||||
goog.base(this, type);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {goog.events.BrowserEvent}
|
||||
*/
|
||||
this.browserEvent = browserEvent;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Event}
|
||||
*/
|
||||
this.originalEvent = browserEvent.getBrowserEvent();
|
||||
|
||||
var eventDict = goog.isDef(opt_eventDict) ? opt_eventDict : {};
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.buttons = this.getButtons_(eventDict);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.pressure = this.getPressure_(eventDict, this.buttons);
|
||||
|
||||
// MouseEvent related properties
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.bubbles = goog.object.get(eventDict, 'bubbles', false);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.cancelable = goog.object.get(eventDict, 'cancelable', false);
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
this.view = goog.object.get(eventDict, 'view', null);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.detail = goog.object.get(eventDict, 'detail', null);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.screenX = goog.object.get(eventDict, 'screenX', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.screenY = goog.object.get(eventDict, 'screenY', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.clientX = goog.object.get(eventDict, 'clientX', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.clientY = goog.object.get(eventDict, 'clientY', 0);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.ctrlKey = goog.object.get(eventDict, 'ctrlKey', false);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.altKey = goog.object.get(eventDict, 'altKey', false);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.shiftKey = goog.object.get(eventDict, 'shiftKey', false);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.metaKey = goog.object.get(eventDict, 'metaKey', false);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.button = goog.object.get(eventDict, 'button', 0);
|
||||
|
||||
/**
|
||||
* @type {Node}
|
||||
*/
|
||||
this.relatedTarget = goog.object.get(eventDict, 'relatedTarget', null);
|
||||
|
||||
// PointerEvent related properties
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
this.pointerId = goog.object.get(eventDict, 'pointerId', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.width = goog.object.get(eventDict, 'width', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.height = goog.object.get(eventDict, 'height', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.tiltX = goog.object.get(eventDict, 'tiltX', 0);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.tiltY = goog.object.get(eventDict, 'tiltY', 0);
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.pointerType = goog.object.get(eventDict, 'pointerType', '');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.hwTimestamp = goog.object.get(eventDict, 'hwTimestamp', 0);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.isPrimary = goog.object.get(eventDict, 'isPrimary', false);
|
||||
|
||||
// keep the semantics of preventDefault
|
||||
if (browserEvent.preventDefault) {
|
||||
this.preventDefault = function() {
|
||||
browserEvent.preventDefault();
|
||||
};
|
||||
}
|
||||
};
|
||||
goog.inherits(ol.pointer.PointerEvent, goog.events.Event);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object.<string, ?>} eventDict
|
||||
* @return {number}
|
||||
*/
|
||||
ol.pointer.PointerEvent.prototype.getButtons_ = function(eventDict) {
|
||||
// According to the w3c spec,
|
||||
// http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
|
||||
// MouseEvent.button == 0 can mean either no mouse button depressed, or the
|
||||
// left mouse button depressed.
|
||||
//
|
||||
// As of now, the only way to distinguish between the two states of
|
||||
// MouseEvent.button is by using the deprecated MouseEvent.which property, as
|
||||
// this maps mouse buttons to positive integers > 0, and uses 0 to mean that
|
||||
// no mouse button is held.
|
||||
//
|
||||
// MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,
|
||||
// but initMouseEvent does not expose an argument with which to set
|
||||
// MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set
|
||||
// MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations
|
||||
// of app developers.
|
||||
//
|
||||
// The only way to propagate the correct state of MouseEvent.which and
|
||||
// MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0
|
||||
// is to call initMouseEvent with a buttonArg value of -1.
|
||||
//
|
||||
// This is fixed with DOM Level 4's use of buttons
|
||||
var buttons;
|
||||
if (eventDict.buttons || ol.pointer.PointerEvent.HAS_BUTTONS) {
|
||||
buttons = eventDict.buttons;
|
||||
} else {
|
||||
switch (eventDict.which) {
|
||||
case 1: buttons = 1; break;
|
||||
case 2: buttons = 4; break;
|
||||
case 3: buttons = 2; break;
|
||||
default: buttons = 0;
|
||||
}
|
||||
}
|
||||
return buttons;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object.<string, ?>} eventDict
|
||||
* @param {number} buttons
|
||||
* @return {number}
|
||||
*/
|
||||
ol.pointer.PointerEvent.prototype.getPressure_ = function(eventDict, buttons) {
|
||||
// Spec requires that pointers without pressure specified use 0.5 for down
|
||||
// state and 0 for up state.
|
||||
var pressure = 0;
|
||||
if (eventDict.pressure) {
|
||||
pressure = eventDict.pressure;
|
||||
} else {
|
||||
pressure = buttons ? 0.5 : 0;
|
||||
}
|
||||
return pressure;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Is the `buttons` property supported?
|
||||
* @type {boolean}
|
||||
*/
|
||||
ol.pointer.PointerEvent.HAS_BUTTONS = false;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the `buttons` property is supported.
|
||||
*/
|
||||
(function() {
|
||||
try {
|
||||
var ev = ol.pointer.PointerEvent.createMouseEvent('click', {buttons: 1});
|
||||
ol.pointer.PointerEvent.HAS_BUTTONS = ev.buttons === 1;
|
||||
} catch (e) {
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* Warning is suppressed because Closure thinks the MouseEvent
|
||||
* constructor takes no arguments.
|
||||
* @param {string} inType The type of the event to create.
|
||||
* @param {Object} inDict An dictionary of initial event properties.
|
||||
* @return {MouseEvent}
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
ol.pointer.PointerEvent.createMouseEvent = function(inType, inDict) {
|
||||
return new MouseEvent(inType, inDict);
|
||||
};
|
||||
496
src/ol/pointer/pointereventhandler.js
Normal file
496
src/ol/pointer/pointereventhandler.js
Normal file
@@ -0,0 +1,496 @@
|
||||
// Based on https://github.com/Polymer/PointerEvents
|
||||
|
||||
// Copyright (c) 2013 The Polymer Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.pointer.PointerEventHandler');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventTarget');
|
||||
|
||||
goog.require('ol.BrowserFeature');
|
||||
goog.require('ol.pointer.MouseSource');
|
||||
goog.require('ol.pointer.MsSource');
|
||||
goog.require('ol.pointer.NativeSource');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
goog.require('ol.pointer.TouchSource');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
* @param {Element|HTMLDocument} element Viewport element.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler = function(element) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Element|HTMLDocument}
|
||||
*/
|
||||
this.element_ = element;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, goog.events.BrowserEvent|Object>}
|
||||
*/
|
||||
this.pointerMap = {};
|
||||
|
||||
/**
|
||||
* @type {Object.<string, function(goog.events.BrowserEvent)>}
|
||||
* @private
|
||||
*/
|
||||
this.eventMap_ = {};
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.pointer.EventSource>}
|
||||
* @private
|
||||
*/
|
||||
this.eventSourceList_ = [];
|
||||
|
||||
this.registerSources();
|
||||
};
|
||||
goog.inherits(ol.pointer.PointerEventHandler, goog.events.EventTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Set up the event sources (mouse, touch and native pointers)
|
||||
* that generate pointer events.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.registerSources = function() {
|
||||
if (ol.BrowserFeature.HAS_POINTER) {
|
||||
this.registerSource('native', new ol.pointer.NativeSource(this));
|
||||
} else if (ol.BrowserFeature.HAS_MSPOINTER) {
|
||||
this.registerSource('ms', new ol.pointer.MsSource(this));
|
||||
} else {
|
||||
var mouseSource = new ol.pointer.MouseSource(this);
|
||||
this.registerSource('mouse', mouseSource);
|
||||
|
||||
if (ol.BrowserFeature.HAS_TOUCH) {
|
||||
this.registerSource('touch',
|
||||
new ol.pointer.TouchSource(this, mouseSource));
|
||||
}
|
||||
}
|
||||
|
||||
// register events on the viewport element
|
||||
this.register_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a new event source that will generate pointer events.
|
||||
*
|
||||
* @param {string} name A name for the event source
|
||||
* @param {ol.pointer.EventSource} source
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.registerSource =
|
||||
function(name, source) {
|
||||
var s = source;
|
||||
var newEvents = s.getEvents();
|
||||
|
||||
if (newEvents) {
|
||||
goog.array.forEach(newEvents, function(e) {
|
||||
var handler = s.getHandlerForEvent(e);
|
||||
|
||||
if (handler) {
|
||||
this.eventMap_[e] = goog.bind(handler, s);
|
||||
}
|
||||
}, this);
|
||||
this.eventSourceList_.push(s);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set up the events for all registered event sources.
|
||||
* @private
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.register_ = function() {
|
||||
var l = this.eventSourceList_.length;
|
||||
var eventSource;
|
||||
for (var i = 0; i < l; i++) {
|
||||
eventSource = this.eventSourceList_[i];
|
||||
this.addEvents_(eventSource.getEvents());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove all registered events.
|
||||
* @private
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.unregister_ = function() {
|
||||
var l = this.eventSourceList_.length;
|
||||
var eventSource;
|
||||
for (var i = 0; i < l; i++) {
|
||||
eventSource = this.eventSourceList_[i];
|
||||
this.removeEvents_(eventSource.getEvents());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the right handler for a new event.
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} inEvent Browser event.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
|
||||
var type = inEvent.type;
|
||||
var handler = this.eventMap_[type];
|
||||
if (handler) {
|
||||
handler(inEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Setup listeners for the given events.
|
||||
* @private
|
||||
* @param {Array.<string>} events List of events.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.addEvents_ = function(events) {
|
||||
goog.array.forEach(events, function(eventName) {
|
||||
goog.events.listen(this.element_, eventName,
|
||||
this.eventHandler_, false, this);
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unregister listeners for the given events.
|
||||
* @private
|
||||
* @param {Array.<string>} events List of events.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.removeEvents_ = function(events) {
|
||||
goog.array.forEach(events, function(e) {
|
||||
goog.events.unlisten(this.element_, e,
|
||||
this.eventHandler_, false, this);
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a snapshot of inEvent, with writable properties.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {Event|Touch} inEvent An event that contains
|
||||
* properties to copy.
|
||||
* @return {Object} An object containing shallow copies of
|
||||
* `inEvent`'s properties.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.cloneEvent =
|
||||
function(browserEvent, inEvent) {
|
||||
var eventCopy = {}, p;
|
||||
for (var i = 0, ii = ol.pointer.CLONE_PROPS.length; i < ii; i++) {
|
||||
p = ol.pointer.CLONE_PROPS[i][0];
|
||||
eventCopy[p] =
|
||||
browserEvent[p] ||
|
||||
inEvent[p] ||
|
||||
ol.pointer.CLONE_PROPS[i][1];
|
||||
}
|
||||
|
||||
return eventCopy;
|
||||
};
|
||||
|
||||
|
||||
// EVENTS
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointerdown' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.down =
|
||||
function(pointerEventData, browserEvent) {
|
||||
this.fireEvent(ol.pointer.EventType.POINTERDOWN,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointermove' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.move =
|
||||
function(pointerEventData, browserEvent) {
|
||||
this.fireEvent(ol.pointer.EventType.POINTERMOVE,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointerup' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.up =
|
||||
function(pointerEventData, browserEvent) {
|
||||
this.fireEvent(ol.pointer.EventType.POINTERUP,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointerenter' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.enter =
|
||||
function(pointerEventData, browserEvent) {
|
||||
pointerEventData.bubbles = false;
|
||||
this.fireEvent(ol.pointer.EventType.POINTERENTER,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointerleave' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.leave =
|
||||
function(pointerEventData, browserEvent) {
|
||||
pointerEventData.bubbles = false;
|
||||
this.fireEvent(ol.pointer.EventType.POINTERLEAVE,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointerover' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.over =
|
||||
function(pointerEventData, browserEvent) {
|
||||
pointerEventData.bubbles = true;
|
||||
this.fireEvent(ol.pointer.EventType.POINTEROVER,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointerout' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.out =
|
||||
function(pointerEventData, browserEvent) {
|
||||
pointerEventData.bubbles = true;
|
||||
this.fireEvent(ol.pointer.EventType.POINTEROUT,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a 'pointercancel' event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.cancel =
|
||||
function(pointerEventData, browserEvent) {
|
||||
this.fireEvent(ol.pointer.EventType.POINTERCANCEL,
|
||||
pointerEventData, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a combination of 'pointerout' and 'pointerleave' events.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.leaveOut =
|
||||
function(pointerEventData, browserEvent) {
|
||||
this.out(pointerEventData, browserEvent);
|
||||
if (!this.contains_(
|
||||
pointerEventData.target,
|
||||
pointerEventData.relatedTarget)) {
|
||||
this.leave(pointerEventData, browserEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a combination of 'pointerover' and 'pointerevents' events.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.enterOver =
|
||||
function(pointerEventData, browserEvent) {
|
||||
this.over(pointerEventData, browserEvent);
|
||||
if (!this.contains_(
|
||||
pointerEventData.target,
|
||||
pointerEventData.relatedTarget)) {
|
||||
this.enter(pointerEventData, browserEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Element} container
|
||||
* @param {Element} contained
|
||||
* @return {boolean} Returns true if the container element
|
||||
* contains the other element.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.contains_ =
|
||||
function(container, contained) {
|
||||
return container.contains(contained);
|
||||
};
|
||||
|
||||
|
||||
// EVENT CREATION AND TRACKING
|
||||
/**
|
||||
* Creates a new Event of type `inType`, based on the information in
|
||||
* `pointerEventData`.
|
||||
*
|
||||
* @param {string} inType A string representing the type of event to create.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
* @return {ol.pointer.PointerEvent} A PointerEvent of type `inType`.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.makeEvent =
|
||||
function(inType, pointerEventData, browserEvent) {
|
||||
return new ol.pointer.PointerEvent(inType, browserEvent, pointerEventData);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make and dispatch an event in one call.
|
||||
* @param {string} inType A string representing the type of event.
|
||||
* @param {Object} pointerEventData
|
||||
* @param {goog.events.BrowserEvent } browserEvent
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.fireEvent =
|
||||
function(inType, pointerEventData, browserEvent) {
|
||||
var e = this.makeEvent(inType, pointerEventData, browserEvent);
|
||||
this.dispatchEvent(e);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a pointer event from a native pointer event
|
||||
* and dispatches this event.
|
||||
* @param {goog.events.BrowserEvent} nativeEvent A platform event with a target.
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.fireNativeEvent =
|
||||
function(nativeEvent) {
|
||||
var e = this.makeEvent(nativeEvent.type, nativeEvent.getBrowserEvent(),
|
||||
nativeEvent);
|
||||
this.dispatchEvent(e);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wrap a native mouse event into a pointer event.
|
||||
* This proxy method is required for the legacy IE support.
|
||||
* @param {string} eventType The pointer event type.
|
||||
* @param {goog.events.BrowserEvent} browserEvent
|
||||
* @return {ol.pointer.PointerEvent}
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.wrapMouseEvent =
|
||||
function(eventType, browserEvent) {
|
||||
var pointerEvent = this.makeEvent(
|
||||
eventType,
|
||||
ol.pointer.MouseSource.prepareEvent(browserEvent, this),
|
||||
browserEvent
|
||||
);
|
||||
return pointerEvent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.pointer.PointerEventHandler.prototype.disposeInternal = function() {
|
||||
this.unregister_();
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constants for event names.
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.pointer.EventType = {
|
||||
POINTERMOVE: 'pointermove',
|
||||
POINTERDOWN: 'pointerdown',
|
||||
POINTERUP: 'pointerup',
|
||||
POINTEROVER: 'pointerover',
|
||||
POINTEROUT: 'pointerout',
|
||||
POINTERENTER: 'pointerenter',
|
||||
POINTERLEAVE: 'pointerleave',
|
||||
POINTERCANCEL: 'pointercancel'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Properties to copy when cloning an event, with default values.
|
||||
* @type {Array.<Array>}
|
||||
*/
|
||||
ol.pointer.CLONE_PROPS = [
|
||||
// MouseEvent
|
||||
['bubbles', false],
|
||||
['cancelable', false],
|
||||
['view', null],
|
||||
['detail', null],
|
||||
['screenX', 0],
|
||||
['screenY', 0],
|
||||
['clientX', 0],
|
||||
['clientY', 0],
|
||||
['ctrlKey', false],
|
||||
['altKey', false],
|
||||
['shiftKey', false],
|
||||
['metaKey', false],
|
||||
['button', 0],
|
||||
['relatedTarget', null],
|
||||
// DOM Level 3
|
||||
['buttons', 0],
|
||||
// PointerEvent
|
||||
['pointerId', 0],
|
||||
['width', 0],
|
||||
['height', 0],
|
||||
['pressure', 0],
|
||||
['tiltX', 0],
|
||||
['tiltY', 0],
|
||||
['pointerType', ''],
|
||||
['hwTimestamp', 0],
|
||||
['isPrimary', false],
|
||||
// event instance
|
||||
['type', ''],
|
||||
['target', null],
|
||||
['currentTarget', null],
|
||||
['which', 0]
|
||||
];
|
||||
445
src/ol/pointer/touchsource.js
Normal file
445
src/ol/pointer/touchsource.js
Normal file
@@ -0,0 +1,445 @@
|
||||
// Based on https://github.com/Polymer/PointerEvents
|
||||
|
||||
// Copyright (c) 2013 The Polymer Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
goog.provide('ol.pointer.TouchSource');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math.Coordinate');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.pointer.EventSource');
|
||||
goog.require('ol.pointer.MouseSource');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.pointer.PointerEventHandler} dispatcher
|
||||
* @param {ol.pointer.MouseSource} mouseSource
|
||||
* @extends {ol.pointer.EventSource}
|
||||
*/
|
||||
ol.pointer.TouchSource = function(dispatcher, mouseSource) {
|
||||
var mapping = {
|
||||
'touchstart': this.touchstart,
|
||||
'touchmove': this.touchmove,
|
||||
'touchend': this.touchend,
|
||||
'touchcancel': this.touchcancel
|
||||
};
|
||||
goog.base(this, dispatcher, mapping);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, goog.events.BrowserEvent|Object>}
|
||||
*/
|
||||
this.pointerMap = dispatcher.pointerMap;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {ol.pointer.MouseSource}
|
||||
*/
|
||||
this.mouseSource = mouseSource;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.firstTouchId_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.clickCount_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.resetId_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function()}
|
||||
*/
|
||||
this.resetClickCountHandler_ = goog.bind(function() {
|
||||
this.clickCount_ = 0;
|
||||
this.resetId_ = undefined;
|
||||
}, this);
|
||||
};
|
||||
goog.inherits(ol.pointer.TouchSource, ol.pointer.EventSource);
|
||||
|
||||
|
||||
/**
|
||||
* Mouse event timeout: This should be long enough to
|
||||
* ignore compat mouse events made by touch.
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.pointer.TouchSource.DEDUP_TIMEOUT = 2500;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
ol.pointer.TouchSource.CLICK_COUNT_TIMEOUT = 200;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
ol.pointer.TouchSource.POINTER_TYPE = 'touch';
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Touch} inTouch
|
||||
* @return {boolean} True, if this is the primary touch.
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.isPrimaryTouch_ = function(inTouch) {
|
||||
return this.firstTouchId_ === inTouch.identifier;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set primary touch if there are no pointers, or the only pointer is the mouse.
|
||||
* @param {Touch} inTouch
|
||||
* @private
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.setPrimaryTouch_ = function(inTouch) {
|
||||
if (goog.object.getCount(this.pointerMap) === 0 ||
|
||||
(goog.object.getCount(this.pointerMap) === 1 &&
|
||||
goog.object.containsKey(this.pointerMap,
|
||||
ol.pointer.MouseSource.POINTER_ID.toString()))) {
|
||||
this.firstTouchId_ = inTouch.identifier;
|
||||
this.cancelResetClickCount_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} inPointer
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.removePrimaryPointer_ = function(inPointer) {
|
||||
if (inPointer.isPrimary) {
|
||||
this.firstTouchId_ = undefined;
|
||||
this.resetClickCount_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.resetClickCount_ = function() {
|
||||
this.resetId_ = goog.global.setTimeout(this.resetClickCountHandler_,
|
||||
ol.pointer.TouchSource.CLICK_COUNT_TIMEOUT);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.cancelResetClickCount_ = function() {
|
||||
if (goog.isDef(this.resetId_)) {
|
||||
goog.global.clearTimeout(this.resetId_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event
|
||||
* @param {Touch} inTouch Touch event
|
||||
* @return {Object}
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.touchToPointer_ =
|
||||
function(browserEvent, inTouch) {
|
||||
var e = this.dispatcher.cloneEvent(browserEvent, inTouch);
|
||||
// Spec specifies that pointerId 1 is reserved for Mouse.
|
||||
// Touch identifiers can start at 0.
|
||||
// Add 2 to the touch identifier for compatibility.
|
||||
e.pointerId = inTouch.identifier + 2;
|
||||
// TODO: check if this is neccessary?
|
||||
//e.target = findTarget(e);
|
||||
e.bubbles = true;
|
||||
e.cancelable = true;
|
||||
e.detail = this.clickCount_;
|
||||
e.button = 0;
|
||||
e.buttons = 1;
|
||||
e.width = inTouch['webkitRadiusX'] || inTouch['radiusX'] || 0;
|
||||
e.height = inTouch['webkitRadiusY'] || inTouch['radiusY'] || 0;
|
||||
e.pressure = inTouch['webkitForce'] || inTouch['force'] || 0.5;
|
||||
e.isPrimary = this.isPrimaryTouch_(inTouch);
|
||||
e.pointerType = ol.pointer.TouchSource.POINTER_TYPE;
|
||||
|
||||
// make sure that the properties that are different for
|
||||
// each `Touch` object are not copied from the BrowserEvent object
|
||||
e.clientX = inTouch.clientX;
|
||||
e.clientY = inTouch.clientY;
|
||||
e.screenX = inTouch.screenX;
|
||||
e.screenY = inTouch.screenY;
|
||||
|
||||
return e;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} inEvent Touch event
|
||||
* @param {function(goog.events.BrowserEvent, Object)} inFunction
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.processTouches_ =
|
||||
function(inEvent, inFunction) {
|
||||
var tl = inEvent.getBrowserEvent().changedTouches;
|
||||
var touchesCopy = goog.array.clone(tl);
|
||||
var pointers = goog.array.map(touchesCopy,
|
||||
goog.partial(this.touchToPointer_, inEvent), this);
|
||||
// forward touch preventDefaults
|
||||
goog.array.forEach(pointers, function(p) {
|
||||
p.preventDefault = function() {
|
||||
inEvent.preventDefault();
|
||||
};
|
||||
}, this);
|
||||
goog.array.forEach(pointers, goog.partial(inFunction, inEvent), this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {TouchList} touchList
|
||||
* @param {number} searchId
|
||||
* @return {boolean} True, if the `Touch` with the given id is in the list.
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.findTouch_ = function(touchList, searchId) {
|
||||
var l = touchList.length;
|
||||
var touch;
|
||||
for (var i = 0; i < l; i++) {
|
||||
touch = touchList[i];
|
||||
if (touch.identifier === searchId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* In some instances, a touchstart can happen without a touchend. This
|
||||
* leaves the pointermap in a broken state.
|
||||
* Therefore, on every touchstart, we remove the touches that did not fire a
|
||||
* touchend event.
|
||||
* To keep state globally consistent, we fire a pointercancel for
|
||||
* this "abandoned" touch
|
||||
*
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.vacuumTouches_ = function(inEvent) {
|
||||
var touchList = inEvent.getBrowserEvent().touches;
|
||||
// pointerMap.getCount() should be < touchList.length here,
|
||||
// as the touchstart has not been processed yet.
|
||||
if (goog.object.getCount(this.pointerMap) >= touchList.length) {
|
||||
var d = [];
|
||||
goog.object.forEach(this.pointerMap, function(value, key) {
|
||||
// Never remove pointerId == 1, which is mouse.
|
||||
// Touch identifiers are 2 smaller than their pointerId, which is the
|
||||
// index in pointermap.
|
||||
if (key != ol.pointer.MouseSource.POINTER_ID &&
|
||||
!this.findTouch_(touchList, key - 2)) {
|
||||
d.push(value.out);
|
||||
}
|
||||
}, this);
|
||||
goog.array.forEach(d, goog.partial(this.cancelOut_, inEvent), this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `touchstart`, triggers `pointerover`,
|
||||
* `pointerenter` and `pointerdown` events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.touchstart = function(inEvent) {
|
||||
this.vacuumTouches_(inEvent);
|
||||
this.setPrimaryTouch_(inEvent.getBrowserEvent().changedTouches[0]);
|
||||
this.dedupSynthMouse_(inEvent);
|
||||
this.clickCount_++;
|
||||
this.processTouches_(inEvent, this.overDown_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} browserEvent
|
||||
* @param {Object} inPointer
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.overDown_ = function(browserEvent, inPointer) {
|
||||
goog.object.set(this.pointerMap, inPointer.pointerId, {
|
||||
target: inPointer.target,
|
||||
out: inPointer,
|
||||
outTarget: inPointer.target
|
||||
});
|
||||
this.dispatcher.over(inPointer, browserEvent);
|
||||
this.dispatcher.enter(inPointer, browserEvent);
|
||||
this.dispatcher.down(inPointer, browserEvent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `touchmove`.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.touchmove = function(inEvent) {
|
||||
inEvent.preventDefault();
|
||||
this.processTouches_(inEvent, this.moveOverOut_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} browserEvent
|
||||
* @param {Object} inPointer
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.moveOverOut_ =
|
||||
function(browserEvent, inPointer) {
|
||||
var event = inPointer;
|
||||
var pointer = goog.object.get(this.pointerMap, event.pointerId);
|
||||
// a finger drifted off the screen, ignore it
|
||||
if (!pointer) {
|
||||
return;
|
||||
}
|
||||
var outEvent = pointer.out;
|
||||
var outTarget = pointer.outTarget;
|
||||
this.dispatcher.move(event, browserEvent);
|
||||
if (outEvent && outTarget !== event.target) {
|
||||
outEvent.relatedTarget = event.target;
|
||||
event.relatedTarget = outTarget;
|
||||
// recover from retargeting by shadow
|
||||
outEvent.target = outTarget;
|
||||
if (event.target) {
|
||||
this.dispatcher.leaveOut(outEvent, browserEvent);
|
||||
this.dispatcher.enterOver(event, browserEvent);
|
||||
} else {
|
||||
// clean up case when finger leaves the screen
|
||||
event.target = outTarget;
|
||||
event.relatedTarget = null;
|
||||
this.cancelOut_(browserEvent, event);
|
||||
}
|
||||
}
|
||||
pointer.out = event;
|
||||
pointer.outTarget = event.target;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `touchend`, triggers `pointerup`,
|
||||
* `pointerout` and `pointerleave` events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.touchend = function(inEvent) {
|
||||
this.dedupSynthMouse_(inEvent);
|
||||
this.processTouches_(inEvent, this.upOut_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} browserEvent
|
||||
* @param {Object} inPointer
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.upOut_ = function(browserEvent, inPointer) {
|
||||
this.dispatcher.up(inPointer, browserEvent);
|
||||
this.dispatcher.out(inPointer, browserEvent);
|
||||
this.dispatcher.leave(inPointer, browserEvent);
|
||||
this.cleanUpPointer_(inPointer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for `touchcancel`, triggers `pointercancel`,
|
||||
* `pointerout` and `pointerleave` events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.touchcancel = function(inEvent) {
|
||||
this.processTouches_(inEvent, this.cancelOut_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} browserEvent
|
||||
* @param {Object} inPointer
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.cancelOut_ =
|
||||
function(browserEvent, inPointer) {
|
||||
this.dispatcher.cancel(inPointer, browserEvent);
|
||||
this.dispatcher.out(inPointer, browserEvent);
|
||||
this.dispatcher.leave(inPointer, browserEvent);
|
||||
this.cleanUpPointer_(inPointer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} inPointer
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.cleanUpPointer_ = function(inPointer) {
|
||||
goog.object.remove(this.pointerMap, inPointer.pointerId);
|
||||
this.removePrimaryPointer_(inPointer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Prevent synth mouse events from creating pointer events.
|
||||
*
|
||||
* @private
|
||||
* @param {goog.events.BrowserEvent} inEvent
|
||||
*/
|
||||
ol.pointer.TouchSource.prototype.dedupSynthMouse_ = function(inEvent) {
|
||||
var lts = this.mouseSource.lastTouches;
|
||||
var t = inEvent.getBrowserEvent().changedTouches[0];
|
||||
// only the primary finger will synth mouse events
|
||||
if (this.isPrimaryTouch_(t)) {
|
||||
// remember x/y of last touch
|
||||
var lt = new goog.math.Coordinate(t.clientX, t.clientY);
|
||||
lts.push(lt);
|
||||
|
||||
goog.global.setTimeout(function() {
|
||||
// remove touch after timeout
|
||||
goog.array.remove(lts, lt);
|
||||
}, ol.pointer.TouchSource.DEDUP_TIMEOUT);
|
||||
}
|
||||
};
|
||||
@@ -48,12 +48,13 @@ describe('ol.interaction.Draw', function() {
|
||||
var viewport = map.getViewport();
|
||||
// calculated in case body has top < 0 (test runner with small window)
|
||||
var position = goog.style.getClientPosition(viewport);
|
||||
var event = new goog.events.BrowserEvent({
|
||||
type: type,
|
||||
clientX: position.x + x + width / 2,
|
||||
clientY: position.y + y + height / 2
|
||||
});
|
||||
goog.events.fireListeners(viewport, type, false, event);
|
||||
var event = new ol.MapBrowserPointerEvent(type, map,
|
||||
new ol.pointer.PointerEvent(type,
|
||||
new goog.events.BrowserEvent({
|
||||
clientX: position.x + x + width / 2,
|
||||
clientY: position.y + y + height / 2
|
||||
})));
|
||||
map.handleMapBrowserEvent(event);
|
||||
}
|
||||
|
||||
describe('constructor', function() {
|
||||
@@ -81,10 +82,9 @@ describe('ol.interaction.Draw', function() {
|
||||
});
|
||||
|
||||
it('draws a point on click', function() {
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
var geometry = features[0].getGeometry();
|
||||
@@ -93,11 +93,10 @@ describe('ol.interaction.Draw', function() {
|
||||
});
|
||||
|
||||
it('does not draw a point with a significant drag', function() {
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mousemove', 15, 20);
|
||||
simulateEvent('mouseup', 15, 20);
|
||||
simulateEvent('click', 15, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointermove', 15, 20);
|
||||
simulateEvent('pointerup', 15, 20);
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(0);
|
||||
});
|
||||
@@ -107,11 +106,10 @@ describe('ol.interaction.Draw', function() {
|
||||
var de = sinon.spy();
|
||||
goog.events.listen(draw, ol.DrawEventType.DRAWSTART, ds);
|
||||
goog.events.listen(draw, ol.DrawEventType.DRAWEND, de);
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('mousemove', 20, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
simulateEvent('pointermove', 20, 20);
|
||||
expect(ds).to.be.called(2);
|
||||
expect(de).to.be.called(1);
|
||||
});
|
||||
@@ -128,10 +126,9 @@ describe('ol.interaction.Draw', function() {
|
||||
});
|
||||
|
||||
it('draws multipoint on click', function() {
|
||||
simulateEvent('mousemove', 30, 15);
|
||||
simulateEvent('mousedown', 30, 15);
|
||||
simulateEvent('mouseup', 30, 15);
|
||||
simulateEvent('click', 30, 15);
|
||||
simulateEvent('pointermove', 30, 15);
|
||||
simulateEvent('pointerdown', 30, 15);
|
||||
simulateEvent('pointerup', 30, 15);
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
var geometry = features[0].getGeometry();
|
||||
@@ -154,21 +151,18 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('draws linestring with clicks, finishing on last point', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// finish on second point
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -179,29 +173,24 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('does not add a point with a significant drag', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// drag map
|
||||
simulateEvent('mousemove', 15, 20);
|
||||
simulateEvent('mousedown', 15, 20);
|
||||
simulateEvent('mousemove', 20, 20);
|
||||
simulateEvent('mouseup', 20, 20);
|
||||
simulateEvent('click', 20, 20);
|
||||
|
||||
simulateEvent('pointermove', 15, 20);
|
||||
simulateEvent('pointerdown', 15, 20);
|
||||
simulateEvent('pointermove', 20, 20);
|
||||
simulateEvent('pointerup', 20, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// finish on second point
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -217,22 +206,19 @@ describe('ol.interaction.Draw', function() {
|
||||
goog.events.listen(draw, ol.DrawEventType.DRAWEND, de);
|
||||
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// finish on second point
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
|
||||
expect(ds).to.be.called(1);
|
||||
expect(de).to.be.called(1);
|
||||
@@ -251,21 +237,18 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('draws multi with clicks, finishing on last point', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// finish on second point
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -289,28 +272,24 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('draws polygon with clicks, finishing on first point', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// third point
|
||||
simulateEvent('mousemove', 40, 10);
|
||||
simulateEvent('mousedown', 40, 10);
|
||||
simulateEvent('mouseup', 40, 10);
|
||||
simulateEvent('click', 40, 10);
|
||||
simulateEvent('pointermove', 40, 10);
|
||||
simulateEvent('pointerdown', 40, 10);
|
||||
simulateEvent('pointerup', 40, 10);
|
||||
|
||||
// finish on first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -324,27 +303,23 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('draws polygon with clicks, finishing on last point', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// third point
|
||||
simulateEvent('mousemove', 40, 10);
|
||||
simulateEvent('mousedown', 40, 10);
|
||||
simulateEvent('mouseup', 40, 10);
|
||||
simulateEvent('click', 40, 10);
|
||||
simulateEvent('pointermove', 40, 10);
|
||||
simulateEvent('pointerdown', 40, 10);
|
||||
simulateEvent('pointerup', 40, 10);
|
||||
|
||||
// finish on last point
|
||||
simulateEvent('mousedown', 40, 10);
|
||||
simulateEvent('mouseup', 40, 10);
|
||||
simulateEvent('click', 40, 11);
|
||||
simulateEvent('pointerdown', 40, 10);
|
||||
simulateEvent('pointerup', 40, 10);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -363,28 +338,24 @@ describe('ol.interaction.Draw', function() {
|
||||
goog.events.listen(draw, ol.DrawEventType.DRAWEND, de);
|
||||
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// third point
|
||||
simulateEvent('mousemove', 30, 10);
|
||||
simulateEvent('mousedown', 30, 10);
|
||||
simulateEvent('mouseup', 30, 10);
|
||||
simulateEvent('click', 30, 10);
|
||||
simulateEvent('pointermove', 30, 10);
|
||||
simulateEvent('pointerdown', 30, 10);
|
||||
simulateEvent('pointerup', 30, 10);
|
||||
|
||||
// finish on first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
expect(ds).to.be.called(1);
|
||||
expect(de).to.be.called(1);
|
||||
@@ -403,28 +374,24 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('draws multi with clicks, finishing on first point', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// third point
|
||||
simulateEvent('mousemove', 40, 10);
|
||||
simulateEvent('mousedown', 40, 10);
|
||||
simulateEvent('mouseup', 40, 10);
|
||||
simulateEvent('click', 40, 10);
|
||||
simulateEvent('pointermove', 40, 10);
|
||||
simulateEvent('pointerdown', 40, 10);
|
||||
simulateEvent('pointerup', 40, 10);
|
||||
|
||||
// finish on first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -440,27 +407,23 @@ describe('ol.interaction.Draw', function() {
|
||||
|
||||
it('draws multi with clicks, finishing on last point', function() {
|
||||
// first point
|
||||
simulateEvent('mousemove', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
simulateEvent('mouseup', 10, 20);
|
||||
simulateEvent('click', 10, 20);
|
||||
simulateEvent('pointermove', 10, 20);
|
||||
simulateEvent('pointerdown', 10, 20);
|
||||
simulateEvent('pointerup', 10, 20);
|
||||
|
||||
// second point
|
||||
simulateEvent('mousemove', 30, 20);
|
||||
simulateEvent('mousedown', 30, 20);
|
||||
simulateEvent('mouseup', 30, 20);
|
||||
simulateEvent('click', 30, 20);
|
||||
simulateEvent('pointermove', 30, 20);
|
||||
simulateEvent('pointerdown', 30, 20);
|
||||
simulateEvent('pointerup', 30, 20);
|
||||
|
||||
// third point
|
||||
simulateEvent('mousemove', 40, 10);
|
||||
simulateEvent('mousedown', 40, 10);
|
||||
simulateEvent('mouseup', 40, 10);
|
||||
simulateEvent('click', 40, 10);
|
||||
simulateEvent('pointermove', 40, 10);
|
||||
simulateEvent('pointerdown', 40, 10);
|
||||
simulateEvent('pointerup', 40, 10);
|
||||
|
||||
// finish on last point
|
||||
simulateEvent('mousedown', 40, 10);
|
||||
simulateEvent('mouseup', 40, 10);
|
||||
simulateEvent('click', 40, 10);
|
||||
simulateEvent('pointerdown', 40, 10);
|
||||
simulateEvent('pointerup', 40, 10);
|
||||
|
||||
var features = source.getFeatures();
|
||||
expect(features).to.have.length(1);
|
||||
@@ -483,6 +446,7 @@ goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapBrowserPointerEvent');
|
||||
goog.require('ol.RendererHint');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
@@ -495,4 +459,5 @@ goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Draw');
|
||||
goog.require('ol.interaction.Interaction');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
goog.require('ol.source.Vector');
|
||||
|
||||
@@ -141,13 +141,12 @@ describe('ol.Map', function() {
|
||||
options = {
|
||||
altShiftDragRotate: false,
|
||||
doubleClickZoom: false,
|
||||
dragPan: false,
|
||||
keyboard: false,
|
||||
mouseWheelZoom: false,
|
||||
shiftDragZoom: false,
|
||||
touchPan: false,
|
||||
touchRotate: false,
|
||||
touchZoom: false
|
||||
dragPan: false,
|
||||
pinchRotate: false,
|
||||
pinchZoom: false
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -28,12 +28,13 @@ describe('ol.MapBrowserEventHandler', function() {
|
||||
});
|
||||
|
||||
it('emulates click', function() {
|
||||
handler.emulateClick_(new goog.events.BrowserEvent({
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
}));
|
||||
handler.emulateClick_(new ol.pointer.PointerEvent('pointerdown',
|
||||
new goog.events.BrowserEvent({
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
})));
|
||||
expect(singleclickSpy.called).to.not.be.ok();
|
||||
expect(dblclickSpy.called).to.not.be.ok();
|
||||
|
||||
@@ -41,12 +42,13 @@ describe('ol.MapBrowserEventHandler', function() {
|
||||
expect(singleclickSpy.calledOnce).to.be.ok();
|
||||
expect(dblclickSpy.called).to.not.be.ok();
|
||||
|
||||
handler.emulateClick_(new goog.events.BrowserEvent({
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
}));
|
||||
handler.emulateClick_(new ol.pointer.PointerEvent('pointerdown',
|
||||
new goog.events.BrowserEvent({
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
})));
|
||||
expect(singleclickSpy.calledOnce).to.be.ok();
|
||||
expect(dblclickSpy.called).to.not.be.ok();
|
||||
});
|
||||
@@ -61,12 +63,13 @@ describe('ol.MapBrowserEventHandler', function() {
|
||||
expect(singleclickSpy.called).to.not.be.ok();
|
||||
expect(dblclickSpy.called).to.not.be.ok();
|
||||
|
||||
handler.emulateClick_(new goog.events.BrowserEvent({
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
}));
|
||||
handler.emulateClick_(new ol.pointer.PointerEvent('pointerdown',
|
||||
new goog.events.BrowserEvent({
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
})));
|
||||
expect(singleclickSpy.called).to.not.be.ok();
|
||||
expect(dblclickSpy.calledOnce).to.be.ok();
|
||||
|
||||
@@ -88,24 +91,13 @@ describe('ol.MapBrowserEventHandler', function() {
|
||||
expect(handler.getDown()).to.be(null);
|
||||
});
|
||||
|
||||
it('returns an event after handleMouseDown_ has been called', function() {
|
||||
var event = new goog.events.BrowserEvent({});
|
||||
handler.handleMouseDown_(event);
|
||||
expect(handler.getDown()).to.be(event);
|
||||
});
|
||||
|
||||
it('returns an event after handlePointerDown_ has been called', function() {
|
||||
var event = new goog.events.BrowserEvent({});
|
||||
var event = new ol.pointer.PointerEvent('pointerdown',
|
||||
new goog.events.BrowserEvent({}));
|
||||
handler.handlePointerDown_(event);
|
||||
expect(handler.getDown()).to.be(event);
|
||||
});
|
||||
|
||||
it('returns an event after handleTouchStart_ has been called', function() {
|
||||
var event = new goog.events.BrowserEvent({});
|
||||
handler.handleTouchStart_(event);
|
||||
expect(handler.getDown()).to.be(event);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -115,3 +107,4 @@ goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapBrowserEventHandler');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
|
||||
101
test/spec/ol/pointer/mousesource.test.js
Normal file
101
test/spec/ol/pointer/mousesource.test.js
Normal file
@@ -0,0 +1,101 @@
|
||||
goog.provide('ol.test.pointer.MouseSource');
|
||||
|
||||
describe('ol.pointer.MouseSource', function() {
|
||||
var handler;
|
||||
var target;
|
||||
var eventSpy;
|
||||
var clock;
|
||||
|
||||
beforeEach(function() {
|
||||
clock = sinon.useFakeTimers();
|
||||
target = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
|
||||
// make sure that a mouse and touch event source is used
|
||||
ol.BrowserFeature.HAS_POINTER = false;
|
||||
ol.BrowserFeature.HAS_MSPOINTER = false;
|
||||
ol.BrowserFeature.HAS_TOUCH = true;
|
||||
|
||||
handler = new ol.pointer.PointerEventHandler(target);
|
||||
eventSpy = sinon.spy();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
handler.dispose();
|
||||
});
|
||||
|
||||
describe('simulated mouse events', function() {
|
||||
it('prevents simulated mouse events', function() {
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
|
||||
// simulates that a mouse event is triggered from a touch
|
||||
simulateTouchEvent('touchstart', 10, 20);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
|
||||
expect(eventSpy.calledOnce).to.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('dispatches real mouse events', function() {
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
|
||||
// the two events are at different positions
|
||||
simulateTouchEvent('touchstart', 10, 20);
|
||||
simulateEvent('mousedown', 10, 40);
|
||||
|
||||
expect(eventSpy.calledTwice).to.be.ok();
|
||||
});
|
||||
|
||||
it('dispatches real mouse events after timeout', function() {
|
||||
// set the timeout to a lower value, to speed up the tests
|
||||
ol.pointer.TouchSource.DEDUP_TIMEOUT = 100;
|
||||
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
|
||||
// first simulate a touch event, then a mouse event
|
||||
// at the same position after a timeout
|
||||
simulateTouchEvent('touchstart', 10, 20);
|
||||
clock.tick(150);
|
||||
simulateEvent('mousedown', 10, 20);
|
||||
|
||||
expect(eventSpy.calledTwice).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
function simulateTouchEvent(type, x, y) {
|
||||
var touches = [
|
||||
{
|
||||
identifier: 4,
|
||||
clientX: x,
|
||||
clientX: y,
|
||||
target: target
|
||||
}
|
||||
];
|
||||
|
||||
var event = new goog.events.BrowserEvent({
|
||||
type: type,
|
||||
touches: touches,
|
||||
changedTouches: touches
|
||||
});
|
||||
goog.events.fireListeners(target, type, false, event);
|
||||
}
|
||||
|
||||
function simulateEvent(type, x, y) {
|
||||
var event = new goog.events.BrowserEvent({
|
||||
type: type,
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
target: target
|
||||
});
|
||||
goog.events.fireListeners(target, type, false, event);
|
||||
}
|
||||
});
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('ol.BrowserFeature');
|
||||
goog.require('ol.pointer.MouseSource');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
goog.require('ol.pointer.PointerEventHandler');
|
||||
goog.require('ol.pointer.TouchSource');
|
||||
170
test/spec/ol/pointer/pointereventhandler.test.js
Normal file
170
test/spec/ol/pointer/pointereventhandler.test.js
Normal file
@@ -0,0 +1,170 @@
|
||||
goog.provide('ol.test.pointer.PointerEventHandler');
|
||||
|
||||
describe('ol.pointer.PointerEventHandler', function() {
|
||||
var handler;
|
||||
var target;
|
||||
var eventSpy;
|
||||
|
||||
beforeEach(function() {
|
||||
target = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
|
||||
// make sure that a mouse event source is used
|
||||
ol.BrowserFeature.HAS_POINTER = false;
|
||||
ol.BrowserFeature.HAS_MSPOINTER = false;
|
||||
|
||||
handler = new ol.pointer.PointerEventHandler(target);
|
||||
eventSpy = sinon.spy();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
handler.dispose();
|
||||
});
|
||||
|
||||
|
||||
describe('constructor', function() {
|
||||
it('registers a least one event source', function() {
|
||||
expect(handler.eventSourceList_.length).to.be.greaterThan(0);
|
||||
expect(handler.eventSourceList_[0]).to.be.a(ol.pointer.MouseSource);
|
||||
});
|
||||
});
|
||||
|
||||
function simulateEvent(type, x, y) {
|
||||
var event = new goog.events.BrowserEvent({
|
||||
type: type,
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
target: target
|
||||
});
|
||||
goog.events.fireListeners(target, type, false, event);
|
||||
}
|
||||
|
||||
describe('pointer down', function() {
|
||||
it('fires pointerdown events', function() {
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
simulateEvent('mousedown', 0, 0);
|
||||
expect(eventSpy.calledOnce).to.be.ok();
|
||||
|
||||
var pointerEvent = eventSpy.firstCall.args[0];
|
||||
expect(pointerEvent).to.be.a(ol.pointer.PointerEvent);
|
||||
expect(pointerEvent.type).to.be('pointerdown');
|
||||
expect(pointerEvent.pointerId).to.be(1);
|
||||
expect(pointerEvent.pointerType).to.be('mouse');
|
||||
});
|
||||
});
|
||||
|
||||
describe('pointer up', function() {
|
||||
it('fires pointerup events', function() {
|
||||
goog.events.listen(handler, 'pointerup', eventSpy);
|
||||
simulateEvent('mousedown', 0, 0);
|
||||
simulateEvent('mouseup', 0, 0);
|
||||
expect(eventSpy.calledOnce).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('pointer move', function() {
|
||||
it('fires pointermove events', function() {
|
||||
goog.events.listen(handler, 'pointermove', eventSpy);
|
||||
simulateEvent('mousemove', 0, 0);
|
||||
expect(eventSpy.calledOnce).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('pointer enter and over', function() {
|
||||
it('fires pointerenter and pointerover events', function() {
|
||||
var enterEventSpy = sinon.spy();
|
||||
var overEventSpy = sinon.spy();
|
||||
|
||||
goog.events.listen(handler, 'pointerenter', enterEventSpy);
|
||||
goog.events.listen(handler, 'pointerover', overEventSpy);
|
||||
|
||||
simulateEvent('mouseover', 0, 0);
|
||||
|
||||
expect(enterEventSpy.calledOnce).to.be.ok();
|
||||
expect(overEventSpy.calledOnce).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('pointer leave and out', function() {
|
||||
it('fires pointerleave and pointerout events', function() {
|
||||
var leaveEventSpy = sinon.spy();
|
||||
var outEventSpy = sinon.spy();
|
||||
|
||||
goog.events.listen(handler, 'pointerleave', leaveEventSpy);
|
||||
goog.events.listen(handler, 'pointerout', outEventSpy);
|
||||
|
||||
simulateEvent('mouseout', 0, 0);
|
||||
|
||||
expect(leaveEventSpy.calledOnce).to.be.ok();
|
||||
expect(outEventSpy.calledOnce).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#cloneEvent', function() {
|
||||
it('copies the properties of an event', function() {
|
||||
var event = {
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 1,
|
||||
clientY: 2
|
||||
};
|
||||
var browserEvent = new goog.events.BrowserEvent(event);
|
||||
|
||||
var eventClone = handler.cloneEvent(browserEvent, event);
|
||||
|
||||
// properties are copied from `event`
|
||||
expect(eventClone.type).to.be('mousedown');
|
||||
expect(eventClone.target).to.be(target);
|
||||
expect(eventClone.clientX).to.be(1);
|
||||
expect(eventClone.clientY).to.be(2);
|
||||
|
||||
// properties are copied from `browserEvent`
|
||||
expect(eventClone.screenX).to.be(0);
|
||||
expect(eventClone.screenY).to.be(0);
|
||||
|
||||
// properties are copied from the defaults
|
||||
expect(eventClone.pointerId).to.be(0);
|
||||
expect(eventClone.pressure).to.be(0);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('#makeEvent', function() {
|
||||
it('makes a new pointer event', function() {
|
||||
var event = {
|
||||
type: 'mousedown',
|
||||
target: target,
|
||||
clientX: 1,
|
||||
clientY: 2
|
||||
};
|
||||
var browserEvent = new goog.events.BrowserEvent(event);
|
||||
|
||||
var eventClone = handler.cloneEvent(browserEvent, event);
|
||||
var pointerEvent = handler.makeEvent('pointerdown',
|
||||
eventClone, browserEvent);
|
||||
|
||||
expect(pointerEvent.type).to.be('pointerdown');
|
||||
expect(pointerEvent.clientX).to.be(1);
|
||||
expect(pointerEvent.clientY).to.be(2);
|
||||
|
||||
expect(pointerEvent.screenX).to.be(0);
|
||||
expect(pointerEvent.screenY).to.be(0);
|
||||
|
||||
expect(pointerEvent.pointerId).to.be(0);
|
||||
expect(pointerEvent.pressure).to.be(0);
|
||||
|
||||
expect(pointerEvent.preventDefault).to.be.ok();
|
||||
|
||||
expect(pointerEvent).to.be.a(ol.pointer.PointerEvent);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('ol.BrowserFeature');
|
||||
goog.require('ol.pointer.MouseSource');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
goog.require('ol.pointer.PointerEventHandler');
|
||||
140
test/spec/ol/pointer/touchsource.test.js
Normal file
140
test/spec/ol/pointer/touchsource.test.js
Normal file
@@ -0,0 +1,140 @@
|
||||
goog.provide('ol.test.pointer.TouchSource');
|
||||
|
||||
goog.require('goog.object');
|
||||
|
||||
describe('ol.pointer.TouchSource', function() {
|
||||
var handler;
|
||||
var target;
|
||||
var eventSpy;
|
||||
|
||||
beforeEach(function() {
|
||||
target = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
|
||||
// make sure that a mouse and touch event source is used
|
||||
ol.BrowserFeature.HAS_POINTER = false;
|
||||
ol.BrowserFeature.HAS_MSPOINTER = false;
|
||||
ol.BrowserFeature.HAS_TOUCH = true;
|
||||
|
||||
handler = new ol.pointer.PointerEventHandler(target);
|
||||
eventSpy = sinon.spy();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
handler.dispose();
|
||||
});
|
||||
|
||||
describe('pointer event creation', function() {
|
||||
it('generates pointer events for each touch contact', function() {
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
|
||||
simulateTouchEvent('touchstart', [
|
||||
{identifier: 3, clientX: 10, clientY: 11},
|
||||
{identifier: 4, clientX: 30, clientY: 45}
|
||||
]);
|
||||
|
||||
expect(eventSpy.calledTwice).to.be.ok();
|
||||
|
||||
// pointer event for the first touch contact
|
||||
var pointerEvent1 = eventSpy.firstCall.args[0];
|
||||
expect(pointerEvent1.pointerId).to.be(5);
|
||||
expect(pointerEvent1.pointerType).to.be('touch');
|
||||
expect(pointerEvent1.clientX).to.be(10);
|
||||
expect(pointerEvent1.clientY).to.be(11);
|
||||
|
||||
// pointer event for the second touch contact
|
||||
var pointerEvent2 = eventSpy.secondCall.args[0];
|
||||
expect(pointerEvent2.pointerId).to.be(6);
|
||||
expect(pointerEvent2.pointerType).to.be('touch');
|
||||
expect(pointerEvent2.clientX).to.be(30);
|
||||
expect(pointerEvent2.clientY).to.be(45);
|
||||
|
||||
expect(goog.object.getCount(handler.pointerMap)).to.be(2);
|
||||
});
|
||||
|
||||
it('creates the right pointer events', function() {
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
|
||||
// first touch
|
||||
simulateTouchEvent('touchstart', [
|
||||
{identifier: 3, clientX: 10, clientY: 11}
|
||||
]);
|
||||
expect(eventSpy.calledOnce).to.be.ok();
|
||||
expect(goog.object.getCount(handler.pointerMap)).to.be(1);
|
||||
|
||||
// second touch (first touch still down)
|
||||
simulateTouchEvent('touchstart', [
|
||||
{identifier: 4, clientX: 30, clientY: 45}
|
||||
], [{identifier: 3}, {identifier: 4}]
|
||||
);
|
||||
expect(eventSpy.calledTwice).to.be.ok();
|
||||
expect(goog.object.getCount(handler.pointerMap)).to.be(2);
|
||||
|
||||
// first touch moves
|
||||
var moveEventSpy = sinon.spy();
|
||||
goog.events.listen(handler, 'pointermove', moveEventSpy);
|
||||
|
||||
simulateTouchEvent('touchmove', [
|
||||
{identifier: 3, clientX: 15, clientY: 16}
|
||||
], [{identifier: 3}, {identifier: 4}]
|
||||
);
|
||||
expect(moveEventSpy.calledOnce).to.be.ok();
|
||||
|
||||
// and then both touches go up
|
||||
var upEventSpy = sinon.spy();
|
||||
goog.events.listen(handler, 'pointerup', upEventSpy);
|
||||
|
||||
simulateTouchEvent('touchend', [
|
||||
{identifier: 3, clientX: 15, clientY: 16},
|
||||
{identifier: 4, clientX: 30, clientY: 45}
|
||||
], [{identifier: 3}, {identifier: 4}]
|
||||
);
|
||||
expect(upEventSpy.calledTwice).to.be.ok();
|
||||
expect(goog.object.getCount(handler.pointerMap)).to.be(0);
|
||||
});
|
||||
|
||||
it('handles flawed touches', function() {
|
||||
goog.events.listen(handler, 'pointerdown', eventSpy);
|
||||
|
||||
// first touch
|
||||
simulateTouchEvent('touchstart', [
|
||||
{identifier: 3, clientX: 10, clientY: 11}
|
||||
]);
|
||||
expect(eventSpy.calledOnce).to.be.ok();
|
||||
expect(goog.object.getCount(handler.pointerMap)).to.be(1);
|
||||
|
||||
// second touch, but the first touch has disappeared
|
||||
var cancelEventSpy = sinon.spy();
|
||||
goog.events.listen(handler, 'pointercancel', cancelEventSpy);
|
||||
simulateTouchEvent('touchstart', [
|
||||
{identifier: 4, clientX: 30, clientY: 45}
|
||||
], [{identifier: 4}]
|
||||
);
|
||||
expect(eventSpy.calledTwice).to.be.ok();
|
||||
|
||||
// the first (broken) touch is canceled
|
||||
expect(cancelEventSpy.calledOnce).to.be.ok();
|
||||
expect(goog.object.getCount(handler.pointerMap)).to.be(1);
|
||||
});
|
||||
});
|
||||
|
||||
function simulateTouchEvent(type, changedTouches, touches) {
|
||||
var touches = goog.isDef(touches) ?
|
||||
touches : changedTouches;
|
||||
|
||||
var event = new goog.events.BrowserEvent({
|
||||
type: type,
|
||||
touches: touches,
|
||||
changedTouches: changedTouches
|
||||
});
|
||||
goog.events.fireListeners(target, type, false, event);
|
||||
}
|
||||
});
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.BrowserEvent');
|
||||
goog.require('ol.BrowserFeature');
|
||||
goog.require('ol.pointer.PointerEvent');
|
||||
goog.require('ol.pointer.PointerEventHandler');
|
||||
goog.require('ol.pointer.TouchSource');
|
||||
Reference in New Issue
Block a user