diff --git a/changelog.txt b/changelog.txt index 40df736f..3206e6f7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -41,11 +41,11 @@ OPENSEADRAGON CHANGELOG * Added a pinchHandler event callback, called as a pinch gesture (2 touch points) is occurring * Added real-time velocity (speed and direction) tracking to drag operations. 'speed' and 'direction' values are passed in the dragHandler and dragEndHandler event data * Enhanced Viewer for multi-touch (#369) - * Added pinch zoom with the new MouseTracker pinchHandler + * Added pinch zoom with the new MouseTracker pinchHandler. The 'pan' and 'zoom' Viewer events can be used to detect changes resulting in pinch gestures * Added a "canvas-pinch" event fired by the pinch event handler * Added flick gesture with the new MouseTracker dragEndHandler * Added a "canvas-drag-end" event fired by the drag-end event handler - * Added a GestureSettings class for per-device gesture options. Currently has settings to enable/disable zoom-on-scroll, zoom-on-click, and flick gesture settings. + * Added a GestureSettings class for per-device gesture options. Currently has settings to enable/disable zoom-on-scroll, zoom-on-pinch, zoom-on-click, and flick gesture settings. * Added GestureSettings objects for mouse, touch, and pen devices to the Viewer options giving users the ability to customize gesture handling in the viewer * Added velocity (speed and direction) properties to the "canvas-drag" event diff --git a/src/mousetracker.js b/src/mousetracker.js index a0f25a42..1d605bb8 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -2116,7 +2116,7 @@ // Only capture and track primary button, pen, and touch contacts //if ( buttonChanged !== 0 ) { - if ( buttonChanged !== 0 && buttonChanged !== 1 ) { //TODO Remove this IE8 compatibility and use the line above + if ( buttonChanged !== 0 && buttonChanged !== 1 ) { //TODO Remove this IE8 compatibility and use the commented line above return false; } @@ -2241,7 +2241,7 @@ // Only capture and track primary button, pen, and touch contacts //if ( buttonChanged !== 0 ) { - if ( buttonChanged !== 0 && buttonChanged !== 1 ) { //TODO Remove this IE8 compatibility and use the line above + if ( buttonChanged !== 0 && buttonChanged !== 1 ) { //TODO Remove this IE8 compatibility and use the commented line above return false; } @@ -2570,7 +2570,8 @@ * Gesture points associated with the event. */ function updatePointersCancel( tracker, event, gPoints ) { - //removePointers( tracker, event, gPoints ); + updatePointersUp( tracker, event, gPoints, 0 ); + updatePointersExit( tracker, event, gPoints ); } diff --git a/src/openseadragon.js b/src/openseadragon.js index b42162bb..c7f69749 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -284,6 +284,7 @@ * Settings for gestures generated by a mouse pointer device. (See {@link OpenSeadragon.GestureSettings}) * @property {Boolean} [gestureSettingsMouse.scrollToZoom=true] - Zoom on scroll gesture * @property {Boolean} [gestureSettingsMouse.clickToZoom=true] - Zoom on click gesture + * @property {Boolean} [gestureSettingsMouse.pinchToZoom=false] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsMouse.flickEnabled=false] - Enable flick gesture * @property {Number} [gestureSettingsMouse.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) * @property {Number} [gestureSettingsMouse.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture @@ -292,6 +293,7 @@ * Settings for gestures generated by a touch pointer device. (See {@link OpenSeadragon.GestureSettings}) * @property {Boolean} [gestureSettingsTouch.scrollToZoom=false] - Zoom on scroll gesture * @property {Boolean} [gestureSettingsTouch.clickToZoom=false] - Zoom on click gesture + * @property {Boolean} [gestureSettingsTouch.pinchToZoom=true] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsTouch.flickEnabled=true] - Enable flick gesture * @property {Number} [gestureSettingsTouch.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) * @property {Number} [gestureSettingsTouch.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture @@ -300,6 +302,7 @@ * Settings for gestures generated by a pen pointer device. (See {@link OpenSeadragon.GestureSettings}) * @property {Boolean} [gestureSettingsPen.scrollToZoom=false] - Zoom on scroll gesture * @property {Boolean} [gestureSettingsPen.clickToZoom=true] - Zoom on click gesture + * @property {Boolean} [gestureSettingsPen.pinchToZoom=false] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsPen.flickEnabled=false] - Enable flick gesture * @property {Number} [gestureSettingsPen.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) * @property {Number} [gestureSettingsPen.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture @@ -308,6 +311,7 @@ * Settings for gestures generated by unknown pointer devices. (See {@link OpenSeadragon.GestureSettings}) * @property {Boolean} [gestureSettingsUnknown.scrollToZoom=true] - Zoom on scroll gesture * @property {Boolean} [gestureSettingsUnknown.clickToZoom=false] - Zoom on click gesture + * @property {Boolean} [gestureSettingsUnknown.pinchToZoom=true] - Zoom on pinch gesture * @property {Boolean} [gestureSettingsUnknown.flickEnabled=true] - Enable flick gesture * @property {Number} [gestureSettingsUnknown.flickMinSpeed=20] - If flickEnabled is true, the minimum speed to initiate a flick gesture (pixels-per-second) * @property {Number} [gestureSettingsUnknown.flickMomentum=0.40] - If flickEnabled is true, the momentum factor for the flick gesture @@ -530,6 +534,9 @@ * @property {Boolean} clickToZoom * Set to false to disable zooming on click gestures. * + * @property {Boolean} pinchToZoom + * Set to false to disable zooming on pinch gestures. + * * @property {Boolean} flickEnabled * Set to false to disable the kinetic panning effect (flick) at the end of a drag gesture. * @@ -886,10 +893,10 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ clickDistThreshold: 5, springStiffness: 5.0, animationTime: 1.2, - gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 }, - gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 }, - gestureSettingsPen: { scrollToZoom: false, clickToZoom: true, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 }, - gestureSettingsUnknown: { scrollToZoom: false, clickToZoom: false, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 }, + gestureSettingsMouse: { scrollToZoom: true, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 }, + gestureSettingsTouch: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 }, + gestureSettingsPen: { scrollToZoom: false, clickToZoom: true, pinchToZoom: false, flickEnabled: false, flickMinSpeed: 20, flickMomentum: 0.40 }, + gestureSettingsUnknown: { scrollToZoom: false, clickToZoom: false, pinchToZoom: true, flickEnabled: true, flickMinSpeed: 20, flickMomentum: 0.40 }, zoomPerClick: 2, zoomPerScroll: 1.2, zoomPerSecond: 1.0, diff --git a/src/viewer.js b/src/viewer.js index c451dace..bd01afe3 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -2383,12 +2383,17 @@ function onCanvasRelease( event ) { } function onCanvasPinch( event ) { + var gestureSettings; + if ( !event.preventDefaultAction && this.viewport ) { - var centerPt = this.viewport.pointFromPixel( event.center, true ), - lastCenterPt = this.viewport.pointFromPixel( event.lastCenter, true ); - this.viewport.zoomBy( event.distance / event.lastDistance, centerPt, true ); - this.viewport.panBy( lastCenterPt.minus( centerPt ), true ); - this.viewport.applyConstraints(); + gestureSettings = this.gestureSettingsByDeviceType( event.pointerType ); + if ( gestureSettings.pinchToZoom ) { + var centerPt = this.viewport.pointFromPixel( event.center, true ), + lastCenterPt = this.viewport.pointFromPixel( event.lastCenter, true ); + this.viewport.zoomBy( event.distance / event.lastDistance, centerPt, true ); + this.viewport.panBy( lastCenterPt.minus( centerPt ), true ); + this.viewport.applyConstraints(); + } } /** * Raised when a pinch event occurs on the {@link OpenSeadragon.Viewer#canvas} element. diff --git a/test/events.js b/test/events.js index 5809ec4d..d56fbf44 100644 --- a/test/events.js +++ b/test/events.js @@ -144,19 +144,31 @@ tracker.dragEndHandler = origDragEndHandler; }; - var simulateEnter = function ($element, x, y) { + var simulateEnter = function (x, y) { simEvent.clientX = offset.left + x; simEvent.clientY = offset.top + y; $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseenter' : 'mouseover', simEvent ); }; - var simulateLeave = function ($element, x, y) { + var simulateLeave = function (x, y) { simEvent.clientX = offset.left + x; simEvent.clientY = offset.top + y; $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent ); }; - var simulateMove = function ($element, dX, dY, count) { + var simulateDown = function (x, y) { + simEvent.clientX = offset.left + x; + simEvent.clientY = offset.top + y; + $canvas.simulate( 'mousedown', simEvent ); + }; + + var simulateUp = function (x, y) { + simEvent.clientX = offset.left + x; + simEvent.clientY = offset.top + y; + $canvas.simulate( 'mouseup', simEvent ); + }; + + var simulateMove = function (dX, dY, count) { var i; for ( i = 0; i < count; i++ ) { simEvent.clientX += dX; @@ -165,50 +177,6 @@ } }; - var simulateTimedMove = function ($element, dX, dY, count, ms, doneCallback) { - var msInterval = Math.floor(ms / count), - dX = dX, - dY = dY, - i = count, - doneCallback = doneCallback, - moves = 0; - - intervalId = window.setInterval(function () { - if (i > 0) { - moves++; - //simEvent.clientX += dX; - //simEvent.clientY += dY; - //$canvas.simulate( 'mousemove', simEvent ); - } - i--; - if (i === 0) { - window.clearInterval( intervalId ); - doneCallback(); - } - }, msInterval ); - - - //for ( i = 0; i < count; i++ ) { - // simEvent.clientX += dX; - // simEvent.clientY += dY; - // $canvas.simulate( 'mousemove', simEvent ); - // targetTime = msWait + OpenSeadragon.now(); - // while (OpenSeadragon.now() < targetTime) {} - //} - }; - - var simulateDown = function ($element, x, y) { - simEvent.clientX = offset.left + x; - simEvent.clientY = offset.top + y; - $canvas.simulate( 'mousedown', simEvent ); - }; - - var simulateUp = function ($element, x, y) { - simEvent.clientX = offset.left + x; - simEvent.clientY = offset.top + y; - $canvas.simulate( 'mouseup', simEvent ); - }; - var resetForAssessment = function () { simEvent = { clientX: offset.left, @@ -271,10 +239,10 @@ equal( quickClick, expected.quickClick, expected.description + 'clickHandler event.quick matches expected (' + expected.quickClick + ')' ); } if ('speed' in expected) { - equal( speed, expected.speed, expected.description + 'Drag speed matches expected (' + expected.speed + ')' ); + Util.assessNumericValue(expected.speed, speed, 1.0, expected.description + 'Drag speed '); } if ('direction' in expected) { - equal( direction, expected.direction, expected.description + 'Drag direction matches expected (' + expected.direction + ')' ); + Util.assessNumericValue(expected.direction, direction, 0.2, expected.description + 'Drag direction '); } }; @@ -289,10 +257,10 @@ // enter-move-release (release in tracked element, press in unknown element) // (Note we also test to see if the pointer is still being tracked by not simulating a leave event until after assessment) resetForAssessment(); - simulateEnter($canvas, 0, 0); - simulateMove($canvas, 1, 1, 10); - simulateMove($canvas, -1, -1, 10); - simulateUp($canvas, 0, 0); + simulateEnter(0, 0); + simulateMove(1, 1, 10); + simulateMove(-1, -1, 10); + simulateUp(0, 0); assessGestureExpectations({ description: 'enter-move-release (release in tracked element, press in unknown element): ', enterCount: 1, @@ -309,14 +277,14 @@ trackedPointers: 1 //quickClick: false }); - simulateLeave($canvas, -1, -1); // flush tracked pointer + simulateLeave(-1, -1); // flush tracked pointer // enter-move-exit (fly-over) resetForAssessment(); - simulateEnter($canvas, 0, 0); - simulateMove($canvas, 1, 1, 10); - simulateMove($canvas, -1, -1, 10); - simulateLeave($canvas, -1, -1); + simulateEnter(0, 0); + simulateMove(1, 1, 10); + simulateMove(-1, -1, 10); + simulateLeave(-1, -1); assessGestureExpectations({ description: 'enter-move-exit (fly-over): ', enterCount: 1, @@ -336,9 +304,9 @@ // move-exit (fly-over, no enter event) resetForAssessment(); - simulateMove($canvas, 1, 1, 10); - simulateMove($canvas, -1, -1, 10); - simulateLeave($canvas, -1, -1); + simulateMove(1, 1, 10); + simulateMove(-1, -1, 10); + simulateLeave(-1, -1); assessGestureExpectations({ description: 'move-exit (fly-over, no enter event): ', enterCount: 0, @@ -358,10 +326,10 @@ // enter-press-release-exit resetForAssessment(); - simulateEnter($canvas, 0, 0); - simulateDown($canvas, 0, 0); - simulateUp($canvas, 0, 0); - simulateLeave($canvas, -1, -1); + simulateEnter(0, 0); + simulateDown(0, 0); + simulateUp(0, 0); + simulateLeave(-1, -1); assessGestureExpectations({ description: 'enter-press-release-exit (click): ', enterCount: 1, @@ -381,12 +349,12 @@ // enter-press-move-release-move-exit (drag, release in tracked element) resetForAssessment(); - simulateEnter($canvas, 0, 0); - simulateDown($canvas, 0, 0); - simulateMove($canvas, 1, 1, 100); - simulateUp($canvas, 10, 10); - simulateMove($canvas, -1, -1, 100); - simulateLeave($canvas, -1, -1); + simulateEnter(0, 0); + simulateDown(0, 0); + simulateMove(1, 1, 100); + simulateUp(10, 10); + simulateMove(-1, -1, 100); + simulateLeave(-1, -1); assessGestureExpectations({ description: 'enter-press-move-release-move-exit (drag, release in tracked element): ', enterCount: 1, @@ -406,13 +374,13 @@ // enter-press-move-exit-move-release (drag, release outside tracked element) resetForAssessment(); - simulateEnter($canvas, 0, 0); - simulateDown($canvas, 0, 0); - simulateMove($canvas, 1, 1, 5); - simulateMove($canvas, -1, -1, 5); - simulateLeave($canvas, -1, -1); - simulateMove($canvas, -1, -1, 5); - simulateUp($canvas, -5, -5); + simulateEnter(0, 0); + simulateDown(0, 0); + simulateMove(1, 1, 5); + simulateMove(-1, -1, 5); + simulateLeave(-1, -1); + simulateMove(-1, -1, 5); + simulateUp(-5, -5); assessGestureExpectations({ description: 'enter-press-move-exit-move-release (drag, release outside tracked element): ', enterCount: 1,