diff --git a/README.md b/README.md index 891f520..5cfec4e 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,12 @@ Impetus will register itself as an AMD module if it's available. - This function will be called with the updated x and y values. + + window + Window + window + The window this instance of Impetus will be bound to (useful when dealing with iframes). + multiplier Number @@ -80,6 +86,12 @@ Impetus will register itself as an AMD module if it's available. true Whether to stretch and rebound values when pulled outside the bounds. + + axis + String|Boolean + true + Whether to lock scrolling to a given axis ("x" or "y"), to unlock both (true), or to completely prevent scrolling (false). + @@ -94,12 +106,32 @@ Impetus will register itself as an AMD module if it's available. - .pause() - Disable movement processing. + .getAxis() + Retrieve the current the locked axis - .resume() - Re-enable movement processing. + .getMultiplier() + Retrieve the current multiplier. + + + .getValues() + Retrieve the current x and y output values. + + + .getBoundX() + Retrieve the current X bound + + + .getBoundY() + Retrieve the current Y bound + + + .getWindow() + Retrieve the window this instance is bound to. + + + .setAxis( <string|boolean> ) + Change the locked axis .setMultiplier( <number> ) @@ -117,6 +149,14 @@ Impetus will register itself as an AMD module if it's available. .setBoundY( <number[2]> ) Adjust the Y bound + + .pause() + Disable movement processing. + + + .resume() + Re-enable movement processing. + .destroy() diff --git a/dist/impetus.js b/dist/impetus.js index c609f23..dcfafeb 100644 --- a/dist/impetus.js +++ b/dist/impetus.js @@ -19,13 +19,13 @@ var bounceDeceleration = 0.04; var bounceAcceleration = 0.11; - // fixes weird safari 10 bug where preventDefault is prevented - // @see https://github.com/metafizzy/flickity/issues/457#issuecomment-254501356 - window.addEventListener('touchmove', function () {}); - var Impetus = function Impetus(_ref) { + var _ref$axis = _ref.axis; + var axis = _ref$axis === undefined ? true : _ref$axis; + var _ref$window = _ref.window; + var win = _ref$window === undefined ? window : _ref$window; var _ref$source = _ref.source; - var sourceEl = _ref$source === undefined ? document : _ref$source; + var sourceEl = _ref$source === undefined ? window : _ref$source; var updateCallback = _ref.update; var _ref$multiplier = _ref.multiplier; var multiplier = _ref$multiplier === undefined ? 1 : _ref$multiplier; @@ -49,11 +49,15 @@ var decelerating = false; var trackingPoints = []; + // fixes weird safari 10 bug where preventDefault is prevented + // @see https://github.com/metafizzy/flickity/issues/457#issuecomment-254501356 + win.addEventListener('touchmove', function () {}); + /** * Initialize instance */ (function init() { - sourceEl = typeof sourceEl === 'string' ? document.querySelector(sourceEl) : sourceEl; + sourceEl = typeof sourceEl === 'string' ? win.document.querySelector(sourceEl) : sourceEl; if (!sourceEl) { throw new Error('IMPETUS: source not found.'); } @@ -133,6 +137,15 @@ } }; + /** + * Retrieve the current x and y values + * @public + * @returns {Number[]} with the x and y values + */ + this.getValues = function () { + return [targetX, targetY]; + }; + /** * Update the multiplier value * @public @@ -143,6 +156,15 @@ stopThreshold = stopThresholdDefault * multiplier; }; + /** + * Retrieve the multiplier value + * @public + * @returns {Number} the multiplier value + */ + this.getMultiplier = function () { + return multiplier; + }; + /** * Update boundX value * @public @@ -153,6 +175,15 @@ boundXmax = boundX[1]; }; + /** + * Retrieve boundX value + * @public + * @returns {Number[]} boundX + */ + this.getBoundX = function () { + return [boundXmin, boundXmax]; + }; + /** * Update boundY value * @public @@ -163,6 +194,43 @@ boundYmax = boundY[1]; }; + /** + * Retrieve boundY value + * @public + * @returns {Number[]} boundY + */ + this.getBoundY = function () { + return [boundYmin, boundYmax]; + }; + + /** + * Set the axis that will be scrolled + * @public + * @param {String|Boolean} axis + */ + this.setAxis = function (val) { + val = typeof val === 'string' ? val.toLowerCase() : val; + axis = val === 'x' ? 'x' : val === 'y' ? 'y' : !!val; + }; + + /** + * Retrieve the current axis value + * @public + * @returns {String|Boolean} axis + */ + this.getAxis = function () { + return axis || false; + }; + + /** + * Retrieve the window this instance has been attached to + * @public + * @returns {Window} window + */ + this.getWindow = function () { + return win; + }; + /** * Executes the update function */ @@ -204,17 +272,17 @@ decelerating = false; pointerId = event.id; - pointerLastX = pointerCurrentX = event.x; - pointerLastY = pointerCurrentY = event.y; + pointerLastX = pointerCurrentX = isAxisUnlocked('x') ? event.x : pointerLastX; + pointerLastY = pointerCurrentY = isAxisUnlocked('y') ? event.y : pointerLastY; trackingPoints = []; addTrackingPoint(pointerLastX, pointerLastY); // @see https://developers.google.com/web/updates/2017/01/scrolling-intervention - document.addEventListener('touchmove', onMove, getPassiveSupported() ? { passive: false } : false); - document.addEventListener('touchend', onUp); - document.addEventListener('touchcancel', stopTracking); - document.addEventListener('mousemove', onMove, getPassiveSupported() ? { passive: false } : false); - document.addEventListener('mouseup', onUp); + win.addEventListener('touchmove', onMove, getPassiveSupported() ? { passive: false } : false); + win.addEventListener('touchend', onUp); + win.addEventListener('touchcancel', stopTracking); + win.addEventListener('mousemove', onMove, getPassiveSupported() ? { passive: false } : false); + win.addEventListener('mouseup', onUp); } } @@ -227,8 +295,8 @@ var event = normalizeEvent(ev); if (pointerActive && event.id === pointerId) { - pointerCurrentX = event.x; - pointerCurrentY = event.y; + pointerCurrentX = isAxisUnlocked('x') ? event.x : pointerCurrentX; + pointerCurrentY = isAxisUnlocked('y') ? event.y : pointerCurrentY; addTrackingPoint(pointerLastX, pointerLastY); requestTick(); } @@ -246,6 +314,13 @@ } } + /** + * Check if the supplied axis is locked + */ + function isAxisUnlocked(testVal) { + return axis === testVal || axis === true; + } + /** * Stops movement tracking, starts animation */ @@ -254,11 +329,11 @@ addTrackingPoint(pointerLastX, pointerLastY); startDecelAnim(); - document.removeEventListener('touchmove', onMove); - document.removeEventListener('touchend', onUp); - document.removeEventListener('touchcancel', stopTracking); - document.removeEventListener('mouseup', onUp); - document.removeEventListener('mousemove', onMove); + win.removeEventListener('touchmove', onMove); + win.removeEventListener('touchend', onUp); + win.removeEventListener('touchcancel', stopTracking); + win.removeEventListener('mouseup', onUp); + win.removeEventListener('mousemove', onMove); } /** @@ -282,8 +357,8 @@ * Calculate new values, call update function */ function updateAndRender() { - var pointerChangeX = pointerCurrentX - pointerLastX; - var pointerChangeY = pointerCurrentY - pointerLastY; + var pointerChangeX = pointerCurrentX - pointerLastX || 0; // prevent NaN + var pointerChangeY = pointerCurrentY - pointerLastY || 0; targetX += pointerChangeX * multiplier; targetY += pointerChangeY * multiplier; @@ -333,16 +408,20 @@ var xDiff = 0; var yDiff = 0; - if (boundXmin !== undefined && targetX < boundXmin) { - xDiff = boundXmin - targetX; - } else if (boundXmax !== undefined && targetX > boundXmax) { - xDiff = boundXmax - targetX; + if (isAxisUnlocked('x')) { + if (boundXmin !== undefined && targetX < boundXmin) { + xDiff = boundXmin - targetX; + } else if (boundXmax !== undefined && targetX > boundXmax) { + xDiff = boundXmax - targetX; + } } - if (boundYmin !== undefined && targetY < boundYmin) { - yDiff = boundYmin - targetY; - } else if (boundYmax !== undefined && targetY > boundYmax) { - yDiff = boundYmax - targetY; + if (isAxisUnlocked('y')) { + if (boundYmin !== undefined && targetY < boundYmin) { + yDiff = boundYmin - targetY; + } else if (boundYmax !== undefined && targetY > boundYmax) { + yDiff = boundYmax - targetY; + } } if (restrict) { diff --git a/dist/impetus.min.js b/dist/impetus.min.js index 49fd819..7d884bb 100644 --- a/dist/impetus.min.js +++ b/dist/impetus.min.js @@ -1 +1 @@ -!function(e,t){if("function"==typeof define&&define.amd)define(["exports","module"],t);else if("undefined"!=typeof exports&&"undefined"!=typeof module)t(exports,module);else{var n={exports:{}};t(n.exports,n),e.Impetus=n.exports}}(this,function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("test",null,t)}catch(e){}return o=function(){return e},e}var i=.04,u=.11;window.addEventListener("touchmove",function(){});var r=function e(t){function r(){b.call(L,O,G)}function c(e){if("touchmove"===e.type||"touchstart"===e.type||"touchend"===e.type){var t=e.targetTouches[0]||e.changedTouches[0];return{x:t.clientX,y:t.clientY,id:t.identifier}}return{x:e.clientX,y:e.clientY,id:null}}function d(e){var t=c(e);K||N||(K=!0,Q=!1,k=t.id,R=V=t.x,U=j=t.y,W=[],m(R,U),document.addEventListener("touchmove",a,!!o()&&{passive:!1}),document.addEventListener("touchend",f),document.addEventListener("touchcancel",v),document.addEventListener("mousemove",a,!!o()&&{passive:!1}),document.addEventListener("mouseup",f))}function a(e){e.preventDefault();var t=c(e);K&&t.id===k&&(V=t.x,j=t.y,m(R,U),p())}function f(e){var t=c(e);K&&t.id===k&&v()}function v(){K=!1,m(R,U),x(),document.removeEventListener("touchmove",a),document.removeEventListener("touchend",f),document.removeEventListener("touchcancel",v),document.removeEventListener("mouseup",f),document.removeEventListener("mousemove",a)}function m(e,t){for(var n=Date.now();W.length>0&&!(n-W[0].time<=100);)W.shift();W.push({x:e,y:t,time:n})}function l(){var e=V-R,t=j-U;if(O+=e*g,G+=t*g,F){var n=y();0!==n.x&&(O-=e*h(n.x)*g),0!==n.y&&(G-=t*h(n.y)*g)}else y(!0);r(),R=V,U=j,J=!1}function h(e){return 5e-6*Math.pow(e,2)+1e-4*e+.55}function p(){J||s(l),J=!0}function y(e){var t=0,n=0;return void 0!==I&&OP&&(t=P-O),void 0!==S&&GD&&(n=D-G),e&&(0!==t&&(O=t>0?I:P),0!==n&&(G=n>0?S:D)),{x:t,y:n,inBounds:0===t&&0===n}}function x(){var e=W[0],t=W[W.length-1],n=t.x-e.x,o=t.y-e.y,i=t.time-e.time,u=i/15/g;z=n/u||0,C=o/u||0;var r=y();(Math.abs(z)>1||Math.abs(C)>1||!r.inBounds)&&(Q=!0,s(w))}function w(){if(Q){z*=B,C*=B,O+=z,G+=C;var e=y();if(Math.abs(z)>H||Math.abs(C)>H||!e.inBounds){if(F){if(0!==e.x)if(e.x*z<=0)z+=e.x*i;else{var t=e.x>0?2.5:-2.5;z=(e.x+t)*u}if(0!==e.y)if(e.y*C<=0)C+=e.y*i;else{var t=e.y>0?2.5:-2.5;C=(e.y+t)*u}}else 0!==e.x&&(O=e.x>0?I:P,z=0),0!==e.y&&(G=e.y>0?S:D,C=0);r(),s(w)}else Q=!1}}var E=t.source,L=void 0===E?document:E,b=t.update,M=t.multiplier,g=void 0===M?1:M,T=t.friction,B=void 0===T?.92:T,q=t.initialValues,X=t.boundX,Y=t.boundY,A=t.bounce,F=void 0===A||A;n(this,e);var I,P,S,D,R,U,V,j,k,z,C,O=0,G=0,H=.3*g,J=!1,K=!1,N=!1,Q=!1,W=[];!function(){if(!(L="string"==typeof L?document.querySelector(L):L))throw new Error("IMPETUS: source not found.");if(!b)throw new Error("IMPETUS: update function not defined.");q&&(q[0]&&(O=q[0]),q[1]&&(G=q[1]),r()),X&&(I=X[0],P=X[1]),Y&&(S=Y[0],D=Y[1]),L.addEventListener("touchstart",d),L.addEventListener("mousedown",d)}(),this.destroy=function(){return L.removeEventListener("touchstart",d),L.removeEventListener("mousedown",d),null},this.pause=function(){K=!1,N=!0},this.resume=function(){N=!1},this.setValues=function(e,t){"number"==typeof e&&(O=e),"number"==typeof t&&(G=t)},this.setMultiplier=function(e){g=e,H=.3*g},this.setBoundX=function(e){I=e[0],P=e[1]},this.setBoundY=function(e){S=e[0],D=e[1]}};t.exports=r;var s=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}()}); \ No newline at end of file +!function(e,t){if("function"==typeof define&&define.amd)define(["exports","module"],t);else if("undefined"!=typeof exports&&"undefined"!=typeof module)t(exports,module);else{var n={exports:{}};t(n.exports,n),e.Impetus=n.exports}}(this,function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("test",null,t)}catch(e){}return i=function(){return e},e}var o=.04,r=.11,u=function e(t){function u(){A.call(T,K,N)}function c(e){if("touchmove"===e.type||"touchstart"===e.type||"touchend"===e.type){var t=e.targetTouches[0]||e.changedTouches[0];return{x:t.clientX,y:t.clientY,id:t.identifier}}return{x:e.clientX,y:e.clientY,id:null}}function d(e){var t=c(e);$||_||($=!0,ee=!1,G=t.id,k=O=v("x")?t.x:k,z=W=v("y")?t.y:z,te=[],l(k,z),M.addEventListener("touchmove",f,!!i()&&{passive:!1}),M.addEventListener("touchend",a),M.addEventListener("touchcancel",h),M.addEventListener("mousemove",f,!!i()&&{passive:!1}),M.addEventListener("mouseup",a))}function f(e){e.preventDefault();var t=c(e);$&&t.id===G&&(O=v("x")?t.x:O,W=v("y")?t.y:W,l(k,z),p())}function a(e){var t=c(e);$&&t.id===G&&h()}function v(e){return g===e||!0===g}function h(){$=!1,l(k,z),w(),M.removeEventListener("touchmove",f),M.removeEventListener("touchend",a),M.removeEventListener("touchcancel",h),M.removeEventListener("mouseup",a),M.removeEventListener("mousemove",f)}function l(e,t){for(var n=Date.now();te.length>0&&!(n-te[0].time<=100);)te.shift();te.push({x:e,y:t,time:n})}function m(){var e=O-k||0,t=W-z||0;if(K+=e*Y,N+=t*Y,C){var n=x();0!==n.x&&(K-=e*y(n.x)*Y),0!==n.y&&(N-=t*y(n.y)*Y)}else x(!0);u(),k=O,z=W,Z=!1}function y(e){return 5e-6*Math.pow(e,2)+1e-4*e+.55}function p(){Z||s(m),Z=!0}function x(e){var t=0,n=0;return v("x")&&(void 0!==D&&KR&&(t=R-K)),v("y")&&(void 0!==U&&Nj&&(n=j-N)),e&&(0!==t&&(K=t>0?D:R),0!==n&&(N=n>0?U:j)),{x:t,y:n,inBounds:0===t&&0===n}}function w(){var e=te[0],t=te[te.length-1],n=t.x-e.x,i=t.y-e.y,o=t.time-e.time,r=o/15/Y;H=n/r||0,J=i/r||0;var u=x();(Math.abs(H)>1||Math.abs(J)>1||!u.inBounds)&&(ee=!0,s(E))}function E(){if(ee){H*=F,J*=F,K+=H,N+=J;var e=x();if(Math.abs(H)>Q||Math.abs(J)>Q||!e.inBounds){if(C){if(0!==e.x)if(e.x*H<=0)H+=e.x*o;else{var t=e.x>0?2.5:-2.5;H=(e.x+t)*r}if(0!==e.y)if(e.y*J<=0)J+=e.y*o;else{var t=e.y>0?2.5:-2.5;J=(e.y+t)*r}}else 0!==e.x&&(K=e.x>0?D:R,H=0),0!==e.y&&(N=e.y>0?U:j,J=0);u(),s(E)}else ee=!1}}var L=t.axis,g=void 0===L||L,b=t.window,M=void 0===b?window:b,B=t.source,T=void 0===B?window:B,A=t.update,X=t.multiplier,Y=void 0===X?1:X,q=t.friction,F=void 0===q?.92:q,I=t.initialValues,P=t.boundX,S=t.boundY,V=t.bounce,C=void 0===V||V;n(this,e);var D,R,U,j,k,z,O,W,G,H,J,K=0,N=0,Q=.3*Y,Z=!1,$=!1,_=!1,ee=!1,te=[];M.addEventListener("touchmove",function(){}),function(){if(!(T="string"==typeof T?M.document.querySelector(T):T))throw new Error("IMPETUS: source not found.");if(!A)throw new Error("IMPETUS: update function not defined.");I&&(I[0]&&(K=I[0]),I[1]&&(N=I[1]),u()),P&&(D=P[0],R=P[1]),S&&(U=S[0],j=S[1]),T.addEventListener("touchstart",d),T.addEventListener("mousedown",d)}(),this.destroy=function(){return T.removeEventListener("touchstart",d),T.removeEventListener("mousedown",d),null},this.pause=function(){$=!1,_=!0},this.resume=function(){_=!1},this.setValues=function(e,t){"number"==typeof e&&(K=e),"number"==typeof t&&(N=t)},this.getValues=function(){return[K,N]},this.setMultiplier=function(e){Y=e,Q=.3*Y},this.getMultiplier=function(){return Y},this.setBoundX=function(e){D=e[0],R=e[1]},this.getBoundX=function(){return[D,R]},this.setBoundY=function(e){U=e[0],j=e[1]},this.getBoundY=function(){return[U,j]},this.setAxis=function(e){e="string"==typeof e?e.toLowerCase():e,g="x"===e?"x":"y"===e?"y":!!e},this.getAxis=function(){return g||!1},this.getWindow=function(){return M}};t.exports=u;var s=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}()}); \ No newline at end of file diff --git a/docs/impetus.min.js b/docs/impetus.min.js index 49fd819..7d884bb 100644 --- a/docs/impetus.min.js +++ b/docs/impetus.min.js @@ -1 +1 @@ -!function(e,t){if("function"==typeof define&&define.amd)define(["exports","module"],t);else if("undefined"!=typeof exports&&"undefined"!=typeof module)t(exports,module);else{var n={exports:{}};t(n.exports,n),e.Impetus=n.exports}}(this,function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("test",null,t)}catch(e){}return o=function(){return e},e}var i=.04,u=.11;window.addEventListener("touchmove",function(){});var r=function e(t){function r(){b.call(L,O,G)}function c(e){if("touchmove"===e.type||"touchstart"===e.type||"touchend"===e.type){var t=e.targetTouches[0]||e.changedTouches[0];return{x:t.clientX,y:t.clientY,id:t.identifier}}return{x:e.clientX,y:e.clientY,id:null}}function d(e){var t=c(e);K||N||(K=!0,Q=!1,k=t.id,R=V=t.x,U=j=t.y,W=[],m(R,U),document.addEventListener("touchmove",a,!!o()&&{passive:!1}),document.addEventListener("touchend",f),document.addEventListener("touchcancel",v),document.addEventListener("mousemove",a,!!o()&&{passive:!1}),document.addEventListener("mouseup",f))}function a(e){e.preventDefault();var t=c(e);K&&t.id===k&&(V=t.x,j=t.y,m(R,U),p())}function f(e){var t=c(e);K&&t.id===k&&v()}function v(){K=!1,m(R,U),x(),document.removeEventListener("touchmove",a),document.removeEventListener("touchend",f),document.removeEventListener("touchcancel",v),document.removeEventListener("mouseup",f),document.removeEventListener("mousemove",a)}function m(e,t){for(var n=Date.now();W.length>0&&!(n-W[0].time<=100);)W.shift();W.push({x:e,y:t,time:n})}function l(){var e=V-R,t=j-U;if(O+=e*g,G+=t*g,F){var n=y();0!==n.x&&(O-=e*h(n.x)*g),0!==n.y&&(G-=t*h(n.y)*g)}else y(!0);r(),R=V,U=j,J=!1}function h(e){return 5e-6*Math.pow(e,2)+1e-4*e+.55}function p(){J||s(l),J=!0}function y(e){var t=0,n=0;return void 0!==I&&OP&&(t=P-O),void 0!==S&&GD&&(n=D-G),e&&(0!==t&&(O=t>0?I:P),0!==n&&(G=n>0?S:D)),{x:t,y:n,inBounds:0===t&&0===n}}function x(){var e=W[0],t=W[W.length-1],n=t.x-e.x,o=t.y-e.y,i=t.time-e.time,u=i/15/g;z=n/u||0,C=o/u||0;var r=y();(Math.abs(z)>1||Math.abs(C)>1||!r.inBounds)&&(Q=!0,s(w))}function w(){if(Q){z*=B,C*=B,O+=z,G+=C;var e=y();if(Math.abs(z)>H||Math.abs(C)>H||!e.inBounds){if(F){if(0!==e.x)if(e.x*z<=0)z+=e.x*i;else{var t=e.x>0?2.5:-2.5;z=(e.x+t)*u}if(0!==e.y)if(e.y*C<=0)C+=e.y*i;else{var t=e.y>0?2.5:-2.5;C=(e.y+t)*u}}else 0!==e.x&&(O=e.x>0?I:P,z=0),0!==e.y&&(G=e.y>0?S:D,C=0);r(),s(w)}else Q=!1}}var E=t.source,L=void 0===E?document:E,b=t.update,M=t.multiplier,g=void 0===M?1:M,T=t.friction,B=void 0===T?.92:T,q=t.initialValues,X=t.boundX,Y=t.boundY,A=t.bounce,F=void 0===A||A;n(this,e);var I,P,S,D,R,U,V,j,k,z,C,O=0,G=0,H=.3*g,J=!1,K=!1,N=!1,Q=!1,W=[];!function(){if(!(L="string"==typeof L?document.querySelector(L):L))throw new Error("IMPETUS: source not found.");if(!b)throw new Error("IMPETUS: update function not defined.");q&&(q[0]&&(O=q[0]),q[1]&&(G=q[1]),r()),X&&(I=X[0],P=X[1]),Y&&(S=Y[0],D=Y[1]),L.addEventListener("touchstart",d),L.addEventListener("mousedown",d)}(),this.destroy=function(){return L.removeEventListener("touchstart",d),L.removeEventListener("mousedown",d),null},this.pause=function(){K=!1,N=!0},this.resume=function(){N=!1},this.setValues=function(e,t){"number"==typeof e&&(O=e),"number"==typeof t&&(G=t)},this.setMultiplier=function(e){g=e,H=.3*g},this.setBoundX=function(e){I=e[0],P=e[1]},this.setBoundY=function(e){S=e[0],D=e[1]}};t.exports=r;var s=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}()}); \ No newline at end of file +!function(e,t){if("function"==typeof define&&define.amd)define(["exports","module"],t);else if("undefined"!=typeof exports&&"undefined"!=typeof module)t(exports,module);else{var n={exports:{}};t(n.exports,n),e.Impetus=n.exports}}(this,function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("test",null,t)}catch(e){}return i=function(){return e},e}var o=.04,r=.11,u=function e(t){function u(){A.call(T,K,N)}function c(e){if("touchmove"===e.type||"touchstart"===e.type||"touchend"===e.type){var t=e.targetTouches[0]||e.changedTouches[0];return{x:t.clientX,y:t.clientY,id:t.identifier}}return{x:e.clientX,y:e.clientY,id:null}}function d(e){var t=c(e);$||_||($=!0,ee=!1,G=t.id,k=O=v("x")?t.x:k,z=W=v("y")?t.y:z,te=[],l(k,z),M.addEventListener("touchmove",f,!!i()&&{passive:!1}),M.addEventListener("touchend",a),M.addEventListener("touchcancel",h),M.addEventListener("mousemove",f,!!i()&&{passive:!1}),M.addEventListener("mouseup",a))}function f(e){e.preventDefault();var t=c(e);$&&t.id===G&&(O=v("x")?t.x:O,W=v("y")?t.y:W,l(k,z),p())}function a(e){var t=c(e);$&&t.id===G&&h()}function v(e){return g===e||!0===g}function h(){$=!1,l(k,z),w(),M.removeEventListener("touchmove",f),M.removeEventListener("touchend",a),M.removeEventListener("touchcancel",h),M.removeEventListener("mouseup",a),M.removeEventListener("mousemove",f)}function l(e,t){for(var n=Date.now();te.length>0&&!(n-te[0].time<=100);)te.shift();te.push({x:e,y:t,time:n})}function m(){var e=O-k||0,t=W-z||0;if(K+=e*Y,N+=t*Y,C){var n=x();0!==n.x&&(K-=e*y(n.x)*Y),0!==n.y&&(N-=t*y(n.y)*Y)}else x(!0);u(),k=O,z=W,Z=!1}function y(e){return 5e-6*Math.pow(e,2)+1e-4*e+.55}function p(){Z||s(m),Z=!0}function x(e){var t=0,n=0;return v("x")&&(void 0!==D&&KR&&(t=R-K)),v("y")&&(void 0!==U&&Nj&&(n=j-N)),e&&(0!==t&&(K=t>0?D:R),0!==n&&(N=n>0?U:j)),{x:t,y:n,inBounds:0===t&&0===n}}function w(){var e=te[0],t=te[te.length-1],n=t.x-e.x,i=t.y-e.y,o=t.time-e.time,r=o/15/Y;H=n/r||0,J=i/r||0;var u=x();(Math.abs(H)>1||Math.abs(J)>1||!u.inBounds)&&(ee=!0,s(E))}function E(){if(ee){H*=F,J*=F,K+=H,N+=J;var e=x();if(Math.abs(H)>Q||Math.abs(J)>Q||!e.inBounds){if(C){if(0!==e.x)if(e.x*H<=0)H+=e.x*o;else{var t=e.x>0?2.5:-2.5;H=(e.x+t)*r}if(0!==e.y)if(e.y*J<=0)J+=e.y*o;else{var t=e.y>0?2.5:-2.5;J=(e.y+t)*r}}else 0!==e.x&&(K=e.x>0?D:R,H=0),0!==e.y&&(N=e.y>0?U:j,J=0);u(),s(E)}else ee=!1}}var L=t.axis,g=void 0===L||L,b=t.window,M=void 0===b?window:b,B=t.source,T=void 0===B?window:B,A=t.update,X=t.multiplier,Y=void 0===X?1:X,q=t.friction,F=void 0===q?.92:q,I=t.initialValues,P=t.boundX,S=t.boundY,V=t.bounce,C=void 0===V||V;n(this,e);var D,R,U,j,k,z,O,W,G,H,J,K=0,N=0,Q=.3*Y,Z=!1,$=!1,_=!1,ee=!1,te=[];M.addEventListener("touchmove",function(){}),function(){if(!(T="string"==typeof T?M.document.querySelector(T):T))throw new Error("IMPETUS: source not found.");if(!A)throw new Error("IMPETUS: update function not defined.");I&&(I[0]&&(K=I[0]),I[1]&&(N=I[1]),u()),P&&(D=P[0],R=P[1]),S&&(U=S[0],j=S[1]),T.addEventListener("touchstart",d),T.addEventListener("mousedown",d)}(),this.destroy=function(){return T.removeEventListener("touchstart",d),T.removeEventListener("mousedown",d),null},this.pause=function(){$=!1,_=!0},this.resume=function(){_=!1},this.setValues=function(e,t){"number"==typeof e&&(K=e),"number"==typeof t&&(N=t)},this.getValues=function(){return[K,N]},this.setMultiplier=function(e){Y=e,Q=.3*Y},this.getMultiplier=function(){return Y},this.setBoundX=function(e){D=e[0],R=e[1]},this.getBoundX=function(){return[D,R]},this.setBoundY=function(e){U=e[0],j=e[1]},this.getBoundY=function(){return[U,j]},this.setAxis=function(e){e="string"==typeof e?e.toLowerCase():e,g="x"===e?"x":"y"===e?"y":!!e},this.getAxis=function(){return g||!1},this.getWindow=function(){return M}};t.exports=u;var s=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}()}); \ No newline at end of file diff --git a/src/Impetus.js b/src/Impetus.js index 920d895..d992bbc 100644 --- a/src/Impetus.js +++ b/src/Impetus.js @@ -3,15 +3,11 @@ const stopThresholdDefault = 0.3; const bounceDeceleration = 0.04; const bounceAcceleration = 0.11; - -// fixes weird safari 10 bug where preventDefault is prevented -// @see https://github.com/metafizzy/flickity/issues/457#issuecomment-254501356 -window.addEventListener('touchmove', function() {}); - - export default class Impetus { constructor({ - source: sourceEl = document, + axis: axis = true, + window: win = window, + source: sourceEl = window, update: updateCallback, multiplier = 1, friction = 0.92, @@ -30,12 +26,16 @@ export default class Impetus { var decelerating = false; var trackingPoints = []; + // fixes weird safari 10 bug where preventDefault is prevented + // @see https://github.com/metafizzy/flickity/issues/457#issuecomment-254501356 + win.addEventListener('touchmove', function() {}); + /** * Initialize instance */ (function init() { - sourceEl = (typeof sourceEl === 'string') ? document.querySelector(sourceEl) : sourceEl; + sourceEl = (typeof sourceEl === 'string') ? win.document.querySelector(sourceEl) : sourceEl; if (!sourceEl) { throw new Error('IMPETUS: source not found.'); } @@ -115,6 +115,15 @@ export default class Impetus { } }; + /** + * Retrieve the current x and y values + * @public + * @returns {Number[]} with the x and y values + */ + this.getValues = function() { + return [targetX, targetY]; + }; + /** * Update the multiplier value * @public @@ -125,6 +134,15 @@ export default class Impetus { stopThreshold = stopThresholdDefault * multiplier; }; + /** + * Retrieve the multiplier value + * @public + * @returns {Number} the multiplier value + */ + this.getMultiplier = function() { + return multiplier; + }; + /** * Update boundX value * @public @@ -135,6 +153,15 @@ export default class Impetus { boundXmax = boundX[1]; }; + /** + * Retrieve boundX value + * @public + * @returns {Number[]} boundX + */ + this.getBoundX = function() { + return [boundXmin, boundXmax]; + }; + /** * Update boundY value * @public @@ -145,6 +172,43 @@ export default class Impetus { boundYmax = boundY[1]; }; + /** + * Retrieve boundY value + * @public + * @returns {Number[]} boundY + */ + this.getBoundY = function() { + return [boundYmin, boundYmax]; + }; + + /** + * Set the axis that will be scrolled + * @public + * @param {String|Boolean} axis + */ + this.setAxis = function(val) { + val = typeof val === 'string' ? val.toLowerCase() : val; + axis = val === 'x' ? 'x' : (val === 'y' ? 'y' : !!val); + }; + + /** + * Retrieve the current axis value + * @public + * @returns {String|Boolean} axis + */ + this.getAxis = function() { + return axis || false; + }; + + /** + * Retrieve the window this instance has been attached to + * @public + * @returns {Window} window + */ + this.getWindow = function() { + return win; + }; + /** * Executes the update function */ @@ -185,17 +249,17 @@ export default class Impetus { decelerating = false; pointerId = event.id; - pointerLastX = pointerCurrentX = event.x; - pointerLastY = pointerCurrentY = event.y; + pointerLastX = pointerCurrentX = isAxisUnlocked('x') ? event.x : pointerLastX; + pointerLastY = pointerCurrentY = isAxisUnlocked('y') ? event.y : pointerLastY; trackingPoints = []; addTrackingPoint(pointerLastX, pointerLastY); // @see https://developers.google.com/web/updates/2017/01/scrolling-intervention - document.addEventListener('touchmove', onMove, getPassiveSupported() ? {passive: false} : false); - document.addEventListener('touchend', onUp); - document.addEventListener('touchcancel', stopTracking); - document.addEventListener('mousemove', onMove, getPassiveSupported() ? {passive: false} : false); - document.addEventListener('mouseup', onUp); + win.addEventListener('touchmove', onMove, getPassiveSupported() ? {passive: false} : false); + win.addEventListener('touchend', onUp); + win.addEventListener('touchcancel', stopTracking); + win.addEventListener('mousemove', onMove, getPassiveSupported() ? {passive: false} : false); + win.addEventListener('mouseup', onUp); } } @@ -208,8 +272,8 @@ export default class Impetus { var event = normalizeEvent(ev); if (pointerActive && event.id === pointerId) { - pointerCurrentX = event.x; - pointerCurrentY = event.y; + pointerCurrentX = isAxisUnlocked('x') ? event.x : pointerCurrentX; + pointerCurrentY = isAxisUnlocked('y') ? event.y : pointerCurrentY; addTrackingPoint(pointerLastX, pointerLastY); requestTick(); } @@ -227,6 +291,15 @@ export default class Impetus { } } + + /** + * Check if the supplied axis is locked + */ + function isAxisUnlocked(testVal) { + return axis === testVal || axis === true; + } + + /** * Stops movement tracking, starts animation */ @@ -235,11 +308,11 @@ export default class Impetus { addTrackingPoint(pointerLastX, pointerLastY); startDecelAnim(); - document.removeEventListener('touchmove', onMove); - document.removeEventListener('touchend', onUp); - document.removeEventListener('touchcancel', stopTracking); - document.removeEventListener('mouseup', onUp); - document.removeEventListener('mousemove', onMove); + win.removeEventListener('touchmove', onMove); + win.removeEventListener('touchend', onUp); + win.removeEventListener('touchcancel', stopTracking); + win.removeEventListener('mouseup', onUp); + win.removeEventListener('mousemove', onMove); } /** @@ -263,8 +336,8 @@ export default class Impetus { * Calculate new values, call update function */ function updateAndRender() { - var pointerChangeX = pointerCurrentX - pointerLastX; - var pointerChangeY = pointerCurrentY - pointerLastY; + var pointerChangeX = (pointerCurrentX - pointerLastX) || 0; // prevent NaN + var pointerChangeY = (pointerCurrentY - pointerLastY) || 0; targetX += pointerChangeX * multiplier; targetY += pointerChangeY * multiplier; @@ -317,16 +390,20 @@ export default class Impetus { var xDiff = 0; var yDiff = 0; - if (boundXmin !== undefined && targetX < boundXmin) { - xDiff = boundXmin - targetX; - } else if (boundXmax !== undefined && targetX > boundXmax) { - xDiff = boundXmax - targetX; + if (isAxisUnlocked('x')) { + if (boundXmin !== undefined && targetX < boundXmin) { + xDiff = boundXmin - targetX; + } else if (boundXmax !== undefined && targetX > boundXmax) { + xDiff = boundXmax - targetX; + } } - if (boundYmin !== undefined && targetY < boundYmin) { - yDiff = boundYmin - targetY; - } else if (boundYmax !== undefined && targetY > boundYmax) { - yDiff = boundYmax - targetY; + if (isAxisUnlocked('y')) { + if (boundYmin !== undefined && targetY < boundYmin) { + yDiff = boundYmin - targetY; + } else if (boundYmax !== undefined && targetY > boundYmax) { + yDiff = boundYmax - targetY; + } } if (restrict) {