├── .editorconfig ├── .eslintrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── examples ├── back-easing.js ├── power4-ease-in-out.js └── simpleExp.js ├── package.json ├── src ├── ease-back.js ├── ease-bounce.js ├── ease-circ.js ├── ease-common.js ├── ease-elastic.js ├── ease-exponential.js ├── ease-powers.js ├── ease-sine.js └── index.js └── test ├── easings.js ├── index.js ├── main.js └── plot-utils.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "ecmaFeatures": { 7 | "arrowFunctions": true, 8 | "binaryLiterals": true, 9 | "regexUFlag": true, 10 | "regexYFlag": true, 11 | "unicodeCodePointEscapes": true, 12 | "destructuring": true, 13 | "modules": true, 14 | "defaultParams": true, 15 | "classes": true, 16 | "spread": true, 17 | "superInFunctions": true, 18 | "templateStrings": true, 19 | "objectLiteralShorthandMethods": true, 20 | "objectLiteralDuplicateProperties": true, 21 | "objectLiteralComputedProperties": true, 22 | "objectLiteralShorthandProperties": true, 23 | "generators": true, 24 | "forOf": true, 25 | "blockBindings": true 26 | }, 27 | "rules": { 28 | "no-cond-assign": [2, "always"], 29 | "no-ex-assign": 2, 30 | "curly": 2, 31 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 32 | "max-len": [2, 80, 4], 33 | "max-depth": [2, 5], 34 | "complexity": [1, 6], 35 | "indent": [2, 2], 36 | "no-trailing-spaces": 2, 37 | "one-var": "never", 38 | "func-names": 2, 39 | "key-spacing": [2, { 40 | "beforeColon": false, 41 | "afterColon": true 42 | }], 43 | "max-nested-callbacks": [2, 1], 44 | "new-cap": [2, {"newIsCap": true}], 45 | "new-parens": 2, 46 | "no-mixed-spaces-and-tabs": 2, 47 | "no-multiple-empty-lines": [1, {"max": 1}], 48 | "no-nested-ternary": 2, 49 | "no-new-object": 2, 50 | "no-spaced-func": 2, 51 | "operator-assignment": [2, "always"], 52 | "operator-linebreak": [2, "before"], 53 | "padded-blocks": [2, "never"], 54 | "quote-props": [2, "as-needed"], 55 | "space-after-keywords": [2, "always"], 56 | "space-before-blocks": [2, "always"], 57 | "space-before-function-paren": [2, "never"], 58 | "space-in-brackets": [2, "never"], 59 | "space-in-parens": [2, "never"], 60 | "space-infix-ops": [2, {"int32Hint": true}], 61 | "space-return-throw-case": 2, 62 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 63 | "no-delete-var": 2, 64 | "no-shadow": 2, 65 | "no-shadow-restricted-names": 2, 66 | "no-undef-init": 2, 67 | "no-undef": 2, 68 | "no-undefined": 2, 69 | "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], 70 | "no-use-before-define": 2, 71 | "yoda": [2, "never"], 72 | "consistent-return": 2, 73 | "spaced-line-comment": [2, "always"], 74 | "quotes": [2, "single"], 75 | "global-strict": [2, "always"], 76 | "eqeqeq": 2, 77 | "guard-for-in": 2, 78 | "no-alert": 2, 79 | "no-caller": 2, 80 | "no-labels": 2, 81 | "no-eval": 2, 82 | "no-fallthrough": 2, 83 | "default-case": 2, 84 | "no-iterator": 2, 85 | "no-loop-func": 2, 86 | "no-multi-spaces": 2, 87 | "no-multi-str": 2, 88 | "no-new": 2, 89 | "no-param-reassign": 2, 90 | "no-proto": 2, 91 | "no-redeclare": 2, 92 | "no-return-assign": 2, 93 | "no-self-compare": 2, 94 | "no-sequences": 2, 95 | "no-throw-literal": 2, 96 | "no-unused-expressions": 2, 97 | "no-with": 2, 98 | "vars-on-top": 0, 99 | "wrap-iife": [2, "outside"], 100 | "valid-typeof": 2, 101 | "max-statements": [1, 30], 102 | "max-params": [1, 3], 103 | "no-var": true, 104 | "semi": 2 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Editor-specific 2 | .idea 3 | *.sublime-project 4 | *.sublime-workspace 5 | .settings 6 | 7 | # Installed libs 8 | node_modules 9 | 10 | # Generated 11 | test/browser/page/tests-bundle.js 12 | lib/ 13 | 14 | # Misc 15 | ignore 16 | npm-debug.log 17 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Andre Medeiros 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 13 | all 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 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RxTween 2 | ======= 3 | 4 | [![npm version](https://badge.fury.io/js/rxtween.svg)](http://badge.fury.io/js/rxtween) 5 | 6 | **NOT ACTIVELY MAINTAINED. I'M LOOKING FOR A NEW MAINTAINER/OWNER FOR THIS REPOSITORY. [Contact me](http://staltz.com/) if you are interested.** 7 | 8 | A small helper library to create animation-related RxJS Observables. Specify a start value, an end value, the duration, and an easing function, and you get an Observable emitting the interpolated values in intervals over time. 9 | 10 | # Get started 11 | 12 | #### Installing 13 | 14 | Available only as an NPM package. 15 | 16 | `npm install rxtween` 17 | 18 | RxTween has RxJS as an npm peerDependency. This means RxTween will include RxJS into your project only if it isn't yet in your project. A good practice is to specify both `rxtween` and `rx` as your npm dependencies in `package.json`. 19 | 20 | #### Usage 21 | 22 | ```js 23 | import RxTween from 'rxtween'; 24 | 25 | let position$ = RxTween({ 26 | from: 0, 27 | to: 20, 28 | duration: 1000, 29 | ease: RxTween.Exp.easeIn, 30 | interval: 20 31 | }); 32 | ``` 33 | 34 | `RxTween` is a factory function taking an `options` object as the only parameter, and returns an `Rx.Observable` emitting JavaScript Numbers. The `options` object takes properties `from`, `to`, `duration`, `ease` (optional, the default is Linear easing), and `interval` (optional). 35 | 36 | # How it works 37 | 38 | `RxTween()` factory function returns an `Rx.Observable.interval` Observable mapped to the correct interpolated values according to `from`, `to`, and `duration`. This whole sequence of values lasts `duration` milliseconds. 39 | 40 | # Easing functions 41 | 42 | ### `RxTween.Linear.ease` 43 | 44 | ``` 45 | | # 46 | | # 47 | | # 48 | | # 49 | | # 50 | | # 51 | | # 52 | | # 53 | | # 54 | | # 55 | | # 56 | | # 57 | | # 58 | | # 59 | | # 60 | | # 61 | | # 62 | | # 63 | | # 64 | | # 65 | |# 66 | +--------------------- 67 | ``` 68 | 69 | ### `RxTween.Power2.easeIn` 70 | 71 | ``` 72 | | # 73 | | 74 | | # 75 | | 76 | | # 77 | | 78 | | # 79 | | # 80 | | 81 | | # 82 | | # 83 | | 84 | | # 85 | | # 86 | | # 87 | | # 88 | | # 89 | | # 90 | | ## 91 | | ## 92 | |#### 93 | +--------------------- 94 | ``` 95 | 96 | ### `RxTween.Power3.easeIn` 97 | 98 | ``` 99 | | # 100 | | 101 | | 102 | | # 103 | | 104 | | # 105 | | 106 | | 107 | | # 108 | | 109 | | # 110 | | 111 | | # 112 | | # 113 | | 114 | | # 115 | | # 116 | | ## 117 | | # 118 | | ### 119 | |###### 120 | +--------------------- 121 | ``` 122 | 123 | ### `RxTween.Power4.easeIn` 124 | 125 | ``` 126 | | # 127 | | 128 | | 129 | | 130 | | # 131 | | 132 | | 133 | | # 134 | | 135 | | 136 | | # 137 | | 138 | | # 139 | | 140 | | # 141 | | # 142 | | # 143 | | # 144 | | # 145 | | ### 146 | |######## 147 | +--------------------- 148 | ``` 149 | 150 | ### `RxTween.Exp.easeIn` 151 | 152 | ``` 153 | | # 154 | | 155 | | 156 | | 157 | | 158 | | # 159 | | 160 | | 161 | | 162 | | # 163 | | 164 | | 165 | | # 166 | | 167 | | # 168 | | 169 | | # 170 | | # 171 | | ## 172 | | ### 173 | |######### 174 | +--------------------- 175 | ``` 176 | 177 | ### `RxTween.Back.easeIn` 178 | 179 | ``` 180 | | # 181 | | 182 | | 183 | | 184 | | # 185 | | 186 | | 187 | | 188 | | # 189 | | 190 | | 191 | | # 192 | | 193 | | 194 | | # 195 | | 196 | | # 197 | | 198 | | # 199 | | 200 | |#____________# 201 | +--------------------- 202 | ``` 203 | 204 | ### `RxTween.Bounce.easeIn` 205 | 206 | ``` 207 | | ## 208 | | 209 | | # 210 | | # 211 | | 212 | | 213 | | # 214 | | 215 | | 216 | | # 217 | | 218 | | 219 | | 220 | | 221 | | # 222 | | ### 223 | | # 224 | | # 225 | | # 226 | | #### # 227 | |### 228 | +--------------------- 229 | ``` 230 | 231 | ### `RxTween.Circ.easeIn` 232 | 233 | ``` 234 | | # 235 | | 236 | | 237 | | 238 | | 239 | | 240 | | # 241 | | 242 | | 243 | | # 244 | | 245 | | # 246 | | # 247 | | # 248 | | # 249 | | # 250 | | # 251 | | ## 252 | | ## 253 | | ### 254 | |##### 255 | +--------------------- 256 | ``` 257 | 258 | ### `RxTween.Elastic.easeIn` 259 | 260 | ``` 261 | | # 262 | | 263 | | 264 | | 265 | | 266 | | 267 | | 268 | | 269 | | 270 | | 271 | | 272 | | 273 | | 274 | | # 275 | | 276 | | 277 | | 278 | | 279 | | ## 280 | | # 281 | |####___###___ ___ 282 | +--------------------- 283 | ``` 284 | 285 | ### `RxTween.Sine.easeIn` 286 | 287 | ``` 288 | | # 289 | | 290 | | # 291 | | # 292 | | 293 | | # 294 | | # 295 | | 296 | | # 297 | | # 298 | | # 299 | | 300 | | # 301 | | # 302 | | # 303 | | # 304 | | # 305 | | # 306 | | ## 307 | | ## 308 | |### 309 | +--------------------- 310 | ``` 311 | 312 | 313 | # Thanks 314 | 315 | Stole (with permission) some ideas and functions from [RxJS Easing](https://github.com/trxcllnt/rxjs-easing) by Paul Taylor. 316 | 317 | This project is a grateful recipient of the [Futurice Open Source sponsorship program](http://futurice.com/blog/sponsoring-free-time-open-source-activities?utm_source=github&utm_medium=spice&utm_campaign=rxtween). 318 | 319 | ## LICENSE 320 | 321 | [The MIT License (MIT)](https://github.com/staltz/cycle/blob/master/LICENSE) 322 | -------------------------------------------------------------------------------- /examples/back-easing.js: -------------------------------------------------------------------------------- 1 | let RxTween = require('../src/index'); 2 | 3 | let position$ = RxTween({ 4 | from: 0, 5 | to: 20, 6 | ease: RxTween.Back.easeInOut, 7 | duration: 1000, 8 | interval: 20 9 | }); 10 | 11 | position$.subscribe(function (x) { 12 | console.log(x); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/power4-ease-in-out.js: -------------------------------------------------------------------------------- 1 | let RxTween = require('../src/index'); 2 | 3 | let position$ = RxTween({ 4 | from: 0, 5 | to: 20, 6 | ease: RxTween.Power4.easeInOut, 7 | duration: 1000, 8 | interval: 20 9 | }); 10 | 11 | position$.subscribe(function (x) { 12 | console.log(x); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/simpleExp.js: -------------------------------------------------------------------------------- 1 | let RxTween = require('../src/index'); 2 | 3 | let position$ = RxTween({ 4 | from: 0, 5 | to: 20, 6 | ease: RxTween.Exp.easeIn, 7 | duration: 1000, 8 | interval: 20 9 | }); 10 | 11 | position$.subscribe(function (x) { 12 | console.log(x); 13 | }); 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rxtween", 3 | "version": "1.0.0", 4 | "description": "A library for creating animation-related RxJS Observables", 5 | "author": "Andre Staltz (http://andre.staltz.com/)", 6 | "license": "MIT", 7 | "keywords": [ 8 | "rx", 9 | "rxjs", 10 | "tween", 11 | "animation" 12 | ], 13 | "homepage": "https://github.com/staltz/rxtween", 14 | "bugs": "https://github.com/staltz/rxtween/issues", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/staltz/rxtween" 18 | }, 19 | "main": "lib/index.js", 20 | "peerDependencies": { 21 | "rx": "4.x.x" 22 | }, 23 | "devDependencies": { 24 | "babel": "^5.1.10", 25 | "eslint": "^0.20.0", 26 | "tape": "^4.0.0" 27 | }, 28 | "scripts": { 29 | "lint": "eslint src/", 30 | "precompile-lib": "rm -rf lib/ && mkdir -p lib", 31 | "compile-lib": "babel -d lib/ src/", 32 | "prepublish": "npm run compile-lib", 33 | "test": "babel-node --optional es7.objectRestSpread ./test/index.js", 34 | "release": "npm run release-patch", 35 | "release-patch": "npm version patch && git push origin master --tags && npm publish", 36 | "release-minor": "npm version minor && git push origin master --tags && npm publish", 37 | "release-major": "npm version major && git push origin master --tags && npm publish" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ease-back.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | const OVERSHOOT = 1.70158; 5 | 6 | export default { 7 | EasingBack: createEasing(x => x * x * ((OVERSHOOT + 1) * x - OVERSHOOT)) 8 | }; 9 | -------------------------------------------------------------------------------- /src/ease-bounce.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | const PARAM1 = 7.5625; 5 | const PARAM2 = 2.75; 6 | function easeOutFn(x) { 7 | let z = x; 8 | if (z < 1 / PARAM2) { 9 | return (PARAM1 * z * z); 10 | } else if (z < 2 / PARAM2) { 11 | return (PARAM1 * (z -= 1.5 / PARAM2) * z + 0.75); 12 | } else if (z < 2.5 / PARAM2) { 13 | return (PARAM1 * (z -= 2.25 / PARAM2) * z + 0.9375); 14 | } else { 15 | return (PARAM1 * (z -= 2.625 / PARAM2) * z + 0.984375); 16 | } 17 | } 18 | 19 | export default { 20 | EasingBounce: createEasing(x => 1 - easeOutFn(1 - x)) 21 | }; 22 | -------------------------------------------------------------------------------- /src/ease-circ.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | export default { 5 | EasingCirc: createEasing(x => -(Math.sqrt(1 - x * x) - 1)) 6 | }; 7 | -------------------------------------------------------------------------------- /src/ease-common.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function interpolate(y, from, to) { 4 | return (from * (1 - y) + to * y); 5 | } 6 | 7 | function flip(fn) { 8 | return x => 1 - fn(1 - x); 9 | } 10 | 11 | export default { 12 | interpolate, 13 | 14 | flip, 15 | 16 | createEasing(fn) { 17 | let fnFlipped = flip(fn); 18 | return { 19 | easeIn(x, from, to) { 20 | return interpolate(fn(x), from, to); 21 | }, 22 | easeOut(x, from, to) { 23 | return interpolate(fnFlipped(x), from, to); 24 | }, 25 | easeInOut(x, from, to) { 26 | const y = (x < 0.5) ? 27 | (fn(2 * x) * 0.5) : 28 | (0.5 + fnFlipped(2 * (x - 0.5)) * 0.5); 29 | return interpolate(y, from, to); 30 | } 31 | }; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /src/ease-elastic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | const PERIOD = 0.3; 5 | const OVERSHOOT = PERIOD / 4; 6 | const AMPLITUDE = 1; 7 | function elasticIn(x) { 8 | let z = x; 9 | if (z <= 0) { 10 | return 0; 11 | } else if (z >= 1) { 12 | return 1; 13 | } else { 14 | z -= 1; 15 | return -(AMPLITUDE * Math.pow(2, 10 * z)) 16 | * Math.sin((z - OVERSHOOT) * (2 * Math.PI) / PERIOD); 17 | } 18 | } 19 | 20 | export default { 21 | EasingElastic: createEasing(elasticIn) 22 | }; 23 | -------------------------------------------------------------------------------- /src/ease-exponential.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | const EXP_WEIGHT = 6; 5 | const EXP_MAX = Math.exp(EXP_WEIGHT) - 1; 6 | function expFn(x) { 7 | return (Math.exp(x * EXP_WEIGHT) - 1) / EXP_MAX; 8 | } 9 | 10 | let EasingExponential = createEasing(expFn); 11 | 12 | export default { 13 | EasingExponential 14 | }; 15 | -------------------------------------------------------------------------------- /src/ease-powers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | let EasingPower2 = createEasing(x => x * x); 5 | let EasingPower3 = createEasing(x => x * x * x); 6 | let EasingPower4 = createEasing(x => { 7 | const xx = x * x; 8 | return xx * xx; 9 | }); 10 | 11 | export default { 12 | EasingPower2, 13 | EasingPower3, 14 | EasingPower4 15 | }; 16 | -------------------------------------------------------------------------------- /src/ease-sine.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let {createEasing} = require('./ease-common'); 3 | 4 | const HALF_PI = Math.PI * 0.5; 5 | 6 | export default { 7 | EasingSine: createEasing(x => 1 - Math.cos(x * HALF_PI)) 8 | }; 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let Rx = require('rx'); 3 | let {interpolate} = require('./ease-common'); 4 | let {EasingPower2, EasingPower3, EasingPower4} = require('./ease-powers'); 5 | let {EasingExponential} = require('./ease-exponential'); 6 | let {EasingBack} = require('./ease-back'); 7 | let {EasingBounce} = require('./ease-bounce'); 8 | let {EasingCirc} = require('./ease-circ'); 9 | let {EasingElastic} = require('./ease-elastic'); 10 | let {EasingSine} = require('./ease-sine'); 11 | 12 | const DEFAULT_INTERVAL = 15; 13 | function sanitizeInterval(interval) { 14 | if (interval === 'auto') { 15 | return DEFAULT_INTERVAL; 16 | } else if (typeof interval !== 'number' || interval <= 0) { 17 | console.warn(`RxTween cannot use invalid given interval: ${interval}`); 18 | return DEFAULT_INTERVAL; 19 | } 20 | return interval; 21 | } 22 | 23 | function RxTween({ 24 | from, 25 | to, 26 | duration, 27 | ease = RxTween.Linear.ease, 28 | interval = 'auto' 29 | }) { 30 | let sanitizedInterval = sanitizeInterval(interval); 31 | const totalTicks = Math.round(duration / sanitizedInterval); 32 | return Rx.Observable.interval(sanitizedInterval) 33 | .take(totalTicks) 34 | .map(tick => ease(tick / totalTicks, from, to)) 35 | .concat(Rx.Observable.just(to)); 36 | } 37 | 38 | RxTween.Linear = {ease: interpolate}; 39 | RxTween.Power2 = EasingPower2; 40 | RxTween.Power3 = EasingPower3; 41 | RxTween.Power4 = EasingPower4; 42 | RxTween.Exp = EasingExponential; 43 | RxTween.Back = EasingBack; 44 | RxTween.Bounce = EasingBounce; 45 | RxTween.Circ = EasingCirc; 46 | RxTween.Elastic = EasingElastic; 47 | RxTween.Sine = EasingSine; 48 | 49 | export default RxTween; 50 | -------------------------------------------------------------------------------- /test/easings.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import RxTween from '../src/index'; 3 | import {plot, plotTweenConfigs, makeAssertPlot} from './plot-utils'; 4 | 5 | 6 | test("RxTween.Linear.ease", function (assert) { 7 | let position$ = RxTween({ease: RxTween.Linear.ease, ...plotTweenConfigs}); 8 | plot(position$).subscribe(makeAssertPlot(assert, ` 9 | | # 10 | | # 11 | | # 12 | | # 13 | | # 14 | | # 15 | | # 16 | | # 17 | | # 18 | | # 19 | | # 20 | | # 21 | | # 22 | | # 23 | | # 24 | | # 25 | | # 26 | | # 27 | | # 28 | | # 29 | |# 30 | +---------------------`)); 31 | }); 32 | 33 | 34 | test("RxTween.Power2.easeIn", function (assert) { 35 | let position$ = RxTween({ease: RxTween.Power2.easeIn, ...plotTweenConfigs}); 36 | plot(position$).subscribe(makeAssertPlot(assert, ` 37 | | # 38 | | 39 | | # 40 | | 41 | | # 42 | | 43 | | # 44 | | # 45 | | 46 | | # 47 | | # 48 | | 49 | | # 50 | | # 51 | | # 52 | | # 53 | | # 54 | | # 55 | | ## 56 | | ## 57 | |#### 58 | +---------------------`)); 59 | }); 60 | 61 | test("RxTween.Power3.easeIn", function (assert) { 62 | let position$ = RxTween({ease: RxTween.Power3.easeIn, ...plotTweenConfigs}); 63 | plot(position$).subscribe(makeAssertPlot(assert, ` 64 | | # 65 | | 66 | | 67 | | # 68 | | 69 | | # 70 | | 71 | | 72 | | # 73 | | 74 | | # 75 | | 76 | | # 77 | | # 78 | | 79 | | # 80 | | # 81 | | ## 82 | | # 83 | | ### 84 | |###### 85 | +---------------------`)); 86 | }); 87 | 88 | test("RxTween.Power4.easeIn", function (assert) { 89 | let position$ = RxTween({ease: RxTween.Power4.easeIn, ...plotTweenConfigs}); 90 | plot(position$).subscribe(makeAssertPlot(assert, ` 91 | | # 92 | | 93 | | 94 | | 95 | | # 96 | | 97 | | 98 | | # 99 | | 100 | | 101 | | # 102 | | 103 | | # 104 | | 105 | | # 106 | | # 107 | | # 108 | | # 109 | | # 110 | | ### 111 | |######## 112 | +---------------------`)); 113 | }); 114 | 115 | test("RxTween.Exp.easeIn", function (assert) { 116 | let position$ = RxTween({ease: RxTween.Exp.easeIn, ...plotTweenConfigs}); 117 | plot(position$).subscribe(makeAssertPlot(assert, ` 118 | | # 119 | | 120 | | 121 | | 122 | | 123 | | # 124 | | 125 | | 126 | | 127 | | # 128 | | 129 | | 130 | | # 131 | | 132 | | # 133 | | 134 | | # 135 | | # 136 | | ## 137 | | ### 138 | |######### 139 | +---------------------`)); 140 | }); 141 | 142 | test("RxTween.Back.easeIn", function (assert) { 143 | let position$ = RxTween({ease: RxTween.Back.easeIn, ...plotTweenConfigs}); 144 | plot(position$).subscribe(makeAssertPlot(assert, ` 145 | | # 146 | | 147 | | 148 | | 149 | | # 150 | | 151 | | 152 | | 153 | | # 154 | | 155 | | 156 | | # 157 | | 158 | | 159 | | # 160 | | 161 | | # 162 | | 163 | | # 164 | | 165 | |#____________# 166 | +---------------------`)); 167 | }); 168 | 169 | test("RxTween.Bounce.easeIn", function (assert) { 170 | let position$ = RxTween({ease: RxTween.Bounce.easeIn, ...plotTweenConfigs}); 171 | plot(position$).subscribe(makeAssertPlot(assert, ` 172 | | ## 173 | | 174 | | # 175 | | # 176 | | 177 | | 178 | | # 179 | | 180 | | 181 | | # 182 | | 183 | | 184 | | 185 | | 186 | | # 187 | | ### 188 | | # 189 | | # 190 | | # 191 | | #### # 192 | |### 193 | +---------------------`)); 194 | }); 195 | 196 | test("RxTween.Circ.easeIn", function (assert) { 197 | let position$ = RxTween({ease: RxTween.Circ.easeIn, ...plotTweenConfigs}); 198 | plot(position$).subscribe(makeAssertPlot(assert, ` 199 | | # 200 | | 201 | | 202 | | 203 | | 204 | | 205 | | # 206 | | 207 | | 208 | | # 209 | | 210 | | # 211 | | # 212 | | # 213 | | # 214 | | # 215 | | # 216 | | ## 217 | | ## 218 | | ### 219 | |##### 220 | +---------------------`)); 221 | }); 222 | 223 | test("RxTween.Elastic.easeIn", function (assert) { 224 | let position$ = RxTween({ease: RxTween.Elastic.easeIn, ...plotTweenConfigs}); 225 | plot(position$).subscribe(makeAssertPlot(assert, ` 226 | | # 227 | | 228 | | 229 | | 230 | | 231 | | 232 | | 233 | | 234 | | 235 | | 236 | | 237 | | 238 | | 239 | | # 240 | | 241 | | 242 | | 243 | | 244 | | ## 245 | | # 246 | |####___###___ ___ 247 | +---------------------`)); 248 | }); 249 | 250 | test("RxTween.Sine.easeIn", function (assert) { 251 | let position$ = RxTween({ease: RxTween.Sine.easeIn, ...plotTweenConfigs}); 252 | plot(position$).subscribe(makeAssertPlot(assert, ` 253 | | # 254 | | 255 | | # 256 | | # 257 | | 258 | | # 259 | | # 260 | | 261 | | # 262 | | # 263 | | # 264 | | 265 | | # 266 | | # 267 | | # 268 | | # 269 | | # 270 | | # 271 | | ## 272 | | ## 273 | |### 274 | +---------------------`)); 275 | }); 276 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('./main.js'); 2 | require('./easings.js'); 3 | -------------------------------------------------------------------------------- /test/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/staltz/rxtween/60e0840013352b69924e94e917e0f03b3cdab6de/test/main.js -------------------------------------------------------------------------------- /test/plot-utils.js: -------------------------------------------------------------------------------- 1 | 2 | const STEPS = 20; 3 | const DURATION = 1000; 4 | 5 | const plotTweenConfigs = { 6 | from: 0, 7 | to: STEPS, 8 | duration: DURATION, 9 | interval: DURATION / STEPS 10 | }; 11 | 12 | function setCharAt(str, idx, chr) { 13 | if (idx > str.length - 1){ 14 | return str.toString(); 15 | } else { 16 | return str.substr(0, idx) + chr + str.substr(idx + 1); 17 | } 18 | } 19 | 20 | function rotate(lines) { 21 | let len = lines[0].length; 22 | return lines[0].split('') 23 | .map((col, i) => 24 | lines 25 | .map(row => row.split('')[len-i-1]) 26 | ) 27 | .map(row => row.join('')); 28 | } 29 | 30 | function stutter(char, length) { 31 | return new Array(length + 1).join(char); 32 | } 33 | 34 | function plot(position$) { 35 | return position$ 36 | .reduce((acc, curr) => { 37 | acc.push(curr); 38 | return acc; 39 | }, []) 40 | .map(arr => { 41 | let coords = arr.map((y, x) => [x, y]); 42 | let lines = coords.reduce((lines, [x, y]) => { 43 | let newline; 44 | if (y < 0) { 45 | newline = setCharAt(stutter(' ', STEPS + 1), 0, '_'); 46 | } else { 47 | newline = setCharAt(stutter(' ', STEPS + 1), Math.round(y), '#'); 48 | } 49 | lines.push(newline); 50 | return lines; 51 | }, []); 52 | return rotate(lines) 53 | .map(line => '|'.concat(line).concat('\n')) 54 | .reduce((lines, line) => lines.concat(line), '') 55 | .concat('+' + stutter('-', STEPS + 1)); 56 | }); 57 | } 58 | 59 | function makeAssertPlot(assert, expected) { 60 | return function assertPlot(actual) { 61 | console.log(actual); 62 | assert.equal(`\n${actual}`, expected); 63 | assert.end(); 64 | }; 65 | } 66 | 67 | module.exports = { 68 | plotTweenConfigs, 69 | plot, 70 | makeAssertPlot, 71 | } 72 | --------------------------------------------------------------------------------