scrollbooster
Advanced tools
Comparing version 1.0.2 to 1.0.3
@@ -165,2 +165,7 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
/** | ||
* Run update loop | ||
*/ | ||
_createClass(ScrollBooster, [{ | ||
@@ -208,2 +213,3 @@ key: 'run', | ||
// if bounce effect is disabled | ||
if (!this.bounce || this.isScrolling) { | ||
@@ -214,2 +220,3 @@ this.position.x = Math.max(Math.min(this.position.x, this.boundX.to), this.boundX.from); | ||
// stop update loop if nothing moves | ||
if (!this.isDragging && !this.isScrolling && Math.abs(this.velocity.x) < 0.005 && Math.abs(this.velocity.y) < 0.005) { | ||
@@ -225,2 +232,7 @@ this.isRunning = false; | ||
} | ||
/** | ||
* Apply force for bounce effect | ||
*/ | ||
}, { | ||
@@ -241,5 +253,6 @@ key: 'applyBoundForce', | ||
var resultForce = { x: 0, y: 0 }; | ||
var resultForce = { x: 0, y: 0 | ||
if (pastLeft || pastRight) { | ||
// scrolled past left of right viewport boundaries | ||
};if (pastLeft || pastRight) { | ||
var bound = pastLeft ? this.boundX.from : this.boundX.to; | ||
@@ -258,2 +271,3 @@ var distance = bound - this.position.x; | ||
// scrolled past top of bottom viewport boundaries | ||
if (pastTop || pastBottom) { | ||
@@ -275,2 +289,7 @@ var _bound = pastTop ? this.boundY.from : this.boundY.to; | ||
} | ||
/** | ||
* Apply force to move content while dragging with mouse/touch | ||
*/ | ||
}, { | ||
@@ -293,2 +312,7 @@ key: 'applyDragForce', | ||
} | ||
/** | ||
* Apply force to emulate mouse wheel | ||
*/ | ||
}, { | ||
@@ -311,2 +335,7 @@ key: 'applyScrollForce', | ||
} | ||
/** | ||
* Manual position setting | ||
*/ | ||
}, { | ||
@@ -325,2 +354,7 @@ key: 'setPosition', | ||
} | ||
/** | ||
* Get latest metrics and coordinates | ||
*/ | ||
}, { | ||
@@ -408,7 +442,6 @@ key: 'getUpdate', | ||
console.log(pageX - vp.offsetLeft, vp.clientLeft + vp.clientWidth); | ||
var rect = vp.getBoundingClientRect(); | ||
// click on vertical scrollbar | ||
if (clientX - rect.left >= vp.clientLeft + vp.clientWidth) { | ||
console.log('lol x'); | ||
return; | ||
@@ -419,3 +452,2 @@ } | ||
if (clientY - rect.top >= vp.clientTop + vp.clientHeight) { | ||
console.log('lol y'); | ||
return; | ||
@@ -422,0 +454,0 @@ } |
@@ -1,1 +0,1 @@ | ||
!function(t,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define("ScrollBooster",[],i):"object"==typeof exports?exports.ScrollBooster=i():t.ScrollBooster=i()}("undefined"!=typeof self?self:this,function(){return function(t){function i(o){if(e[o])return e[o].exports;var n=e[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,i),n.l=!0,n.exports}var e={};return i.m=t,i.c=e,i.d=function(t,e,o){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:o})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},i.p="/dist/",i(i.s=0)}([function(t,i,e){"use strict";function o(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}function n(t){return Math.max(t.offsetWidth,t.scrollWidth)}function s(t){return Math.max(t.offsetHeight,t.scrollHeight)}Object.defineProperty(i,"__esModule",{value:!0});var r=Object.assign||function(t){for(var i=1;i<arguments.length;i++){var e=arguments[i];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t},h=function(){function t(t,i){for(var e=0;e<i.length;e++){var o=i[e];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(i,e,o){return e&&t(i.prototype,e),o&&t(i,o),i}}(),p=function(){function t(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(o(this,t),!(i.viewport&&i.viewport instanceof Element))return void console.error('"viewport" config property must be present and must be Element');var e={handle:i.viewport,content:i.viewport.children[0],bounce:!0,onUpdate:function(){}};if(this.props=r({},e,i),!this.props.content)return void console.error("Viewport does not have any content");this.viewport={width:this.props.viewport.clientWidth,height:this.props.viewport.clientHeight},this.content={width:n(this.props.content),height:s(this.props.content)},this.position={x:0,y:0},this.velocity={x:0,y:0},this.friction=.95,this.isDragging=!1,this.dragStartPosition={x:0,y:0},this.dragPosition=r({},this.position),this.isScrollEnabled=!!this.props.emulateScroll,this.isScrolling=!1,this.scrollOffset={x:0,y:0},this.bounce=this.props.bounce,this.boundX={from:Math.min(-this.content.width+this.viewport.width,0),to:0},this.boundY={from:Math.min(-this.content.height+this.viewport.height,0),to:0},this.mode={x:"x"==this.props.mode,y:"y"==this.props.mode,xy:"x"!==this.props.mode&&"y"!==this.props.mode},this.isRunning=!1,this.rafID=null,this.events={},this.animate(),this.handleEvents()}return h(t,[{key:"run",value:function(){var t=this;this.isRunning=!0,cancelAnimationFrame(this.rafID),this.rafID=requestAnimationFrame(function(){return t.animate()})}},{key:"animate",value:function(){var t=this;this.isRunning&&(this.update(),this.notify(),this.rafID=requestAnimationFrame(function(){return t.animate()}))}},{key:"update",value:function(){this.applyBoundForce(),this.applyDragForce(),this.applyScrollForce(),this.velocity.x*=this.friction,this.velocity.y*=this.friction,this.mode.y||(this.position.x+=this.velocity.x),this.mode.x||(this.position.y+=this.velocity.y),this.bounce&&!this.isScrolling||(this.position.x=Math.max(Math.min(this.position.x,this.boundX.to),this.boundX.from),this.position.y=Math.max(Math.min(this.position.y,this.boundY.to),this.boundY.from)),!this.isDragging&&!this.isScrolling&&Math.abs(this.velocity.x)<.005&&Math.abs(this.velocity.y)<.005&&(this.isRunning=!1)}},{key:"applyForce",value:function(t){this.velocity.x+=t.x,this.velocity.y+=t.y}},{key:"applyBoundForce",value:function(){if(this.bounce&&!this.isDragging){var t=this.position.x<this.boundX.from,i=this.position.x>this.boundX.to,e=this.position.y<this.boundY.from,o=this.position.y>this.boundY.to,n={x:0,y:0};if(t||i){var s=t?this.boundX.from:this.boundX.to,r=s-this.position.x,h=.1*r,p=this.position.x+(this.velocity.x+h)/(1-this.friction);t&&p<this.boundX.from||i&&p>this.boundX.to||(h=.1*r-this.velocity.x),n.x=h}if(e||o){var l=e?this.boundY.from:this.boundY.to,c=l-this.position.y,a=.1*c,u=this.position.y+(this.velocity.y+a)/(1-this.friction);e&&u<this.boundY.from||o&&u>this.boundY.to||(a=.1*c-this.velocity.y),n.y=a}this.applyForce(n)}}},{key:"applyDragForce",value:function(){if(this.isDragging){var t={x:this.dragPosition.x-this.position.x,y:this.dragPosition.y-this.position.y},i={x:t.x-this.velocity.x,y:t.y-this.velocity.y};this.applyForce(i)}}},{key:"applyScrollForce",value:function(){if(this.isScrolling){var t={x:this.scrollOffset.x-this.velocity.x,y:this.scrollOffset.y-this.velocity.y};this.scrollOffset.x=0,this.scrollOffset.y=0,this.applyForce(t)}}},{key:"setPosition",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.velocity.x=0,this.velocity.y=0,this.position.x=-t.x||0,this.position.y=-t.y||0,this.run()}},{key:"getUpdate",value:function(){return{position:{x:-this.position.x,y:-this.position.y},viewport:r({},this.viewport),content:r({},this.content)}}},{key:"notify",value:function(){this.props.onUpdate(this.getUpdate())}},{key:"updateMetrics",value:function(){this.viewport.width=this.props.viewport.clientWidth,this.viewport.height=this.props.viewport.clientHeight,this.content.width=n(this.props.content),this.content.height=s(this.props.content),this.boundX.from=Math.min(-this.content.width+this.viewport.width,0),this.boundY.from=Math.min(-this.content.height+this.viewport.height,0),this.run()}},{key:"handleEvents",value:function(){var t=this,i=this.props.viewport,e={x:0,y:0},o={x:0,y:0},n=!1,s=function(i){var e=void 0,s=void 0;n?(e=i.touches[0].pageX,s=i.touches[0].pageY):(e=i.pageX,s=i.pageY);var r=e-o.x,h=s-o.y;t.dragPosition.x=t.dragStartPosition.x+r,t.dragPosition.y=t.dragStartPosition.y+h,n||i.preventDefault()};this.events.pointerdown=function(r){var h=void 0,p=void 0,l=void 0,c=void 0;n=!(!r.touches||!r.touches[0]),n?(h=r.touches[0].pageX,p=r.touches[0].pageY,l=r.touches[0].clientX,c=r.touches[0].clientY):(h=r.pageX,p=r.pageY,l=r.clientX,c=r.clientY),console.log(h-i.offsetLeft,i.clientLeft+i.clientWidth);var a=i.getBoundingClientRect();if(l-a.left>=i.clientLeft+i.clientWidth)return void console.log("lol x");if(c-a.top>=i.clientTop+i.clientHeight)return void console.log("lol y");t.isDragging=!0,(e.x||e.y)&&(t.position.x=e.x,t.position.y=e.y,e.x=0,e.y=0),o.x=h,o.y=p,t.dragStartPosition.x=t.position.x,t.dragStartPosition.y=t.position.y,s(r),t.run();var u=void 0,v=void 0;v=function(i){t.isDragging=!1,n?(window.removeEventListener("touchmove",s),window.removeEventListener("touchend",u)):(window.removeEventListener("mousemove",s),window.removeEventListener("mouseup",u))},n?(u=window.addEventListener("touchend",v),window.addEventListener("touchmove",s)):(u=window.addEventListener("mouseup",v),window.addEventListener("mousemove",s))};var r=null;this.events.wheel=function(i){t.velocity.x=0,t.isScrollEnabled&&(t.isScrolling=!0,t.scrollOffset.x=-i.deltaX,t.scrollOffset.y=-i.deltaY,t.run(),clearTimeout(r),r=setTimeout(function(){return t.isScrolling=!1},80),i.preventDefault())},this.events.scroll=function(i){var o=t.props.viewport.scrollLeft,n=t.props.viewport.scrollTop;Math.abs(t.position.x+o)>3&&(t.position.x=-o,t.velocity.x=0),Math.abs(t.position.y+n)>3&&(t.position.y=-n,t.velocity.y=0),e.x=-t.props.viewport.scrollLeft,e.y=-t.props.viewport.scrollTop},this.events.resize=this.updateMetrics.bind(this),this.props.handle.addEventListener("mousedown",this.events.pointerdown),this.props.handle.addEventListener("touchstart",this.events.pointerdown),this.props.viewport.addEventListener("wheel",this.events.wheel),this.props.viewport.addEventListener("scroll",this.events.scroll),window.addEventListener("resize",this.events.resize)}},{key:"destroy",value:function(){this.props.handle.removeEventListener("mousedown",this.events.pointerdown),this.props.handle.removeEventListener("touchstart",this.events.pointerdown),this.props.viewport.removeEventListener("wheel",this.events.wheel),this.props.viewport.removeEventListener("scroll",this.events.scroll),window.removeEventListener("resize",this.events.resize)}}]),t}();i.default=p,t.exports=i.default}])}); | ||
!function(t,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define("ScrollBooster",[],i):"object"==typeof exports?exports.ScrollBooster=i():t.ScrollBooster=i()}("undefined"!=typeof self?self:this,function(){return function(t){function i(o){if(e[o])return e[o].exports;var n=e[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,i),n.l=!0,n.exports}var e={};return i.m=t,i.c=e,i.d=function(t,e,o){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:o})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},i.p="/dist/",i(i.s=0)}([function(t,i,e){"use strict";function o(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}function n(t){return Math.max(t.offsetWidth,t.scrollWidth)}function s(t){return Math.max(t.offsetHeight,t.scrollHeight)}Object.defineProperty(i,"__esModule",{value:!0});var r=Object.assign||function(t){for(var i=1;i<arguments.length;i++){var e=arguments[i];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t},h=function(){function t(t,i){for(var e=0;e<i.length;e++){var o=i[e];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(i,e,o){return e&&t(i.prototype,e),o&&t(i,o),i}}(),p=function(){function t(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(o(this,t),!(i.viewport&&i.viewport instanceof Element))return void console.error('"viewport" config property must be present and must be Element');var e={handle:i.viewport,content:i.viewport.children[0],bounce:!0,onUpdate:function(){}};if(this.props=r({},e,i),!this.props.content)return void console.error("Viewport does not have any content");this.viewport={width:this.props.viewport.clientWidth,height:this.props.viewport.clientHeight},this.content={width:n(this.props.content),height:s(this.props.content)},this.position={x:0,y:0},this.velocity={x:0,y:0},this.friction=.95,this.isDragging=!1,this.dragStartPosition={x:0,y:0},this.dragPosition=r({},this.position),this.isScrollEnabled=!!this.props.emulateScroll,this.isScrolling=!1,this.scrollOffset={x:0,y:0},this.bounce=this.props.bounce,this.boundX={from:Math.min(-this.content.width+this.viewport.width,0),to:0},this.boundY={from:Math.min(-this.content.height+this.viewport.height,0),to:0},this.mode={x:"x"==this.props.mode,y:"y"==this.props.mode,xy:"x"!==this.props.mode&&"y"!==this.props.mode},this.isRunning=!1,this.rafID=null,this.events={},this.animate(),this.handleEvents()}return h(t,[{key:"run",value:function(){var t=this;this.isRunning=!0,cancelAnimationFrame(this.rafID),this.rafID=requestAnimationFrame(function(){return t.animate()})}},{key:"animate",value:function(){var t=this;this.isRunning&&(this.update(),this.notify(),this.rafID=requestAnimationFrame(function(){return t.animate()}))}},{key:"update",value:function(){this.applyBoundForce(),this.applyDragForce(),this.applyScrollForce(),this.velocity.x*=this.friction,this.velocity.y*=this.friction,this.mode.y||(this.position.x+=this.velocity.x),this.mode.x||(this.position.y+=this.velocity.y),this.bounce&&!this.isScrolling||(this.position.x=Math.max(Math.min(this.position.x,this.boundX.to),this.boundX.from),this.position.y=Math.max(Math.min(this.position.y,this.boundY.to),this.boundY.from)),!this.isDragging&&!this.isScrolling&&Math.abs(this.velocity.x)<.005&&Math.abs(this.velocity.y)<.005&&(this.isRunning=!1)}},{key:"applyForce",value:function(t){this.velocity.x+=t.x,this.velocity.y+=t.y}},{key:"applyBoundForce",value:function(){if(this.bounce&&!this.isDragging){var t=this.position.x<this.boundX.from,i=this.position.x>this.boundX.to,e=this.position.y<this.boundY.from,o=this.position.y>this.boundY.to,n={x:0,y:0};if(t||i){var s=t?this.boundX.from:this.boundX.to,r=s-this.position.x,h=.1*r,p=this.position.x+(this.velocity.x+h)/(1-this.friction);t&&p<this.boundX.from||i&&p>this.boundX.to||(h=.1*r-this.velocity.x),n.x=h}if(e||o){var c=e?this.boundY.from:this.boundY.to,a=c-this.position.y,l=.1*a,u=this.position.y+(this.velocity.y+l)/(1-this.friction);e&&u<this.boundY.from||o&&u>this.boundY.to||(l=.1*a-this.velocity.y),n.y=l}this.applyForce(n)}}},{key:"applyDragForce",value:function(){if(this.isDragging){var t={x:this.dragPosition.x-this.position.x,y:this.dragPosition.y-this.position.y},i={x:t.x-this.velocity.x,y:t.y-this.velocity.y};this.applyForce(i)}}},{key:"applyScrollForce",value:function(){if(this.isScrolling){var t={x:this.scrollOffset.x-this.velocity.x,y:this.scrollOffset.y-this.velocity.y};this.scrollOffset.x=0,this.scrollOffset.y=0,this.applyForce(t)}}},{key:"setPosition",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.velocity.x=0,this.velocity.y=0,this.position.x=-t.x||0,this.position.y=-t.y||0,this.run()}},{key:"getUpdate",value:function(){return{position:{x:-this.position.x,y:-this.position.y},viewport:r({},this.viewport),content:r({},this.content)}}},{key:"notify",value:function(){this.props.onUpdate(this.getUpdate())}},{key:"updateMetrics",value:function(){this.viewport.width=this.props.viewport.clientWidth,this.viewport.height=this.props.viewport.clientHeight,this.content.width=n(this.props.content),this.content.height=s(this.props.content),this.boundX.from=Math.min(-this.content.width+this.viewport.width,0),this.boundY.from=Math.min(-this.content.height+this.viewport.height,0),this.run()}},{key:"handleEvents",value:function(){var t=this,i=this.props.viewport,e={x:0,y:0},o={x:0,y:0},n=!1,s=function(i){var e=void 0,s=void 0;n?(e=i.touches[0].pageX,s=i.touches[0].pageY):(e=i.pageX,s=i.pageY);var r=e-o.x,h=s-o.y;t.dragPosition.x=t.dragStartPosition.x+r,t.dragPosition.y=t.dragStartPosition.y+h,n||i.preventDefault()};this.events.pointerdown=function(r){var h=void 0,p=void 0,c=void 0,a=void 0;n=!(!r.touches||!r.touches[0]),n?(h=r.touches[0].pageX,p=r.touches[0].pageY,c=r.touches[0].clientX,a=r.touches[0].clientY):(h=r.pageX,p=r.pageY,c=r.clientX,a=r.clientY);var l=i.getBoundingClientRect();if(!(c-l.left>=i.clientLeft+i.clientWidth||a-l.top>=i.clientTop+i.clientHeight)){t.isDragging=!0,(e.x||e.y)&&(t.position.x=e.x,t.position.y=e.y,e.x=0,e.y=0),o.x=h,o.y=p,t.dragStartPosition.x=t.position.x,t.dragStartPosition.y=t.position.y,s(r),t.run();var u=void 0,v=void 0;v=function(i){t.isDragging=!1,n?(window.removeEventListener("touchmove",s),window.removeEventListener("touchend",u)):(window.removeEventListener("mousemove",s),window.removeEventListener("mouseup",u))},n?(u=window.addEventListener("touchend",v),window.addEventListener("touchmove",s)):(u=window.addEventListener("mouseup",v),window.addEventListener("mousemove",s))}};var r=null;this.events.wheel=function(i){t.velocity.x=0,t.isScrollEnabled&&(t.isScrolling=!0,t.scrollOffset.x=-i.deltaX,t.scrollOffset.y=-i.deltaY,t.run(),clearTimeout(r),r=setTimeout(function(){return t.isScrolling=!1},80),i.preventDefault())},this.events.scroll=function(i){var o=t.props.viewport.scrollLeft,n=t.props.viewport.scrollTop;Math.abs(t.position.x+o)>3&&(t.position.x=-o,t.velocity.x=0),Math.abs(t.position.y+n)>3&&(t.position.y=-n,t.velocity.y=0),e.x=-t.props.viewport.scrollLeft,e.y=-t.props.viewport.scrollTop},this.events.resize=this.updateMetrics.bind(this),this.props.handle.addEventListener("mousedown",this.events.pointerdown),this.props.handle.addEventListener("touchstart",this.events.pointerdown),this.props.viewport.addEventListener("wheel",this.events.wheel),this.props.viewport.addEventListener("scroll",this.events.scroll),window.addEventListener("resize",this.events.resize)}},{key:"destroy",value:function(){this.props.handle.removeEventListener("mousedown",this.events.pointerdown),this.props.handle.removeEventListener("touchstart",this.events.pointerdown),this.props.viewport.removeEventListener("wheel",this.events.wheel),this.props.viewport.removeEventListener("scroll",this.events.scroll),window.removeEventListener("resize",this.events.resize)}}]),t}();i.default=p,t.exports=i.default}])}); |
{ | ||
"name": "scrollbooster", | ||
"description": "Enjoyable content dragging library", | ||
"version": "1.0.2", | ||
"description": "Enjoyable content drag-to-scroll library", | ||
"version": "1.0.3", | ||
"author": "Ilya Shubin <pixelwake@gmail.com>", | ||
@@ -18,2 +18,15 @@ "license": "MIT", | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ilyashubin/scrollbooster.git" | ||
}, | ||
"keywords": [ | ||
"drag", | ||
"draggable", | ||
"scroll", | ||
"scrollable", | ||
"UI", | ||
"microlibrary" | ||
], | ||
"homepage": "https://ilyashubin.github.io/scrollbooster", | ||
"devDependencies": { | ||
@@ -20,0 +33,0 @@ "babel-core": "^6.26.0", |
# ScrollBooster | ||
Enjoyable content drag-to-scroll micro (~2KB gzipped) library. | ||
### Installation | ||
You can install it via `npm` package manager or just drop a `script` tag: | ||
``` bash | ||
npm i scrollbooster | ||
``` | ||
``` | ||
``` html | ||
<script src="https://unpkg.com/scrollbooster@1.0.3/dist/scrollbooster.min.js"></script> | ||
``` | ||
### Usage | ||
``` js | ||
import ScrollBooster from 'scrollbooster' | ||
let sb = new ScrollBooster({ | ||
viewport: document.querySelector('.viewport') // required | ||
// ...other options | ||
}) | ||
``` | ||
### Options | ||
Option | Type | Default | Description | ||
------ | ---- | ------- | ----------- | ||
viewport | element | null | Viewport - outer element | ||
content | element | First child of viewport element | Scrollable content inside viewport | ||
handle | element | Viewport element | Element that respond to drag event | ||
bounce | boolean | true | Inertia bounce effect (scroll past viewport borders) | ||
friction | float | 0.05 | Scroll friction factor (scroll inertia after pointer release) | ||
bounceForce | float | 0.1 | Bounce effect factor | ||
emulateScroll | boolean | false | Emulate viewport mouse wheel events (for cases when scrolling with `transform` property) | ||
onUpdate | function | noop | User function that updates element properties according to received coordinates (see demo examples). Receives object with properties: `position`, `viewport` and `content`. Each property contains metrics to perform an actual scrolling | ||
### Methods | ||
Method | Description | ||
------ | ----------- | ||
setPosition | Sets new scroll position in viewport. Receives an object with properties `x` and `y` | ||
updateMetrics | Updates element sizes. Useful for images loading or other dynamic content | ||
getUpdate | Returns current metrics and coordinates in a same format as `onUpdate` | ||
destroy | Destroys all instance's event listeners | ||
### Full Example | ||
``` js | ||
let viewport = document.querySelector('.viewport') | ||
let content = document.querySelector('.viewport-content') | ||
let sb = new ScrollBooster({ | ||
viewport: viewport, | ||
content: content, | ||
handle: document.querySelector('.viewport-scroller'), | ||
bounce: true, | ||
emulateScroll: false, | ||
onUpdate: (data)=> { | ||
content.style.transform = `translate( | ||
${-data.position.x}px, | ||
${-data.position.y}px | ||
)` | ||
// and also metrics: data.viewport['width'|'height'] and data.cotent['width'|'height'] | ||
} | ||
}) | ||
// methods example: | ||
sb.updateMetrics() | ||
sb.setPosition({ | ||
x: 100, | ||
y: 100 | ||
}) | ||
sb.destroy() | ||
``` | ||
### Browser support | ||
ScrollBooster has been tested in IE 11, Edge and other modern browsers (Chrome, Firefox, Safari). | ||
### Special thanks | ||
David DeSandro for his talk ["Practical UI Physics"](https://www.youtube.com/watch?v=90oMnMFozEE). | ||
### License | ||
MIT License (c) Ilya Shubin |
@@ -13,3 +13,5 @@ export default class ScrollBooster { | ||
bounce: true, | ||
onUpdate: function () { } | ||
friction: 0.05, | ||
bounceForce: 0.1, | ||
onUpdate: function () {} | ||
} | ||
@@ -35,3 +37,4 @@ | ||
this.velocity = { x: 0, y: 0 } | ||
this.friction = 0.95 | ||
this.friction = 1 - this.props.friction | ||
this.bounceForce = this.props.bounceForce | ||
@@ -72,2 +75,5 @@ this.isDragging = false | ||
/** | ||
* Run update loop | ||
*/ | ||
run() { | ||
@@ -101,2 +107,3 @@ this.isRunning = true | ||
// if bounce effect is disabled | ||
if (!this.bounce || this.isScrolling) { | ||
@@ -107,2 +114,3 @@ this.position.x = Math.max(Math.min(this.position.x, this.boundX.to), this.boundX.from) | ||
// stop update loop if nothing moves | ||
if ( | ||
@@ -123,2 +131,5 @@ !this.isDragging && | ||
/** | ||
* Apply force for bounce effect | ||
*/ | ||
applyBoundForce() { | ||
@@ -135,2 +146,3 @@ if (!this.bounce) { return } | ||
// scrolled past left of right viewport boundaries | ||
if (pastLeft || pastRight) { | ||
@@ -140,3 +152,3 @@ let bound = pastLeft ? this.boundX.from : this.boundX.to | ||
let force = distance * 0.1 | ||
let force = distance * this.bounceForce | ||
var restX = this.position.x + (this.velocity.x + force) / (1 - this.friction) | ||
@@ -147,3 +159,3 @@ | ||
) { | ||
force = distance * 0.1 - this.velocity.x | ||
force = distance * this.bounceForce - this.velocity.x | ||
} | ||
@@ -154,2 +166,3 @@ | ||
// scrolled past top of bottom viewport boundaries | ||
if (pastTop || pastBottom) { | ||
@@ -159,3 +172,3 @@ let bound = pastTop ? this.boundY.from : this.boundY.to | ||
let force = distance * 0.1 | ||
let force = distance * this.bounceForce | ||
var restY = this.position.y + (this.velocity.y + force) / (1 - this.friction) | ||
@@ -166,3 +179,3 @@ | ||
) { | ||
force = distance * 0.1 - this.velocity.y | ||
force = distance * this.bounceForce - this.velocity.y | ||
} | ||
@@ -176,2 +189,5 @@ | ||
/** | ||
* Apply force to move content while dragging with mouse/touch | ||
*/ | ||
applyDragForce() { | ||
@@ -191,2 +207,5 @@ if (!this.isDragging) { return } | ||
/** | ||
* Apply force to emulate mouse wheel | ||
*/ | ||
applyScrollForce() { | ||
@@ -206,2 +225,5 @@ if (!this.isScrolling) { return } | ||
/** | ||
* Manual position setting | ||
*/ | ||
setPosition(newPosition = {}) { | ||
@@ -217,2 +239,5 @@ this.velocity.x = 0 | ||
/** | ||
* Get latest metrics and coordinates | ||
*/ | ||
getUpdate() { | ||
@@ -390,13 +415,7 @@ return { | ||
function getFullWidth (elem) { | ||
return Math.max( | ||
elem.offsetWidth, | ||
elem.scrollWidth | ||
) | ||
return Math.max(elem.offsetWidth, elem.scrollWidth) | ||
} | ||
function getFullHeight (elem) { | ||
return Math.max( | ||
elem.offsetHeight, | ||
elem.scrollHeight | ||
) | ||
return Math.max(elem.offsetHeight, elem.scrollHeight) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
93555
19
941
0
90
0