├── .gitignore
├── .npmignore
├── LICENSE.md
├── README.md
├── bundle.js
├── index.html
├── index.js
├── package.json
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | *.log
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | *.log
4 | .DS_Store
5 | bundle.js
6 | test
7 | test.js
8 | demo/
9 | .npmignore
10 | LICENSE.md
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2015 Matt DesLauriers
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
20 | OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # spring-input
2 |
3 | [](http://github.com/badges/stability-badges)
4 |
5 | A utility to provide a springy mouse and touch input, similar to bouncy scroll panels in iOS. This can be used in a variety of applications, such as scrolling, rotating a 3D camera, flicking a 2D card, etc.
6 |
7 | Demo:
8 |
9 | [http://mattdesl.github.io/spring-input/](http://mattdesl.github.io/spring-input/)
10 |
11 |
12 |
13 | Adapted from [touch-scroll-physics](https://github.com/Jam3/touch-scroll-physics/), which is more application-specific than this module.
14 |
15 | ## Install
16 |
17 | ```sh
18 | npm install spring-input --save
19 | ```
20 |
21 | ## Example
22 |
23 | See [test.js](./test.js) for a full example.
24 |
25 | ```js
26 | var createSpring = require('spring-input')
27 |
28 | // e.g. a slider along the x-axis
29 | var spring = createSpring({
30 | min: 0, // min bound
31 | max: 1, // max bound
32 | edge: 0.1, // gutter size
33 | value: 0.5, // initial value
34 | damping: 0.25, // flick friction
35 | spring: 0.15 // "bounce back" friction
36 | })
37 |
38 | function onDragStart (x, y) {
39 | spring.start(x)
40 | }
41 |
42 | function onDragMove (x, y) {
43 | spring.move(x)
44 | }
45 |
46 | function onDragEnd (x, y) {
47 | spring.end(x)
48 | }
49 |
50 | function onRequestAnimationFrame () {
51 | spring.update()
52 | }
53 | ```
54 |
55 | This is a low-level module, intended to be used with your own input handling and update loop. This can be easily combined with the following modules:
56 |
57 | - [touches](https://github.com/Jam3/touches) - unified mouse / touch input and drag events
58 | - [mouse-wheel](http://npmjs.com/package/mouse-wheel) - cross-browser mouse wheel events
59 | - [raf-loop](https://www.npmjs.com/package/raf-loop) - a simple requestAnimationFrame loop
60 |
61 | ## Usage
62 |
63 | [](https://www.npmjs.com/package/spring-input)
64 |
65 | #### `spring = createSpring([opt])`
66 |
67 | Creates a new sprint input with the optional settings:
68 |
69 | - `value` - the initial value, default 0
70 | - `min` - the minimum bound, default 0 (can be `-Infinity`)
71 | - `max` - the maximum bound, default 1 (can be `Infinity`)
72 | - `edge` - the relative edge gutter size, default 0 (i.e. no "bounce back")
73 | - `damping` - adjusts the friction when flicking; defualt 0.3
74 | - `spring` - adjusts the friction when bouncing back; default 0.2
75 | - `maxVelocity` - the maximum velocity in a flick, default 0.05
76 |
77 | All values can be changed during runtime, eg:
78 |
79 | ```js
80 | spring.max = newScrollHeight
81 | ```
82 |
83 | #### `spring.start(value)`
84 |
85 | Called to trigger a "start" event with the specified `value`, such as the initial X mouse position.
86 |
87 | #### `spring.move(value)`
88 |
89 | Called to trigger a "move" event with the specified `value`, such as a new mouse X position.
90 |
91 | #### `spring.end()`
92 |
93 | Stops user input, allowing the value to be integrated and slide into place.
94 |
95 | #### `spring.update()`
96 |
97 | Integrates the spring. Should be called once per animation loop.
98 |
99 | #### `spring.value`
100 |
101 | The currently integrated value.
102 |
103 | #### `spring.velocity`
104 |
105 | The current velocity.
106 |
107 | ## See Also
108 |
109 | - [touch-scroll-physics](https://github.com/Jam3/touch-scroll-physics/) very similar, but more application-specific
110 |
111 | ## License
112 |
113 | MIT, see [LICENSE.md](http://github.com/mattdesl/spring-input/blob/master/LICENSE.md) for details.
114 |
--------------------------------------------------------------------------------
/bundle.js:
--------------------------------------------------------------------------------
1 | !function t(e,n,r){function i(o,u){if(!n[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);var c=new Error("Cannot find module '"+o+"'");throw c.code="MODULE_NOT_FOUND",c}var h=n[o]={exports:{}};e[o][0].call(h.exports,function(t){var n=e[o][1][t];return i(n?n:t)},h,h.exports,t,e,n,r)}return n[o].exports}for(var s="function"==typeof require&&require,o=0;othis.max,n=!this.interacting,r=0;t?(this.velocity=0,this.inputDelta<0&&0!==this.edge&&(this.inputDelta*=1-Math.abs(this.value-this.min)/this.edge)):e&&(this.velocity=0,this.inputDelta>0&&0!==this.edge&&(this.inputDelta*=1-Math.abs(this.value-this.max)/this.edge)),n&&(t?r=this.value-this.min:e&&(r=this.value-this.max),r*=this.spring),this.value+=this.inputDelta,this.inputDelta=0,this.interacting||(this.value+=this.velocity),this.velocity*=1-this.damping,this.value-=r,this.value=s(this.value,this.min-this.edge,this.max+this.edge)},i.prototype.start=function(t){this.interacting=!0,this.velocity=0,this.inputDelta=0,this.lastInput=t},i.prototype.move=function(t){if(this.interacting){var e=t-this.lastInput;this.value+e>this.max+this.edge&&(t=Math.min(t,this.max+this.edge)),this.value+e0&&(this.velocity=Math.min(this.velocity+this.inputDelta,n))}},i.prototype.end=function(){this.interacting=!1}},{clamp:4,defined:5}],2:[function(t,e,n){function r(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function i(t){return"function"==typeof t}function s(t){return"number"==typeof t}function o(t){return"object"==typeof t&&null!==t}function u(t){return void 0===t}e.exports=r,r.EventEmitter=r,r.prototype._events=void 0,r.prototype._maxListeners=void 0,r.defaultMaxListeners=10,r.prototype.setMaxListeners=function(t){if(!s(t)||0>t||isNaN(t))throw TypeError("n must be a positive number");return this._maxListeners=t,this},r.prototype.emit=function(t){var e,n,r,s,a,c;if(this._events||(this._events={}),"error"===t&&(!this._events.error||o(this._events.error)&&!this._events.error.length)){if(e=arguments[1],e instanceof Error)throw e;throw TypeError('Uncaught, unspecified "error" event.')}if(n=this._events[t],u(n))return!1;if(i(n))switch(arguments.length){case 1:n.call(this);break;case 2:n.call(this,arguments[1]);break;case 3:n.call(this,arguments[1],arguments[2]);break;default:for(r=arguments.length,s=new Array(r-1),a=1;r>a;a++)s[a-1]=arguments[a];n.apply(this,s)}else if(o(n)){for(r=arguments.length,s=new Array(r-1),a=1;r>a;a++)s[a-1]=arguments[a];for(c=n.slice(),r=c.length,a=0;r>a;a++)c[a].apply(this,s)}return!0},r.prototype.addListener=function(t,e){var n;if(!i(e))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",t,i(e.listener)?e.listener:e),this._events[t]?o(this._events[t])?this._events[t].push(e):this._events[t]=[this._events[t],e]:this._events[t]=e,o(this._events[t])&&!this._events[t].warned){var n;n=u(this._maxListeners)?r.defaultMaxListeners:this._maxListeners,n&&n>0&&this._events[t].length>n&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace())}return this},r.prototype.on=r.prototype.addListener,r.prototype.once=function(t,e){function n(){this.removeListener(t,n),r||(r=!0,e.apply(this,arguments))}if(!i(e))throw TypeError("listener must be a function");var r=!1;return n.listener=e,this.on(t,n),this},r.prototype.removeListener=function(t,e){var n,r,s,u;if(!i(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(n=this._events[t],s=n.length,r=-1,n===e||i(n.listener)&&n.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(o(n)){for(u=s;u-->0;)if(n[u]===e||n[u].listener&&n[u].listener===e){r=u;break}if(0>r)return this;1===n.length?(n.length=0,delete this._events[t]):n.splice(r,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},r.prototype.removeAllListeners=function(t){var e,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(n=this._events[t],i(n))this.removeListener(t,n);else for(;n.length;)this.removeListener(t,n[n.length-1]);return delete this._events[t],this},r.prototype.listeners=function(t){var e;return e=this._events&&this._events[t]?i(this._events[t])?[this._events[t]]:this._events[t].slice():[]},r.listenerCount=function(t,e){var n;return n=t._events&&t._events[e]?i(t._events[e])?1:t._events[e].length:0}},{}],3:[function(t,e,n){function r(){h=!1,u.length?c=u.concat(c):f=-1,c.length&&i()}function i(){if(!h){var t=setTimeout(r);h=!0;for(var e=c.length;e;){for(u=c,c=[];++f1)for(var n=1;ne?e>t?e:t>n?n:t:n>t?n:t>e?e:t}e.exports=r},{}],5:[function(t,e,n){e.exports=function(){for(var t=0;t
2 |
3 |
4 |
5 |
6 | spring-input
7 |
8 |
62 |
63 |
64 |