├── .npmignore ├── entry.js ├── .gitignore ├── package.json ├── LICENSE ├── .github └── workflows │ └── npmpublish.yml ├── webpack.config.js ├── readme.md ├── docs └── index.html ├── dist ├── kinet.min.js └── kinet.js └── src └── index.js /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | entry.js 3 | webpack.config.js 4 | .idea 5 | index.html 6 | docs -------------------------------------------------------------------------------- /entry.js: -------------------------------------------------------------------------------- 1 | // this is here for webpack to expose Kinet as window.Kinet 2 | import Kinet from './src/index.js' 3 | module.exports = Kinet -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.DS_Store 3 | !.gitignore 4 | !.htaccess 5 | !web.config 6 | node_modules 7 | bower_components 8 | Thumbs.db 9 | wiki-common 10 | wiki-images files 11 | wiki-wishlist 12 | *.sublime-project 13 | *.sublime-workspace 14 | .editorconfig 15 | .idea 16 | lib 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinet", 3 | "version": "2.2.1", 4 | "description": "Animate stuff with kinetic force.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "compile": "babel --presets es2015,stage-0 -d lib/ src/", 9 | "build": "webpack-cli", 10 | "prepublish": "npm run compile && npm run build" 11 | }, 12 | "author": "Georgy Marchuk", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/gmrchk/kinet.git" 17 | }, 18 | "keywords": [ 19 | "kinetic", 20 | "animation" 21 | ], 22 | "dependencies": {}, 23 | "devDependencies": { 24 | "babel-cli": "^6.26.0", 25 | "babel-loader": "^7.1.4", 26 | "babel-preset-es2015": "^6.24.1", 27 | "babel-preset-stage-0": "^6.24.1", 28 | "uglifyjs-webpack-plugin": "^1.2.5", 29 | "webpack": "^4.8.3", 30 | "webpack-cli": "^2.1.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Georgy Marchuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | push: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v1 16 | - uses: actions/setup-node@v1 17 | with: 18 | node-version: 12 19 | - run: npm ci 20 | - run: npm test 21 | 22 | publish-npm: 23 | needs: build 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v1 27 | - uses: actions/setup-node@v1 28 | with: 29 | node-version: 12 30 | registry-url: https://registry.npmjs.org/ 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | 35 | publish-gpr: 36 | needs: build 37 | runs-on: ubuntu-latest 38 | steps: 39 | - uses: actions/checkout@v1 40 | - uses: actions/setup-node@v1 41 | with: 42 | node-version: 12 43 | registry-url: https://npm.pkg.github.com/ 44 | - run: npm publish 45 | env: 46 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 47 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 3 | 4 | const baseConfig = { 5 | mode: "production", 6 | module: { 7 | rules: [ 8 | { 9 | test: /\.js$/, 10 | loader: 'babel-loader', 11 | exclude: /node_modules/, 12 | options: { 13 | presets: ['es2015', 'stage-0'], 14 | } 15 | } 16 | ] 17 | }, 18 | optimization: { 19 | minimizer: [ 20 | // we specify a custom UglifyJsPlugin here to get source maps in production 21 | new UglifyJsPlugin({ 22 | uglifyOptions: { 23 | compress: false, 24 | ecma: 6, 25 | mangle: true 26 | }, 27 | include: /\.min\.js$/ 28 | }) 29 | ] 30 | } 31 | } 32 | 33 | const config = Object.assign({}, baseConfig, { 34 | entry: { 35 | "kinet": "./entry.js", 36 | "kinet.min": "./entry.js", 37 | }, 38 | output: { 39 | path: __dirname + "/dist/", 40 | library: "Kinet", 41 | libraryTarget: "umd", 42 | filename: "[name].js", 43 | }, 44 | }) 45 | 46 | module.exports = config 47 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Kinet 2 | Kind of a most lightweight animation library of all. Kinet lets you animate with that spring effect so you can use the values wherever you need to. 3 | 4 | ## Installation 5 | Include Kinet with scripts tag 6 | 7 | ```html 8 | 9 | ``` 10 | or with *npm* and *import* 11 | ```shell 12 | npm install kinet --save 13 | ``` 14 | ```javascript 15 | // import needed modules from npm 16 | import Kinet from 'kinet'; 17 | ``` 18 | 19 | ## Options 20 | Kinet accepts several options defined as follows. 21 | ```javascript 22 | var options = { option: "value" } 23 | var kinet = new Kinet(options); 24 | ``` 25 | 26 | ### friction 27 | Recommended value 0-1. Default value is `0.3`. 28 | 29 | ### acceleration 30 | Recommended value 0-1. Default value is `0.04`. 31 | 32 | ### initialValue 33 | Sets the initial value of `current` and `target` variables in animated instances. 34 | 35 | ### names 36 | Array of names (strings). Kinet creates animated instance for each name. Defaults to single `x` value in array. 37 | 38 | ### test 39 | Function testing whether the animation has finished. Function gets and animated instance as an argument. 40 | When test function returns false for all animated instances, Kinet stops the animation and sets values to target values. 41 | 42 | ```javascript 43 | // default value 44 | test: function (instance) { 45 | return Math.abs(instance.current - instance.target) > 0.1; 46 | } 47 | ``` 48 | 49 | ## Methods 50 | ```javascript 51 | var kinet = new Kinet({name: ["x", "y"]}); 52 | ``` 53 | 54 | ### set 55 | Sets value of current and target of animated instance to required value without animating. 56 | ```javascript 57 | var kinet = new Kinet(); 58 | kinet.set("x", 10); // sets to number 10 59 | ``` 60 | 61 | ### animate 62 | Animates value of current variable of animated instance to target value without animating. 63 | ```javascript 64 | var kinet = new Kinet(); 65 | kinet.animate("x", 10); // animates to number 10 66 | ``` 67 | 68 | ### on 69 | Sets handler for event. Available events are `start` (called at start of animation), `end` (called at the end of animation) and `tick` (called for every tick of animation). 70 | Tick is called with `requestAnimationFrame` as the `current` value progresses to `target` value. 71 | ```javascript 72 | // init 73 | var kinet = new Kinet(); 74 | 75 | // set handler 76 | kinet.on('tick', function () { 77 | // do something on every animation tick 78 | }); 79 | ``` 80 | 81 | 82 | ### off 83 | Removes handler. 84 | ```javascript 85 | kinet.off('tick', handler); // removes single handler 86 | kinet.off('tick'); // removes all handlers for 'tick' event 87 | kinet.off(); // removes all handlers 88 | ``` 89 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Kinet 9 | 63 | 64 | 65 | 66 |
67 |
68 |

Kinet

69 |

DEMO Source

70 | Star 71 |
72 |
73 |
74 | 75 | 76 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /dist/kinet.min.js: -------------------------------------------------------------------------------- 1 | (function t(e,n){if(typeof exports==="object"&&typeof module==="object")module.exports=n();else if(typeof define==="function"&&define.amd)define([],n);else if(typeof exports==="object")exports["Kinet"]=n();else e["Kinet"]=n()})(window,function(){return function(t){var e={};function n(i){if(e[i]){return e[i].exports}var r=e[i]={i,l:false,exports:{}};t[i].call(r.exports,r,r.exports,n);r.l=true;return r.exports}n.m=t;n.c=e;n.d=function(t,e,i){if(!n.o(t,e)){Object.defineProperty(t,e,{enumerable:true,get:i})}};n.r=function(t){if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(t,"__esModule",{value:true})};n.t=function(t,e){if(e&1)t=n(t);if(e&8)return t;if(e&4&&typeof t==="object"&&t&&t.__esModule)return t;var i=Object.create(null);n.r(i);Object.defineProperty(i,"default",{enumerable:true,value:t});if(e&2&&typeof t!="string")for(var r in t)n.d(i,r,function(e){return t[e]}.bind(null,r));return i};n.n=function(t){var e=t&&t.__esModule?function e(){return t["default"]}:function e(){return t};n.d(e,"a",e);return e};n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)};n.p="";return n(n.s=0)}([function(t,e,n){"use strict";var i=n(1);var r=s(i);function s(t){return t&&t.__esModule?t:{default:t}}t.exports=r.default},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:true});var i=Object.assign||function(t){for(var e=1;e.1}};this._options=i({},r,e);if(e&&e.friction){this._options.friction=1-e.friction}this._instances={};this._options.names.forEach(function(t){n._instances[t]=new o(n._options.initialValue,n._options.acceleration,n._options.friction)});this._raf=null}r(t,[{key:"set",value:function t(e,n){var i=this;if(n==null){console.warn("Define a value.");return}if(this._instances[e]==null){console.warn('Instance "'+e+"\" doesn't exist.");return}this._instances[e].current=n;this._instances[e].target=n;if(!this._raf){this._handlers["set"].forEach(function(t){return t(i._instances)});this._handlers["tick"].forEach(function(t){return t(i._instances)})}}},{key:"animate",value:function t(e,n){var i=this;if(n==null){console.warn("Define a value.");return}if(this._instances[e]==null){console.warn("Instance "+e+" doesn't exist.");return}if(this._instances[e].target!==n){this._instances[e].target=n;if(!this._raf){this._handlers["start"].forEach(function(t){return t(i._instances,i._instances)});this._animateValues()}return n}return false}},{key:"_animateValues",value:function t(){var e=this;var n=true;Object.keys(this._instances).forEach(function(t){e._instances[t].update();if(e._options.test(e._instances[t])){n=false}});if(!n){this._raf=requestAnimationFrame(this._animateValues.bind(this));this._handlers["tick"].forEach(function(t){return t(e._instances)})}else{Object.keys(this._instances).forEach(function(t){e._instances[t].current=e._instances[t].target;e._instances[t].velocity=0});this._handlers["tick"].forEach(function(t){return t(e._instances)});this._handlers["end"].forEach(function(t){return t(e._instances)});this._raf=null}}},{key:"on",value:function t(e,n){if(this._handlers[e]){this._handlers[e].push(n)}else{console.warn("Unsupported event "+e+".")}}},{key:"off",value:function t(e,n){var i=this;if(e!=null){if(n!=null){if(this._handlers[e]&&this._handlers[e].filter(function(t){return t===n}).length){var r=this._handlers[e].filter(function(t){return t===n})[0];var s=this._handlers[e].indexOf(r);if(s>-1){this._handlers[e].splice(s,1)}}else{console.warn("Handler for event "+e+" no found.")}}else{this._handlers[e]=[]}}else{Object.keys(this._handlers).forEach(function(t){i._handlers[t]=[]})}}}]);return t}();e.default=a;var o=function(){function t(e,n,i){s(this,t);this.current=e;this.target=e;this._acceleration=n;this._friction=i;this.velocity=0}r(t,[{key:"update",value:function t(){var e=this.target-this.current;var n=e*this._acceleration;this.applyForce(n);this.velocity*=this._friction;this.current+=this.velocity;return e}},{key:"applyForce",value:function t(e){this.velocity+=e}}]);return t}()}])}); -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export default class Kinet { 2 | 3 | constructor(options) { 4 | this._handlers = { 5 | set: [], 6 | start: [], 7 | tick: [], 8 | end: [], 9 | }; 10 | 11 | let dafaults = { 12 | friction: 1 - 0.3, 13 | acceleration: 0.04, 14 | initialValue: 0, 15 | names: ["x"], 16 | test: function (instance) { 17 | return Math.abs(instance.current - instance.target) > 0.1; 18 | }, 19 | }; 20 | 21 | this._options = { 22 | ...dafaults, 23 | ...options, 24 | }; 25 | 26 | // to set correct value (1 - x) 27 | if (options && options.friction) { 28 | this._options.friction = 1 - options.friction; 29 | } 30 | 31 | this._instances = {}; 32 | this._options.names.forEach(name => { 33 | this._instances[name] = new KinetItem(this._options.initialValue, this._options.acceleration, this._options.friction); 34 | }); 35 | 36 | this._raf = null; 37 | } 38 | 39 | set(name, num) { 40 | if (num == null) { 41 | console.warn('Define a value.'); 42 | return; 43 | } 44 | if (this._instances[name] == null) { 45 | console.warn(`Instance "${name}" doesn't exist.`); 46 | return; 47 | } 48 | this._instances[name].current = num; 49 | this._instances[name].target = num; 50 | if (!this._raf) { 51 | this._handlers['set'].forEach(handler => handler(this._instances)); 52 | this._handlers['tick'].forEach(handler => handler(this._instances)); 53 | } 54 | } 55 | 56 | animate(name, num) { 57 | if (num == null) { 58 | console.warn('Define a value.'); 59 | return; 60 | } 61 | if (this._instances[name] == null) { 62 | console.warn(`Instance ${name} doesn't exist.`); 63 | return; 64 | } 65 | if (this._instances[name].target !== num) { 66 | this._instances[name].target = num; 67 | if (!this._raf) { 68 | this._handlers['start'].forEach(handler => handler(this._instances, this._instances)); 69 | this._animateValues(); 70 | } 71 | return num; 72 | } 73 | 74 | return false; 75 | } 76 | 77 | _animateValues() { 78 | let done = true; 79 | 80 | Object.keys(this._instances).forEach(key => { 81 | this._instances[key].update(); 82 | 83 | if (this._options.test(this._instances[key])) { 84 | done = false; 85 | } 86 | }); 87 | 88 | if (!done) { 89 | this._raf = requestAnimationFrame(this._animateValues.bind(this)); 90 | this._handlers['tick'].forEach(handler => handler(this._instances)); 91 | } else { 92 | // set to final values 93 | Object.keys(this._instances).forEach(key => { 94 | this._instances[key].current = this._instances[key].target; 95 | this._instances[key].velocity = 0; 96 | }); 97 | 98 | this._handlers['tick'].forEach(handler => handler(this._instances)); 99 | this._handlers['end'].forEach(handler => handler(this._instances)); 100 | this._raf = null; 101 | } 102 | } 103 | 104 | on(event, handler) { 105 | if (this._handlers[event]) { 106 | this._handlers[event].push(handler); 107 | } else { 108 | console.warn(`Unsupported event ${event}.`); 109 | } 110 | } 111 | 112 | off(event, handler) { 113 | if (event != null) { 114 | if (handler != null) { 115 | if (this._handlers[event] && this._handlers[event].filter(savedHandler => savedHandler === handler).length) { 116 | let toRemove = this._handlers[event].filter(savedHandler => savedHandler === handler)[0]; 117 | let index = this._handlers[event].indexOf(toRemove); 118 | if (index > -1) { 119 | this._handlers[event].splice(index, 1); 120 | } 121 | } else { 122 | console.warn(`Handler for event ${event} no found.`); 123 | } 124 | } else { 125 | this._handlers[event] = []; 126 | } 127 | } else { 128 | Object.keys(this._handlers).forEach(keys => { 129 | this._handlers[keys] = []; 130 | }); 131 | } 132 | } 133 | 134 | } 135 | 136 | class KinetItem { 137 | constructor(intitalValue, acceleration, friction) { 138 | this.current = intitalValue; 139 | this.target = intitalValue; 140 | this._acceleration = acceleration; 141 | this._friction = friction; 142 | this.velocity = 0; 143 | } 144 | 145 | update() { 146 | const distance = this.target - this.current; 147 | const attraction = distance * this._acceleration; 148 | 149 | this.applyForce(attraction); 150 | 151 | this.velocity *= this._friction; 152 | this.current += this.velocity; 153 | 154 | return distance; 155 | } 156 | 157 | applyForce(force) { 158 | this.velocity += force; 159 | } 160 | } -------------------------------------------------------------------------------- /dist/kinet.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define([], factory); 6 | else if(typeof exports === 'object') 7 | exports["Kinet"] = factory(); 8 | else 9 | root["Kinet"] = factory(); 10 | })(window, function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) { 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ } 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // define getter function for harmony exports 47 | /******/ __webpack_require__.d = function(exports, name, getter) { 48 | /******/ if(!__webpack_require__.o(exports, name)) { 49 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 50 | /******/ } 51 | /******/ }; 52 | /******/ 53 | /******/ // define __esModule on exports 54 | /******/ __webpack_require__.r = function(exports) { 55 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 56 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 57 | /******/ } 58 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 59 | /******/ }; 60 | /******/ 61 | /******/ // create a fake namespace object 62 | /******/ // mode & 1: value is a module id, require it 63 | /******/ // mode & 2: merge all properties of value into the ns 64 | /******/ // mode & 4: return value when already ns object 65 | /******/ // mode & 8|1: behave like require 66 | /******/ __webpack_require__.t = function(value, mode) { 67 | /******/ if(mode & 1) value = __webpack_require__(value); 68 | /******/ if(mode & 8) return value; 69 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 70 | /******/ var ns = Object.create(null); 71 | /******/ __webpack_require__.r(ns); 72 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 73 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 74 | /******/ return ns; 75 | /******/ }; 76 | /******/ 77 | /******/ // getDefaultExport function for compatibility with non-harmony modules 78 | /******/ __webpack_require__.n = function(module) { 79 | /******/ var getter = module && module.__esModule ? 80 | /******/ function getDefault() { return module['default']; } : 81 | /******/ function getModuleExports() { return module; }; 82 | /******/ __webpack_require__.d(getter, 'a', getter); 83 | /******/ return getter; 84 | /******/ }; 85 | /******/ 86 | /******/ // Object.prototype.hasOwnProperty.call 87 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 88 | /******/ 89 | /******/ // __webpack_public_path__ 90 | /******/ __webpack_require__.p = ""; 91 | /******/ 92 | /******/ 93 | /******/ // Load entry module and return exports 94 | /******/ return __webpack_require__(__webpack_require__.s = 0); 95 | /******/ }) 96 | /************************************************************************/ 97 | /******/ ([ 98 | /* 0 */ 99 | /***/ (function(module, exports, __webpack_require__) { 100 | 101 | "use strict"; 102 | 103 | 104 | var _index = __webpack_require__(1); 105 | 106 | var _index2 = _interopRequireDefault(_index); 107 | 108 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 109 | 110 | module.exports = _index2.default; // this is here for webpack to expose Kinet as window.Kinet 111 | 112 | /***/ }), 113 | /* 1 */ 114 | /***/ (function(module, exports, __webpack_require__) { 115 | 116 | "use strict"; 117 | 118 | 119 | Object.defineProperty(exports, "__esModule", { 120 | value: true 121 | }); 122 | 123 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 124 | 125 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 126 | 127 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 128 | 129 | var Kinet = function () { 130 | function Kinet(options) { 131 | var _this = this; 132 | 133 | _classCallCheck(this, Kinet); 134 | 135 | this._handlers = { 136 | set: [], 137 | start: [], 138 | tick: [], 139 | end: [] 140 | }; 141 | 142 | var dafaults = { 143 | friction: 1 - 0.3, 144 | acceleration: 0.04, 145 | initialValue: 0, 146 | names: ["x"], 147 | test: function test(instance) { 148 | return Math.abs(instance.current - instance.target) > 0.1; 149 | } 150 | }; 151 | 152 | this._options = _extends({}, dafaults, options); 153 | 154 | // to set correct value (1 - x) 155 | if (options && options.friction) { 156 | this._options.friction = 1 - options.friction; 157 | } 158 | 159 | this._instances = {}; 160 | this._options.names.forEach(function (name) { 161 | _this._instances[name] = new KinetItem(_this._options.initialValue, _this._options.acceleration, _this._options.friction); 162 | }); 163 | 164 | this._raf = null; 165 | } 166 | 167 | _createClass(Kinet, [{ 168 | key: 'set', 169 | value: function set(name, num) { 170 | var _this2 = this; 171 | 172 | if (num == null) { 173 | console.warn('Define a value.'); 174 | return; 175 | } 176 | if (this._instances[name] == null) { 177 | console.warn('Instance "' + name + '" doesn\'t exist.'); 178 | return; 179 | } 180 | this._instances[name].current = num; 181 | this._instances[name].target = num; 182 | if (!this._raf) { 183 | this._handlers['set'].forEach(function (handler) { 184 | return handler(_this2._instances); 185 | }); 186 | this._handlers['tick'].forEach(function (handler) { 187 | return handler(_this2._instances); 188 | }); 189 | } 190 | } 191 | }, { 192 | key: 'animate', 193 | value: function animate(name, num) { 194 | var _this3 = this; 195 | 196 | if (num == null) { 197 | console.warn('Define a value.'); 198 | return; 199 | } 200 | if (this._instances[name] == null) { 201 | console.warn('Instance ' + name + ' doesn\'t exist.'); 202 | return; 203 | } 204 | if (this._instances[name].target !== num) { 205 | this._instances[name].target = num; 206 | if (!this._raf) { 207 | this._handlers['start'].forEach(function (handler) { 208 | return handler(_this3._instances, _this3._instances); 209 | }); 210 | this._animateValues(); 211 | } 212 | return num; 213 | } 214 | 215 | return false; 216 | } 217 | }, { 218 | key: '_animateValues', 219 | value: function _animateValues() { 220 | var _this4 = this; 221 | 222 | var done = true; 223 | 224 | Object.keys(this._instances).forEach(function (key) { 225 | _this4._instances[key].update(); 226 | 227 | if (_this4._options.test(_this4._instances[key])) { 228 | done = false; 229 | } 230 | }); 231 | 232 | if (!done) { 233 | this._raf = requestAnimationFrame(this._animateValues.bind(this)); 234 | this._handlers['tick'].forEach(function (handler) { 235 | return handler(_this4._instances); 236 | }); 237 | } else { 238 | // set to final values 239 | Object.keys(this._instances).forEach(function (key) { 240 | _this4._instances[key].current = _this4._instances[key].target; 241 | _this4._instances[key].velocity = 0; 242 | }); 243 | 244 | this._handlers['tick'].forEach(function (handler) { 245 | return handler(_this4._instances); 246 | }); 247 | this._handlers['end'].forEach(function (handler) { 248 | return handler(_this4._instances); 249 | }); 250 | this._raf = null; 251 | } 252 | } 253 | }, { 254 | key: 'on', 255 | value: function on(event, handler) { 256 | if (this._handlers[event]) { 257 | this._handlers[event].push(handler); 258 | } else { 259 | console.warn('Unsupported event ' + event + '.'); 260 | } 261 | } 262 | }, { 263 | key: 'off', 264 | value: function off(event, handler) { 265 | var _this5 = this; 266 | 267 | if (event != null) { 268 | if (handler != null) { 269 | if (this._handlers[event] && this._handlers[event].filter(function (savedHandler) { 270 | return savedHandler === handler; 271 | }).length) { 272 | var toRemove = this._handlers[event].filter(function (savedHandler) { 273 | return savedHandler === handler; 274 | })[0]; 275 | var index = this._handlers[event].indexOf(toRemove); 276 | if (index > -1) { 277 | this._handlers[event].splice(index, 1); 278 | } 279 | } else { 280 | console.warn('Handler for event ' + event + ' no found.'); 281 | } 282 | } else { 283 | this._handlers[event] = []; 284 | } 285 | } else { 286 | Object.keys(this._handlers).forEach(function (keys) { 287 | _this5._handlers[keys] = []; 288 | }); 289 | } 290 | } 291 | }]); 292 | 293 | return Kinet; 294 | }(); 295 | 296 | exports.default = Kinet; 297 | 298 | var KinetItem = function () { 299 | function KinetItem(intitalValue, acceleration, friction) { 300 | _classCallCheck(this, KinetItem); 301 | 302 | this.current = intitalValue; 303 | this.target = intitalValue; 304 | this._acceleration = acceleration; 305 | this._friction = friction; 306 | this.velocity = 0; 307 | } 308 | 309 | _createClass(KinetItem, [{ 310 | key: 'update', 311 | value: function update() { 312 | var distance = this.target - this.current; 313 | var attraction = distance * this._acceleration; 314 | 315 | this.applyForce(attraction); 316 | 317 | this.velocity *= this._friction; 318 | this.current += this.velocity; 319 | 320 | return distance; 321 | } 322 | }, { 323 | key: 'applyForce', 324 | value: function applyForce(force) { 325 | this.velocity += force; 326 | } 327 | }]); 328 | 329 | return KinetItem; 330 | }(); 331 | 332 | /***/ }) 333 | /******/ ]); 334 | }); --------------------------------------------------------------------------------