finished support for touch events, works great on the ipad, a little slow on iphone (I think we can scale drag and zoom better based on viewport size). Awesome

This commit is contained in:
thatcher 2012-02-09 22:16:09 -05:00
parent 1739294700
commit 05b8cb82fd
5 changed files with 363 additions and 59 deletions

View File

@ -5,8 +5,8 @@
PROJECT: openseadragon
BUILD_MAJOR: 0
BUILD_MINOR: 8
BUILD_ID: 27
BUILD_MINOR: 9
BUILD_ID: 01
BUILD: ${PROJECT}.${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}
VERSION: ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}

View File

@ -1,5 +1,5 @@
/**
* @version OpenSeadragon 0.8.27
* @version OpenSeadragon 0.9.01
*
* @fileOverview
* <h2>
@ -371,8 +371,17 @@ OpenSeadragon = window.OpenSeadragon || (function(){
* function when console is unavailable.
* @static
*/
$.console = window.console ? window.console : function(){};
var nullfunction = function( msg ){
//document.location.hash = msg;
};
$.console = window.console || {
log: nullfunction,
debug: nullfunction,
info: nullfunction,
warn: nullfunction,
error: nullfunction
};
$.extend( $, {
@ -384,7 +393,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){
* @returns {Element} The element with the given id, null, or the element itself.
*/
getElement: function( element ) {
if ( typeof ( element ) == "string") {
if ( typeof ( element ) == "string" ) {
element = document.getElementById( element );
}
return element;
@ -1373,24 +1382,28 @@ $.EventHandler.prototype = {
* Position of last mouse down
*/
THIS[ this.hash ] = {
"mouseover": function( event ){ onMouseOver( _this, event ); },
"mouseout": function( event ){ onMouseOut( _this, event ); },
"mousedown": function( event ){ onMouseDown( _this, event ); },
"mouseup": function( event ){ onMouseUp( _this, event ); },
"click": function( event ){ onMouseClick( _this, event ); },
"DOMMouseScroll": function( event ){ onMouseWheelSpin( _this, event ); },
"mousewheel": function( event ){ onMouseWheelSpin( _this, event ); },
"mouseupie": function( event ){ onMouseUpIE( _this, event ); },
"mousemoveie": function( event ){ onMouseMoveIE( _this, event ); },
"mouseupwindow": function( event ){ onMouseUpWindow( _this, event ); },
"mousemove": function( event ){ onMouseMove( _this, event ); },
tracking : false,
capturing : false,
buttonDown : false,
insideElement : false,
lastPoint : null,
lastMouseDownTime : null,
lastMouseDownPoint : null
"mouseover": function( event ){ onMouseOver( _this, event ); },
"mouseout": function( event ){ onMouseOut( _this, event ); },
"mousedown": function( event ){ onMouseDown( _this, event ); },
"mouseup": function( event ){ onMouseUp( _this, event ); },
"click": function( event ){ onMouseClick( _this, event ); },
"DOMMouseScroll": function( event ){ onMouseWheelSpin( _this, event ); },
"mousewheel": function( event ){ onMouseWheelSpin( _this, event ); },
"mouseupie": function( event ){ onMouseUpIE( _this, event ); },
"mousemoveie": function( event ){ onMouseMoveIE( _this, event ); },
"mouseupwindow": function( event ){ onMouseUpWindow( _this, event ); },
"mousemove": function( event ){ onMouseMove( _this, event ); },
"touchstart": function( event ){ onTouchStart( _this, event ); },
"touchmove": function( event ){ onTouchMove( _this, event ); },
"touchend": function( event ){ onTouchEnd( _this, event ); },
tracking: false,
capturing: false,
buttonDown: false,
insideElement: false,
lastPoint: null,
lastMouseDownTime: null,
lastMouseDownPoint: null,
lastPinchDelta: 0
};
};
@ -1539,8 +1552,10 @@ $.EventHandler.prototype = {
*/
function startTracking( tracker ) {
var events = [
"mouseover", "mouseout", "mousedown", "mouseup", "click",
"DOMMouseScroll", "mousewheel"
"mouseover", "mouseout", "mousedown", "mouseup",
"click",
"DOMMouseScroll", "mousewheel",
"touchstart", "touchmove", "touchend"
],
delegate = THIS[ tracker.hash ],
event,
@ -1568,8 +1583,10 @@ $.EventHandler.prototype = {
*/
function stopTracking( tracker ) {
var events = [
"mouseover", "mouseout", "mousedown", "mouseup", "click",
"DOMMouseScroll", "mousewheel"
"mouseover", "mouseout", "mousedown", "mouseup",
"click",
"DOMMouseScroll", "mousewheel",
"touchstart", "touchmove", "touchend"
],
delegate = THIS[ tracker.hash ],
event,
@ -1693,6 +1710,7 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
@ -1706,11 +1724,13 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
*/
function onMouseOver( tracker, event ) {
var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ];
@ -1755,6 +1775,7 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
@ -1804,6 +1825,7 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
@ -1853,6 +1875,38 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
*/
function onTouchStart( tracker, event ) {
var touchA,
touchB;
window.location.hash = event.touches[ 0 ].target.tagName;
if( event.touches.length == 1 &&
event.targetTouches.length == 1 &&
event.changedTouches.length == 1 ){
THIS[ tracker.hash ].lastTouch = event.touches[ 0 ];
onMouseOver( tracker, event.changedTouches[ 0 ] );
onMouseDown( tracker, event.touches[ 0 ] );
}
if( event.touches.length == 2 ){
touchA = getMouseAbsolute( event.touches[ 0 ] );
touchB = getMouseAbsolute( event.touches[ 1 ] );
THIS[ tracker.hash ].lastPinchDelta =
Math.abs( touchA.x - touchB.x ) +
Math.abs( touchA.y - touchB.y );
//$.console.debug("pinch start : "+THIS[ tracker.hash ].lastPinchDelta);
}
event.preventDefault();
};
/**
* @private
* @inner
@ -1894,6 +1948,29 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
*/
function onTouchEnd( tracker, event ) {
if( event.touches.length == 0 &&
event.targetTouches.length == 0 &&
event.changedTouches.length == 1 ){
THIS[ tracker.hash ].lastTouch = null;
onMouseUp( tracker, event.changedTouches[ 0 ] );
onMouseOut( tracker, event.changedTouches[ 0 ] );
}
if( event.touches.length + event.changedTouches.length == 2 ){
THIS[ tracker.hash ].lastPinchDelta = null;
//$.console.debug("pinch end");
}
event.preventDefault();
};
/**
* Only triggered once by the deepest element that initially received
* the mouse down event. We want to make sure THIS event doesn't bubble.
@ -1930,6 +2007,7 @@ $.EventHandler.prototype = {
$.stopEvent( event );
};
/**
* Only triggered in W3C browsers by elements within which the mouse was
* initially pressed, since they are now listening to the window for
@ -1946,6 +2024,7 @@ $.EventHandler.prototype = {
releaseMouse( tracker );
};
/**
* @private
* @inner
@ -1956,6 +2035,7 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
@ -1975,7 +2055,9 @@ $.EventHandler.prototype = {
} else if (event.detail) { // Mozilla FireFox
nDelta = -event.detail;
}
//The nDelta variable is gated to provide smooth z-index scrolling
//since the mouse wheel allows for substantial deltas meant for rapid
//y-index scrolling.
nDelta = nDelta > 0 ? 1 : -1;
if ( tracker.scrollHandler ) {
@ -1999,6 +2081,7 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
@ -2036,6 +2119,7 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
@ -2069,6 +2153,50 @@ $.EventHandler.prototype = {
}
};
/**
* @private
* @inner
*/
function onTouchMove( tracker, event ) {
var touchA,
touchB,
pinchDelta;
if( event.touches.length === 1 &&
event.targetTouches.length === 1 &&
event.changedTouches.length === 1 &&
THIS[ tracker.hash ].lastTouch === event.touches[ 0 ]){
onMouseMove( tracker, event.touches[ 0 ] );
} else if ( event.touches.length === 2 ){
touchA = getMouseAbsolute( event.touches[ 0 ] );
touchB = getMouseAbsolute( event.touches[ 1 ] );
pinchDelta =
Math.abs( touchA.x - touchB.x ) +
Math.abs( touchA.y - touchB.y );
//TODO: make the 75px pinch threshold configurable
if( Math.abs( THIS[ tracker.hash ].lastPinchDelta - pinchDelta ) > 75 ){
//$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta);
onMouseWheelSpin( tracker, {
shift: false,
pageX: ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2,
pageY: ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2,
detail:(
THIS[ tracker.hash ].lastPinchDelta > pinchDelta
) ? 1 : -1
});
THIS[ tracker.hash ].lastPinchDelta = pinchDelta;
}
}
event.preventDefault();
};
/**
* Only triggered once by the deepest element that initially received
* the mouse down event. Since no other element has captured the mouse,
@ -2390,6 +2518,7 @@ $.Viewer = function( options ) {
this.bodyHeight = document.body.style.height;
this.bodyOverflow = document.body.style.overflow;
this.docOverflow = document.documentElement.style.overflow;
this.previousBody = [];
this._fsBoundsDelta = new $.Point( 1, 1 );
this._prevContainerSize = null;
@ -2815,8 +2944,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
},
/**
* Toggle full page mode.
* @function
* @name OpenSeadragon.Viewer.prototype.setFullPage
* @param {Boolean} fullPage
* If true, enter full page mode. If false, exit full page mode.
*/
setFullPage: function( fullPage ) {
@ -2826,8 +2958,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
containerStyle = this.container.style,
canvasStyle = this.canvas.style,
oldBounds,
newBounds;
newBounds,
nodes,
i;
//dont bother modifying the DOM if we are already in full page mode.
if ( fullPage == this.isFullPage() ) {
return;
}
@ -2850,12 +2985,24 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
containerStyle.position = "fixed";
containerStyle.zIndex = "99999999";
//when entering full screen on the ipad it wasnt sufficient to leave
//the body intact as only only the top half of the screen would
//respond to touch events on the canvas, while the bottom half treated
//them as touch events on the document body. Thus we remove and store
//the bodies elements and replace them when we leave full screen.
this.previousBody = [];
nodes = document.body.childNodes.length;
for ( i = 0; i < nodes; i ++ ){
this.previousBody.push( document.body.childNodes[ 0 ] );
document.body.removeChild( document.body.childNodes[ 0 ] );
}
body.appendChild( this.container );
this._prevContainerSize = $.getWindowSize();
// mouse will be inside container now
$.delegate( this, onContainerEnter )();
} else {
bodyStyle.overflow = this.bodyOverflow;
@ -2870,6 +3017,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
containerStyle.position = "relative";
containerStyle.zIndex = "";
document.body.removeChild( this.container );
nodes = this.previousBody.length;
for ( i = 0; i < nodes; i++ ){
document.body.appendChild( this.previousBody.shift() );
}
this.element.appendChild( this.container );
this._prevContainerSize = $.getElementSize( this.element );

View File

@ -104,24 +104,28 @@
* Position of last mouse down
*/
THIS[ this.hash ] = {
"mouseover": function( event ){ onMouseOver( _this, event ); },
"mouseout": function( event ){ onMouseOut( _this, event ); },
"mousedown": function( event ){ onMouseDown( _this, event ); },
"mouseup": function( event ){ onMouseUp( _this, event ); },
"click": function( event ){ onMouseClick( _this, event ); },
"DOMMouseScroll": function( event ){ onMouseWheelSpin( _this, event ); },
"mousewheel": function( event ){ onMouseWheelSpin( _this, event ); },
"mouseupie": function( event ){ onMouseUpIE( _this, event ); },
"mousemoveie": function( event ){ onMouseMoveIE( _this, event ); },
"mouseupwindow": function( event ){ onMouseUpWindow( _this, event ); },
"mousemove": function( event ){ onMouseMove( _this, event ); },
tracking : false,
capturing : false,
buttonDown : false,
insideElement : false,
lastPoint : null,
lastMouseDownTime : null,
lastMouseDownPoint : null
"mouseover": function( event ){ onMouseOver( _this, event ); },
"mouseout": function( event ){ onMouseOut( _this, event ); },
"mousedown": function( event ){ onMouseDown( _this, event ); },
"mouseup": function( event ){ onMouseUp( _this, event ); },
"click": function( event ){ onMouseClick( _this, event ); },
"DOMMouseScroll": function( event ){ onMouseWheelSpin( _this, event ); },
"mousewheel": function( event ){ onMouseWheelSpin( _this, event ); },
"mouseupie": function( event ){ onMouseUpIE( _this, event ); },
"mousemoveie": function( event ){ onMouseMoveIE( _this, event ); },
"mouseupwindow": function( event ){ onMouseUpWindow( _this, event ); },
"mousemove": function( event ){ onMouseMove( _this, event ); },
"touchstart": function( event ){ onTouchStart( _this, event ); },
"touchmove": function( event ){ onTouchMove( _this, event ); },
"touchend": function( event ){ onTouchEnd( _this, event ); },
tracking: false,
capturing: false,
buttonDown: false,
insideElement: false,
lastPoint: null,
lastMouseDownTime: null,
lastMouseDownPoint: null,
lastPinchDelta: 0
};
};
@ -270,8 +274,10 @@
*/
function startTracking( tracker ) {
var events = [
"mouseover", "mouseout", "mousedown", "mouseup", "click",
"DOMMouseScroll", "mousewheel"
"mouseover", "mouseout", "mousedown", "mouseup",
"click",
"DOMMouseScroll", "mousewheel",
"touchstart", "touchmove", "touchend"
],
delegate = THIS[ tracker.hash ],
event,
@ -299,8 +305,10 @@
*/
function stopTracking( tracker ) {
var events = [
"mouseover", "mouseout", "mousedown", "mouseup", "click",
"DOMMouseScroll", "mousewheel"
"mouseover", "mouseout", "mousedown", "mouseup",
"click",
"DOMMouseScroll", "mousewheel",
"touchstart", "touchmove", "touchend"
],
delegate = THIS[ tracker.hash ],
event,
@ -424,6 +432,7 @@
}
};
/**
* @private
* @inner
@ -437,11 +446,13 @@
}
};
/**
* @private
* @inner
*/
function onMouseOver( tracker, event ) {
var event = $.getEvent( event ),
delegate = THIS[ tracker.hash ];
@ -486,6 +497,7 @@
}
};
/**
* @private
* @inner
@ -535,6 +547,7 @@
}
};
/**
* @private
* @inner
@ -584,6 +597,38 @@
}
};
/**
* @private
* @inner
*/
function onTouchStart( tracker, event ) {
var touchA,
touchB;
window.location.hash = event.touches[ 0 ].target.tagName;
if( event.touches.length == 1 &&
event.targetTouches.length == 1 &&
event.changedTouches.length == 1 ){
THIS[ tracker.hash ].lastTouch = event.touches[ 0 ];
onMouseOver( tracker, event.changedTouches[ 0 ] );
onMouseDown( tracker, event.touches[ 0 ] );
}
if( event.touches.length == 2 ){
touchA = getMouseAbsolute( event.touches[ 0 ] );
touchB = getMouseAbsolute( event.touches[ 1 ] );
THIS[ tracker.hash ].lastPinchDelta =
Math.abs( touchA.x - touchB.x ) +
Math.abs( touchA.y - touchB.y );
//$.console.debug("pinch start : "+THIS[ tracker.hash ].lastPinchDelta);
}
event.preventDefault();
};
/**
* @private
* @inner
@ -625,6 +670,29 @@
}
};
/**
* @private
* @inner
*/
function onTouchEnd( tracker, event ) {
if( event.touches.length == 0 &&
event.targetTouches.length == 0 &&
event.changedTouches.length == 1 ){
THIS[ tracker.hash ].lastTouch = null;
onMouseUp( tracker, event.changedTouches[ 0 ] );
onMouseOut( tracker, event.changedTouches[ 0 ] );
}
if( event.touches.length + event.changedTouches.length == 2 ){
THIS[ tracker.hash ].lastPinchDelta = null;
//$.console.debug("pinch end");
}
event.preventDefault();
};
/**
* Only triggered once by the deepest element that initially received
* the mouse down event. We want to make sure THIS event doesn't bubble.
@ -661,6 +729,7 @@
$.stopEvent( event );
};
/**
* Only triggered in W3C browsers by elements within which the mouse was
* initially pressed, since they are now listening to the window for
@ -677,6 +746,7 @@
releaseMouse( tracker );
};
/**
* @private
* @inner
@ -687,6 +757,7 @@
}
};
/**
* @private
* @inner
@ -706,7 +777,9 @@
} else if (event.detail) { // Mozilla FireFox
nDelta = -event.detail;
}
//The nDelta variable is gated to provide smooth z-index scrolling
//since the mouse wheel allows for substantial deltas meant for rapid
//y-index scrolling.
nDelta = nDelta > 0 ? 1 : -1;
if ( tracker.scrollHandler ) {
@ -730,6 +803,7 @@
}
};
/**
* @private
* @inner
@ -767,6 +841,7 @@
}
};
/**
* @private
* @inner
@ -800,6 +875,50 @@
}
};
/**
* @private
* @inner
*/
function onTouchMove( tracker, event ) {
var touchA,
touchB,
pinchDelta;
if( event.touches.length === 1 &&
event.targetTouches.length === 1 &&
event.changedTouches.length === 1 &&
THIS[ tracker.hash ].lastTouch === event.touches[ 0 ]){
onMouseMove( tracker, event.touches[ 0 ] );
} else if ( event.touches.length === 2 ){
touchA = getMouseAbsolute( event.touches[ 0 ] );
touchB = getMouseAbsolute( event.touches[ 1 ] );
pinchDelta =
Math.abs( touchA.x - touchB.x ) +
Math.abs( touchA.y - touchB.y );
//TODO: make the 75px pinch threshold configurable
if( Math.abs( THIS[ tracker.hash ].lastPinchDelta - pinchDelta ) > 75 ){
//$.console.debug( "pinch delta : " + pinchDelta + " | previous : " + THIS[ tracker.hash ].lastPinchDelta);
onMouseWheelSpin( tracker, {
shift: false,
pageX: ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2,
pageY: ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2,
detail:(
THIS[ tracker.hash ].lastPinchDelta > pinchDelta
) ? 1 : -1
});
THIS[ tracker.hash ].lastPinchDelta = pinchDelta;
}
}
event.preventDefault();
};
/**
* Only triggered once by the deepest element that initially received
* the mouse down event. Since no other element has captured the mouse,

View File

@ -371,8 +371,17 @@ OpenSeadragon = window.OpenSeadragon || (function(){
* function when console is unavailable.
* @static
*/
$.console = window.console ? window.console : function(){};
var nullfunction = function( msg ){
//document.location.hash = msg;
};
$.console = window.console || {
log: nullfunction,
debug: nullfunction,
info: nullfunction,
warn: nullfunction,
error: nullfunction
};
$.extend( $, {
@ -384,7 +393,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){
* @returns {Element} The element with the given id, null, or the element itself.
*/
getElement: function( element ) {
if ( typeof ( element ) == "string") {
if ( typeof ( element ) == "string" ) {
element = document.getElementById( element );
}
return element;

View File

@ -132,6 +132,7 @@ $.Viewer = function( options ) {
this.bodyHeight = document.body.style.height;
this.bodyOverflow = document.body.style.overflow;
this.docOverflow = document.documentElement.style.overflow;
this.previousBody = [];
this._fsBoundsDelta = new $.Point( 1, 1 );
this._prevContainerSize = null;
@ -557,8 +558,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
},
/**
* Toggle full page mode.
* @function
* @name OpenSeadragon.Viewer.prototype.setFullPage
* @param {Boolean} fullPage
* If true, enter full page mode. If false, exit full page mode.
*/
setFullPage: function( fullPage ) {
@ -568,8 +572,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
containerStyle = this.container.style,
canvasStyle = this.canvas.style,
oldBounds,
newBounds;
newBounds,
nodes,
i;
//dont bother modifying the DOM if we are already in full page mode.
if ( fullPage == this.isFullPage() ) {
return;
}
@ -592,12 +599,24 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
containerStyle.position = "fixed";
containerStyle.zIndex = "99999999";
//when entering full screen on the ipad it wasnt sufficient to leave
//the body intact as only only the top half of the screen would
//respond to touch events on the canvas, while the bottom half treated
//them as touch events on the document body. Thus we remove and store
//the bodies elements and replace them when we leave full screen.
this.previousBody = [];
nodes = document.body.childNodes.length;
for ( i = 0; i < nodes; i ++ ){
this.previousBody.push( document.body.childNodes[ 0 ] );
document.body.removeChild( document.body.childNodes[ 0 ] );
}
body.appendChild( this.container );
this._prevContainerSize = $.getWindowSize();
// mouse will be inside container now
$.delegate( this, onContainerEnter )();
} else {
bodyStyle.overflow = this.bodyOverflow;
@ -612,6 +631,11 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, {
containerStyle.position = "relative";
containerStyle.zIndex = "";
document.body.removeChild( this.container );
nodes = this.previousBody.length;
for ( i = 0; i < nodes; i++ ){
document.body.appendChild( this.previousBody.shift() );
}
this.element.appendChild( this.container );
this._prevContainerSize = $.getElementSize( this.element );