diff --git a/README.md b/README.md index 1d0cd8b..6d3d29d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ var mytraqball = new Traqball(configurationObject); ``` js { - stage: "stage", // id of block element. String, default value: + stage: "stage", // id (String) of block element or selected DOM-Element. Default value: + activationElement: "stage", // DOM-Element that catches the events. Default value: first child of stage (the rotating element) axis: [0.5,1,0.25], // X,Y,Z values of initial rotation vector. Array, default value: [1,0,0] angle: 0.12, // Initial rotation angle in radian. Float, default value: 0. perspective: perspectiveValue, // Perspective. Integer, default value 700. diff --git a/demo/js/traqball.js b/demo/js/traqball.js index aa72ca6..c70f021 100644 --- a/demo/js/traqball.js +++ b/demo/js/traqball.js @@ -10,6 +10,10 @@ (function(){ var userAgent = navigator.userAgent.toLowerCase(), + startEvent = document.createEvent('HTMLEvents'), + rotateEvent = document.createEvent('HTMLEvents'), + releaseEvent = document.createEvent('HTMLEvents'), + fullStopEvent = document.createEvent('HTMLEvents'), canTouch = "ontouchstart" in window, prefix = cssPref = "", requestAnimFrame, cancelAnimFrame; @@ -29,7 +33,12 @@ }else{ prefix = ""; } - + + startEvent.initEvent("traqballStartRotate", true, true); + rotateEvent.initEvent("traqballRotate", true, true); + releaseEvent.initEvent("traqballRelease", true, true); + fullStopEvent.initEvent("traqballFullStop", true, true); + function bindEvent(target, type, callback, remove){ //translate events var evType = type || "touchend", @@ -79,7 +88,9 @@ })(); var Traqball = function(confObj){ - this.config = {}; + this.config = { + stage: document.body + }; this.box = null; this.setup(confObj); @@ -87,7 +98,7 @@ Traqball.prototype.disable = function(){ if(this.box !== null){ - bindEvent(this.box, 'touchstart', this.evHandlers[0], "remove"); + bindEvent(this.config.activationArea, 'touchstart', this.evHandlers[0], "remove"); bindEvent(document, 'touchmove', this.evHandlers[1], "remove"); bindEvent(document, 'touchend', this.evHandlers[2], "remove"); } @@ -95,7 +106,7 @@ Traqball.prototype.activate = function(){ if(this.box !== null){ - bindEvent(this.box, 'touchstart', this.evHandlers[0]); + bindEvent(this.config.activationArea, 'touchstart', this.evHandlers[0]); bindEvent(document, 'touchmove', this.evHandlers[1], "remove"); bindEvent(document, 'touchend', this.evHandlers[2], "remove"); } @@ -118,8 +129,11 @@ for(var prop in conf){ THIS.config[prop] = conf[prop]; } - - stage = document.getElementById(THIS.config.stage) || document.getElementsByTagname("body")[0]; + + if (typeof THIS.config.stage === 'string') { + THIS.config.stage = document.getElementById(THIS.config.stage); + } + stage = THIS.config.stage; pos = findPos(stage); angle = THIS.config.angle || 0; impulse = THIS.config.impulse === false ? false : true; @@ -141,6 +155,9 @@ break; } } + if (typeof THIS.config.activationArea === 'undefined') { + THIS.config.activationArea = THIS.box; + } var perspective = getStyle(stage, prefix+"perspective"), pOrigin = getStyle(stage, prefix+"perspective-origin"), @@ -207,8 +224,10 @@ mouseDownVect = calcZvector(getCoords(e)); oldTime = curTime = new Date().getTime(); oldAngle = angle; - - bindEvent(THIS.box,'touchstart', startrotation, "remove"); + + THIS.box.dispatchEvent(startEvent); + + bindEvent(THIS.config.activationArea,'touchstart', startrotation, "remove"); bindEvent(document, 'touchmove', rotate); bindEvent(document, 'touchend', finishrotation); } @@ -218,8 +237,11 @@ bindEvent(document, 'touchmove', rotate, "remove"); bindEvent(document, 'touchend', finishrotation, "remove"); - bindEvent(THIS.box, 'touchstart', startrotation); + bindEvent(THIS.config.activationArea, 'touchstart', startrotation); calcSpeed(); + + THIS.box.dispatchEvent(releaseEvent); + if( impulse && delta > 0){ requestAnimFrame(slide); }else if(!(isNaN(axis[0]) || isNaN(axis[1]) || isNaN(axis[2]))) { @@ -264,7 +286,9 @@ //Only one thing left to do: Update the position of the box by applying a new transform: // 2 transforms will be applied: the current rotation 3d and the start-matrix THIS.box.style[cssPref+"Transform"] = "rotate3d("+ axis+","+angle+"rad) matrix3d("+startMatrix+")"; - + rotateEvent.data = {axis: axis, angle: angle}; + THIS.box.dispatchEvent(rotateEvent); + curTime = new Date().getTime(); } @@ -287,6 +311,8 @@ delta = delta > 0 ? delta-decr : 0; THIS.box.style[cssPref+"Transform"] = "rotate3d("+ axis+","+angle+"rad) matrix3d("+startMatrix+")"; + rotateEvent.data = {axis: axis, angle: angle}; + THIS.box.dispatchEvent(rotateEvent); if (delta === 0){ stopSlide(); @@ -298,8 +324,12 @@ function stopSlide(){ cancelAnimFrame(slide); cleanupMatrix(); + oldAngle = angle = 0; delta = 0; + + fullStopEvent.data = {matrix: startMatrix}; + THIS.box.dispatchEvent(fullStopEvent); } //Some stupid matrix-multiplication. diff --git a/src/traqball.js b/src/traqball.js index aa72ca6..78f1a0c 100644 --- a/src/traqball.js +++ b/src/traqball.js @@ -10,6 +10,10 @@ (function(){ var userAgent = navigator.userAgent.toLowerCase(), + startEvent = document.createEvent('HTMLEvents'), + rotateEvent = document.createEvent('HTMLEvents'), + releaseEvent = document.createEvent('HTMLEvents'), + fullStopEvent = document.createEvent('HTMLEvents'), canTouch = "ontouchstart" in window, prefix = cssPref = "", requestAnimFrame, cancelAnimFrame; @@ -29,7 +33,12 @@ }else{ prefix = ""; } - + + startEvent.initEvent("traqballStartRotate", true, true); + rotateEvent.initEvent("traqballRotate", true, true); + releaseEvent.initEvent("traqballRelease", true, true); + fullStopEvent.initEvent("traqballFullStop", true, true); + function bindEvent(target, type, callback, remove){ //translate events var evType = type || "touchend", @@ -79,7 +88,9 @@ })(); var Traqball = function(confObj){ - this.config = {}; + this.config = { + stage: document.body + }; this.box = null; this.setup(confObj); @@ -87,7 +98,7 @@ Traqball.prototype.disable = function(){ if(this.box !== null){ - bindEvent(this.box, 'touchstart', this.evHandlers[0], "remove"); + bindEvent(this.config.activationArea, 'touchstart', this.evHandlers[0], "remove"); bindEvent(document, 'touchmove', this.evHandlers[1], "remove"); bindEvent(document, 'touchend', this.evHandlers[2], "remove"); } @@ -95,7 +106,7 @@ Traqball.prototype.activate = function(){ if(this.box !== null){ - bindEvent(this.box, 'touchstart', this.evHandlers[0]); + bindEvent(this.config.activationArea, 'touchstart', this.evHandlers[0]); bindEvent(document, 'touchmove', this.evHandlers[1], "remove"); bindEvent(document, 'touchend', this.evHandlers[2], "remove"); } @@ -118,8 +129,11 @@ for(var prop in conf){ THIS.config[prop] = conf[prop]; } - - stage = document.getElementById(THIS.config.stage) || document.getElementsByTagname("body")[0]; + + if (typeof THIS.config.stage === 'string') { + THIS.config.stage = document.getElementById(THIS.config.stage); + } + stage = THIS.config.stage; pos = findPos(stage); angle = THIS.config.angle || 0; impulse = THIS.config.impulse === false ? false : true; @@ -141,6 +155,9 @@ break; } } + if (typeof THIS.config.activationArea === 'undefined') { + THIS.config.activationArea = THIS.box; + } var perspective = getStyle(stage, prefix+"perspective"), pOrigin = getStyle(stage, prefix+"perspective-origin"), @@ -194,7 +211,7 @@ } THIS.box.style[cssPref+"Transform"] = "matrix3d("+ startMatrix+")"; - bindEvent(THIS.box, 'touchstart', startrotation); + bindEvent(THIS.config.activationArea, 'touchstart', startrotation); THIS.evHandlers = [startrotation, rotate, finishrotation]; })(); @@ -207,8 +224,10 @@ mouseDownVect = calcZvector(getCoords(e)); oldTime = curTime = new Date().getTime(); oldAngle = angle; - - bindEvent(THIS.box,'touchstart', startrotation, "remove"); + + THIS.box.dispatchEvent(startEvent); + + bindEvent(THIS.config.activationArea,'touchstart', startrotation, "remove"); bindEvent(document, 'touchmove', rotate); bindEvent(document, 'touchend', finishrotation); } @@ -218,8 +237,11 @@ bindEvent(document, 'touchmove', rotate, "remove"); bindEvent(document, 'touchend', finishrotation, "remove"); - bindEvent(THIS.box, 'touchstart', startrotation); + bindEvent(THIS.config.activationArea, 'touchstart', startrotation); calcSpeed(); + + THIS.box.dispatchEvent(releaseEvent); + if( impulse && delta > 0){ requestAnimFrame(slide); }else if(!(isNaN(axis[0]) || isNaN(axis[1]) || isNaN(axis[2]))) { @@ -264,7 +286,9 @@ //Only one thing left to do: Update the position of the box by applying a new transform: // 2 transforms will be applied: the current rotation 3d and the start-matrix THIS.box.style[cssPref+"Transform"] = "rotate3d("+ axis+","+angle+"rad) matrix3d("+startMatrix+")"; - + rotateEvent.data = {axis: axis, angle: angle}; + THIS.box.dispatchEvent(rotateEvent); + curTime = new Date().getTime(); } @@ -287,6 +311,8 @@ delta = delta > 0 ? delta-decr : 0; THIS.box.style[cssPref+"Transform"] = "rotate3d("+ axis+","+angle+"rad) matrix3d("+startMatrix+")"; + rotateEvent.data = {axis: axis, angle: angle}; + THIS.box.dispatchEvent(rotateEvent); if (delta === 0){ stopSlide(); @@ -298,8 +324,12 @@ function stopSlide(){ cancelAnimFrame(slide); cleanupMatrix(); + oldAngle = angle = 0; delta = 0; + + fullStopEvent.data = {matrix: startMatrix}; + THIS.box.dispatchEvent(fullStopEvent); } //Some stupid matrix-multiplication.