├── .editorconfig ├── .gitignore ├── .prettierrc ├── .eslintignore ├── .travis.yml ├── .vscode └── settings.json ├── .npmignore ├── rollup.config.js ├── .babelrc ├── .eslintrc.json ├── src ├── shim.js ├── index.js ├── selector.js ├── NodeCache.js ├── Interpolator.js ├── PlaybackPosition.js ├── Easing.js ├── Interpolation.js ├── core.js ├── Timeline.js ├── constants.js └── Tween.js ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ ├── regular-issue.md │ └── bug_report.md └── FUNDING.yml ├── jsdoc.json ├── withPage.js ├── LICENSE ├── examples ├── basic.html └── test.html ├── CONTRIBUTING.md ├── performance ├── gsap.html ├── kute.html ├── es6-tween.html └── kute.js ├── logo ├── box.svg └── es6-logo.svg ├── package.json ├── CODE_OF_CONDUCT.md ├── README.md ├── test.js └── API.md /.editorconfig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | docs/ 3 | full/ 4 | bundled/ 5 | lite/ 6 | guide_notes/ 7 | node_modules/ 8 | npm-debug.log 9 | yarn-error.log 10 | .vscode 11 | .idea 12 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 120, 4 | "trailingComma": "es5", 5 | "arrowParens": "always", 6 | "bracketSpacing": true 7 | } 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # /node_modules/* and /bower_components/* in the project root are ignored by default 2 | 3 | # Ignore 4 | .github/* 5 | bundled/* 6 | examples/* 7 | performance/* 8 | logo/* 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - node_modules 5 | notifications: 6 | email: false 7 | node_js: 8 | - '12' 9 | before_script: 10 | - npm prune 11 | script: 12 | - npm test 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": true, 3 | "eslint.autoFixOnSave": true, 4 | "eslint.packageManager": "npm", 5 | "prettier.requireConfig": true, 6 | "editor.codeActionsOnSave": { 7 | "source.fixAll.eslint": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .git 3 | .github 4 | bower.json 5 | tsconfig.json 6 | tslint.json 7 | assets 8 | docs 9 | examples 10 | logo 11 | performance 12 | guide_notes 13 | CONTRIBUTING.md 14 | ISSUE_TEMPLATE.md 15 | API.md 16 | .travis.yml 17 | yarn-error.log 18 | .vscode 19 | .idea 20 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel' 2 | 3 | export default { 4 | input: 'src/index.js', 5 | output: { 6 | format: 'umd', 7 | file: 'bundled/Tween.js', 8 | name: 'TWEEN', 9 | sourcemap: true 10 | }, 11 | context: 'this', 12 | plugins: [babel()] 13 | } 14 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["node_modules/**", "bundled/**", "performance/**", "logo/**", "examples/**"], 3 | "presets": [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | "modules": false, 8 | "shippedProposals": true 9 | } 10 | ] 11 | ], 12 | "plugins": ["@babel/plugin-proposal-class-properties"] 13 | } 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": "standard", 8 | "globals": { 9 | "Atomics": "readonly", 10 | "SharedArrayBuffer": "readonly" 11 | }, 12 | "parserOptions": { 13 | "ecmaVersion": 2018, 14 | "sourceType": "module" 15 | }, 16 | "rules": {} 17 | } 18 | -------------------------------------------------------------------------------- /src/shim.js: -------------------------------------------------------------------------------- 1 | /* global global, self */ 2 | export let root = 3 | typeof self !== 'undefined' 4 | ? self 5 | : typeof window !== 'undefined' 6 | ? window 7 | : typeof global !== 'undefined' 8 | ? global 9 | : this || (typeof exports !== 'undefined' ? exports : {}) 10 | export let requestAnimationFrame = root.requestAnimationFrame || ((fn) => root.setTimeout(fn, 50 / 3)) 11 | export let cancelAnimationFrame = root.cancelAnimationFrame || ((id) => root.clearTimeout(id)) 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: dalisoft 4 | patreon: dalisoft # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # dalisoft # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # ['https://www.buymeacoffee.com/dalisoft', 'https://paypal.me/dalisoft'] 13 | -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true, 4 | "dictionaries": [ 5 | "jsdoc" 6 | ] 7 | }, 8 | "source": { 9 | "include": [ 10 | "src" 11 | ], 12 | "includePattern": ".js$", 13 | "excludePattern": "(node_modules/|logo|docs|bundled|examples|performance|.vscode|.github)" 14 | }, 15 | "plugins": [ 16 | "plugins/markdown" 17 | ], 18 | "templates": { 19 | "cleverLinks": false, 20 | "monospaceLinks": true 21 | }, 22 | "opts": { 23 | "destination": "../es6-tween-gh/docs/", 24 | "encoding": "utf8", 25 | "private": true, 26 | "recurse": true, 27 | "template": "./node_modules/docdash" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/regular-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Regular issue 3 | about: For regular issue 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | |Issue name|Issue description|Issue Demo URL 11 | |---|---|---| 12 | | | | | 13 | 14 | ### Related 15 | This issue is related to 16 | 17 | - [ ] README 18 | - [ ] package.json 19 | - [ ] Demos 20 | - [ ] Core features/functionality 21 | - [ ] Tween class 22 | - [ ] Easing 23 | - [ ] Interpolation 24 | - [ ] Timeline class 25 | - [ ] LICENSE 26 | - [ ] ABOUT COPYRIGHT VIOLATION (be careful before checking this...!) 27 | 28 | - or provide something else (from es6-tween files...) 29 | 30 | ### What you excepted? 31 | - Describe your result of research or idea... 32 | 33 | ### NOTE 34 | - Please add read code, docs, files, issues, PR list for avoid duplicating existing question, bug or something else... 35 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | add, 3 | onTick, 4 | autoPlay, 5 | get, 6 | getAll, 7 | has, 8 | isRunning, 9 | now, 10 | onRequestTick, 11 | FrameThrottle, 12 | ToggleLagSmoothing, 13 | Plugins, 14 | remove, 15 | removeAll, 16 | update 17 | } from './core' 18 | import Easing from './Easing' 19 | import Interpolation from './Interpolation' 20 | import Tween from './Tween' 21 | import Timeline from './Timeline' 22 | import Selector from './selector' 23 | import Interpolator from './Interpolator' 24 | import * as utils from './constants' 25 | import './shim' 26 | export { 27 | Plugins, 28 | Selector, 29 | Interpolator, 30 | onTick, 31 | has, 32 | get, 33 | getAll, 34 | removeAll, 35 | remove, 36 | add, 37 | now, 38 | update, 39 | autoPlay, 40 | isRunning, 41 | onRequestTick, 42 | FrameThrottle, 43 | ToggleLagSmoothing, 44 | Tween, 45 | Timeline, 46 | Easing, 47 | Interpolation, 48 | utils 49 | } 50 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /src/selector.js: -------------------------------------------------------------------------------- 1 | export default function (selector, collection, allowRaw) { 2 | if (!selector) { 3 | return null 4 | } 5 | 6 | const isGlobalScope = 7 | (typeof window !== 'undefined' && selector === window) || 8 | (typeof document !== 'undefined' && selector === document) 9 | 10 | if (collection) { 11 | return isGlobalScope 12 | ? [selector] 13 | : typeof selector === 'string' 14 | ? !!document.querySelectorAll && document.querySelectorAll(selector) 15 | : Array.isArray(selector) 16 | ? selector 17 | : selector.nodeType 18 | ? [selector] 19 | : allowRaw 20 | ? selector 21 | : [] 22 | } 23 | return isGlobalScope 24 | ? selector 25 | : typeof selector === 'string' 26 | ? !!document.querySelector && document.querySelector(selector) 27 | : Array.isArray(selector) 28 | ? selector[0] 29 | : selector.nodeType 30 | ? selector 31 | : allowRaw 32 | ? selector 33 | : null 34 | } 35 | -------------------------------------------------------------------------------- /withPage.js: -------------------------------------------------------------------------------- 1 | import puppeteer from 'puppeteer' 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | 6 | // Parse 7 | function describe (jsHandle) { 8 | return jsHandle.executionContext().evaluate((obj) => { 9 | // serialize |obj| however you want 10 | return JSON.stringify(obj) 11 | }, jsHandle) 12 | } 13 | 14 | export default (t, run) => { 15 | let _browser 16 | return puppeteer 17 | .launch({ headless: true, args: ['--no-sandbox'] }) 18 | .then((browser) => { 19 | _browser = browser 20 | return browser 21 | .newPage() 22 | .then((page) => { 23 | page.on('console', async (msg) => { 24 | const args = await Promise.all(msg.args().map((arg) => describe(arg))) 25 | console.log('Logs from Headless Chrome', ...args) 26 | }) 27 | return page.evaluate(fs.readFileSync(path.join(__dirname, 'bundled/Tween.js'), 'utf8')).then(() => page) 28 | }) 29 | .then((page) => run(t, page).then(() => page)) 30 | }) 31 | .then((page) => { 32 | _browser.close() 33 | page.close() 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 tween.js and es6-tween contributors 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 | -------------------------------------------------------------------------------- /src/NodeCache.js: -------------------------------------------------------------------------------- 1 | import { remove } from './core' 2 | 3 | export const Store = {} 4 | export default function (node, object, tween) { 5 | if (!node || !node.nodeType) { 6 | return object 7 | } 8 | const ID = node.queueID || 'q_' + Date.now() 9 | if (!node.queueID) { 10 | node.queueID = ID 11 | } 12 | const storeID = Store[ID] 13 | if (storeID) { 14 | if (storeID.object === object && node === storeID.tween.node && tween._startTime === storeID.tween._startTime) { 15 | remove(storeID.tween) 16 | } else if (typeof object === 'object' && !!object && !!storeID.object) { 17 | for (let prop in object) { 18 | if (prop in storeID.object) { 19 | if (tween._startTime === storeID.tween._startTime) { 20 | delete storeID.object[prop] 21 | } else { 22 | storeID.propNormaliseRequired = true 23 | } 24 | } 25 | } 26 | Object.assign(storeID.object, object) 27 | } 28 | return storeID.object 29 | } 30 | 31 | if (typeof object === 'object' && !!object) { 32 | Store[ID] = { 33 | tween, 34 | object, 35 | propNormaliseRequired: false 36 | } 37 | return Store[ID].object 38 | } 39 | 40 | return object 41 | } 42 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
](https://www.browserstack.com/)
151 |
152 | ## Tests
153 |
154 | ```bash
155 | yarn test
156 | ```
157 |
158 | or you can go [here](https://travis-ci.org/tweenjs/es6-tween) for more information, tests and etc...
159 |
160 | every time you want to run the tests.
161 |
162 | If you want to add any feature or change existing features, you _must_ run the tests to make sure you didn't break anything else. If you send a PR to add something new and it doesn't have tests, or the tests don't pass, the PR won't be accepted. See [contributing](CONTRIBUTING.md) for more information.
163 |
164 | ## People
165 |
166 | - [All contributors](https://github.com/tweenjs/es6-tween/contributors).
167 | - [es6-tween contributors](https://github.com/tweenjs/es6-tween/graphs/contributors)/
168 |
169 | ## Thanks to
170 |
171 | these tools developers and to their community and without these tools maybe this library wouldn't be possible
172 |
173 | - [GitHub](https://github.com/)
174 | - [Travis CI](http://travis-ci.org)
175 | - [BrowserStack](https://www.browserstack.com/)
176 | - [Node.js](https://nodejs.org/en/)
177 | - [ESLint](http://eslint.org)
178 | - [jsDoc](http://usejsdoc.org) ([docdash theme](https://github.com/clenemt/docdash))
179 | - [Rollup](https://rollupjs.org/guide/en)
180 | - [Babel](https://babeljs.io)
181 | - [Ava](https://github.com/avajs/ava)
182 | - [Puppeteer](https://pptr.dev)
183 | - [UglifyJS v3](https://github.com/mishoo/UglifyJS2)
184 | - [Husky](https://github.com/typicode/husky)
185 |
186 | ## Projects using es6-tween
187 |
188 | - [ft](https://github.com/2players/ft)
189 | - [react-heartwood-components](https://www.npmjs.com/package/@sprucelabs/react-heartwood-components)
190 | - [el-controls](https://github.com/eljs/el-controls)
191 | - [lightweight-pixijs-engine](https://github.com/dgzornoza/lightweight-pixijs-engine#readme)
192 | - [vue-sliderx](https://www.npmjs.com/package/vue-sliderx)
193 | - [vue-mapbox-feature](https://cityseer.github.io/vue-mapbox-feature)
194 | - [vuxtras](https://github.com/homerjam/vuxtras#readme)
195 | - [Slye](https://github.com/Slye3D/slye#readme)
196 | - [react-3d-globe](https://chrisrzhou.github.io/react-3d-globe/)
197 |
198 | It's great to see this library to be used in production and/or library, thank you!
199 |
200 | If you have projects using es6-tween, please make issue or PR, i will add here your project too :)
201 |
202 | [npm-min-size]: https://img.shields.io/bundlephobia/min/es6-tween.svg
203 | [npm-gzip-size]: https://img.badgesize.io/https://unpkg.com/es6-tween?compression=gzip
204 | [npm-image]: https://img.shields.io/npm/v/es6-tween.svg
205 | [npm-url]: https://npmjs.org/package/es6-tween
206 | [downloads-image]: https://img.shields.io/npm/dm/es6-tween.svg
207 | [travis-image]: https://travis-ci.org/tweenjs/es6-tween.svg?branch=master
208 | [travis-url]: https://travis-ci.org/tweenjs/es6-tween
209 | [cdnjs-image]: https://img.shields.io/cdnjs/v/es6-tween.svg
210 | [cdnjs-url]: https://cdnjs.com/libraries/es6-tween
211 | [unpkg-url]: https://unpkg.com/es6-tween
212 |
--------------------------------------------------------------------------------
/src/Timeline.js:
--------------------------------------------------------------------------------
1 | import { add, now, remove, isRunning, isLagSmoothing } from './core'
2 | import PlaybackPosition from './PlaybackPosition'
3 | import Tween from './Tween'
4 | import {
5 | EVENT_START,
6 | EVENT_COMPLETE,
7 | EVENT_REPEAT,
8 | EVENT_REVERSE,
9 | EVENT_RESTART,
10 | EVENT_UPDATE,
11 | FRAME_MS,
12 | TOO_LONG_FRAME_MS
13 | } from './constants'
14 | import Selector from './selector'
15 |
16 | export const shuffle = (a) => {
17 | let j
18 | let x
19 | let i
20 | for (i = a.length; i; i -= 1) {
21 | j = Math.floor(Math.random() * i)
22 | x = a[i - 1]
23 | a[i - 1] = a[j]
24 | a[j] = x
25 | }
26 | return a
27 | }
28 |
29 | let _id = 0
30 | /**
31 | * Timeline main constructor.
32 | *
33 | * It works same as `Tween` instance, using `.repeat`, `.restart` or `etc` works like a `Tween`, so please see `Tween` class for methods
34 | * @constructor
35 | * @class
36 | * @namespace TWEEN.Timeline
37 | * @param {Object=} params Default params for new tweens
38 | * @example let tl = new Timeline({delay:200})
39 | * @extends Tween
40 | */
41 | class Timeline extends Tween {
42 | constructor (params) {
43 | super()
44 | this._duration = 0
45 | this._startTime = params && params.startTime !== undefined ? params.startTime : now()
46 | this._tweens = []
47 | this.elapsed = 0
48 | this._id = _id++
49 | this._defaultParams = params
50 | this.position = new PlaybackPosition()
51 | this.position.addLabel('afterLast', this._duration)
52 | this.position.addLabel('afterInit', this._startTime)
53 | this._onStartCallbackFired = false
54 |
55 | return this
56 | }
57 | mapTotal (fn) {
58 | fn.call(this, this._tweens)
59 | return this
60 | }
61 | timingOrder (fn) {
62 | const timing = fn(this._tweens.map((t) => t._startTime))
63 | this._tweens.map((tween, i) => {
64 | tween._startTime = timing[i]
65 | })
66 | return this
67 | }
68 | getTiming (mode, nodes, params, offset = 0) {
69 | if (mode === 'reverse') {
70 | const { stagger } = params
71 | const totalStagger = (stagger || 0) * (nodes.length - 1)
72 | return nodes.map((node, i) => totalStagger - (stagger || 0) * i + offset)
73 | } else if (mode === 'async') {
74 | return nodes.map((node) => offset)
75 | } else if (mode === 'sequence' || mode === 'delayed') {
76 | let { stagger } = params
77 | if (!stagger) {
78 | stagger = (params.duration || 1000) / (nodes.length - 1)
79 | }
80 | return nodes.map((node, i) => stagger * i + offset)
81 | } else if (mode === 'oneByOne') {
82 | return nodes.map((node) => params.duration)
83 | } else if (mode === 'shuffle') {
84 | const { stagger } = params
85 | return shuffle(nodes.map((node, i) => (stagger || 0) * i + offset))
86 | } else {
87 | const { stagger } = params
88 | return nodes.map((node, i) => (stagger || 0) * i + offset)
89 | }
90 | }
91 |
92 | /**
93 | * @param {Arrayobject
4 | Lightweight, effecient and modular ES6 version of tween.js
5 |
6 | **Kind**: global namespace
7 | **License**: MIT
8 | **Copyright**: 2019 @dalisoft and es6-tween contributors
9 | **Example**
10 | ```js
11 | // ES6
12 | const {add, remove, isRunning, autoPlay} = TWEEN
13 | ```
14 |
15 | * [TWEEN](#TWEEN) : object
16 | * [.Easing](#TWEEN.Easing) : object
17 | * [.Interpolation](#TWEEN.Interpolation) : object
18 | * [.Interpolator](#TWEEN.Interpolator) ⇒ function
19 | * [.Timeline](#TWEEN.Timeline) : object
20 | * [.Tween](#TWEEN.Tween) : object
21 | * [.Tween#setMaxListener(count)](#TWEEN.Tween.Tween+setMaxListener)
22 | * [.Tween#on(event, callback)](#TWEEN.Tween.Tween+on)
23 | * [.Tween#once(event, callback)](#TWEEN.Tween.Tween+once)
24 | * [.Tween#off(event, callback)](#TWEEN.Tween.Tween+off)
25 | * [.Tween#emit(event)](#TWEEN.Tween.Tween+emit)
26 | * [.Tween#isPlaying()](#TWEEN.Tween.Tween+isPlaying) ⇒ boolean
27 | * [.Tween#isStarted()](#TWEEN.Tween.Tween+isStarted) ⇒ boolean
28 | * [.Tween#reverse([state])](#TWEEN.Tween.Tween+reverse)
29 | * [.Tween#reversed()](#TWEEN.Tween.Tween+reversed) ⇒ boolean
30 | * [.Tween#pause()](#TWEEN.Tween.Tween+pause)
31 | * [.Tween#play()](#TWEEN.Tween.Tween+play)
32 | * [.Tween#restart([noDelay])](#TWEEN.Tween.Tween+restart)
33 | * ~~[.Tween#seek(time, [keepPlaying])](#TWEEN.Tween.Tween+seek)~~
34 | * ~~[.Tween#duration(amount)](#TWEEN.Tween.Tween+duration)~~
35 | * [.Tween#to(properties, [duration])](#TWEEN.Tween.Tween+to)
36 | * [.Tween#start(time)](#TWEEN.Tween.Tween+start)
37 | * [.Tween#stop()](#TWEEN.Tween.Tween+stop)
38 | * [.Tween#delay(amount)](#TWEEN.Tween.Tween+delay)
39 | * [.Tween#chainedTweens(arguments)](#TWEEN.Tween.Tween+chainedTweens)
40 | * [.Tween#repeat(amount)](#TWEEN.Tween.Tween+repeat)
41 | * [.Tween#reverseDelay(amount)](#TWEEN.Tween.Tween+reverseDelay)
42 | * [.Tween#yoyo(state, [_easingReverse])](#TWEEN.Tween.Tween+yoyo)
43 | * [.Tween#easing(_easingFunction)](#TWEEN.Tween.Tween+easing)
44 | * [.Tween#interpolation(_interpolationFunction)](#TWEEN.Tween.Tween+interpolation)
45 | * [.Tween#update(time, [preserve], [forceTime])](#TWEEN.Tween.Tween+update)
46 | * [.Plugins](#TWEEN.Plugins) : object
47 | * [.now](#TWEEN.now) ⇒
48 | * [.add(tween)](#TWEEN.add)
49 | * [.onTick(fn)](#TWEEN.onTick)
50 | * [.FrameThrottle(frameCount)](#TWEEN.FrameThrottle)
51 | * [.ToggleLagSmoothing(state)](#TWEEN.ToggleLagSmoothing)
52 | * [.autoPlay(state)](#TWEEN.autoPlay)
53 | * [.removeAll()](#TWEEN.removeAll)
54 | * [.get(tween)](#TWEEN.get) ⇒ Tween
55 | * [.has(tween)](#TWEEN.has) ⇒ Boolean
56 | * [.remove(tween)](#TWEEN.remove)
57 | * [.update([time], [preserve])](#TWEEN.update)
58 | * [.isRunning()](#TWEEN.isRunning) ⇒ Boolean
59 | * [.isLagSmoothing()](#TWEEN.isLagSmoothing) ⇒ Boolean
60 |
61 |
62 |
63 | ### TWEEN.Easing : object
64 | List of full easings
65 |
66 | **Kind**: static namespace of [TWEEN](#TWEEN)
67 | **Example**
68 | ```js
69 | import {Tween, Easing} from 'es6-tween'
70 |
71 | // then set via new Tween({x:0}).to({x:100}, 1000).easing(Easing.Quadratic.InOut).start()
72 | ```
73 |
74 |
75 | ### TWEEN.Interpolation : object
76 | List of full Interpolation
77 |
78 | **Kind**: static namespace of [TWEEN](#TWEEN)
79 | **Example**
80 | ```js
81 | import {Interpolation, Tween} from 'es6-tween'
82 |
83 | let bezier = Interpolation.Bezier
84 | new Tween({x:0}).to({x:[0, 4, 8, 12, 15, 20, 30, 40, 20, 40, 10, 50]}, 1000).interpolation(bezier).start()
85 | ```
86 |
87 |
88 | ### TWEEN.Interpolator ⇒ function
89 | Tween helper for plugins
90 |
91 | **Kind**: static namespace of [TWEEN](#TWEEN)
92 | **Returns**: function - Returns function that accepts number between `0-1`
93 |
94 | | Param | Type | Description |
95 | | --- | --- | --- |
96 | | a | any | Initial position |
97 | | b | any | End position |
98 |
99 |
100 |
101 | ### TWEEN.Timeline : object
102 | Timeline main constructor.
103 |
104 | It works same as `Tween` instance, using `.repeat`, `.restart` or `etc` works like a `Tween`, so please see `Tween` class for methods
105 |
106 | **Kind**: static namespace of [TWEEN](#TWEEN)
107 | **Extends**: Tween
108 |
109 | | Param | Type | Description |
110 | | --- | --- | --- |
111 | | [params] | Object | Default params for new tweens |
112 |
113 | **Example**
114 | ```js
115 | let tl = new Timeline({delay:200})
116 | ```
117 |
118 |
119 | ### TWEEN.Tween : object
120 | Tween main constructor
121 |
122 | **Kind**: static namespace of [TWEEN](#TWEEN)
123 |
124 | | Param | Type | Description |
125 | | --- | --- | --- |
126 | | node | Object \| Element | Node Element or Tween initial object |
127 | | [object] | Object | If Node Element is using, second argument is used for Tween initial object |
128 |
129 | **Example**
130 | ```js
131 | let tween = new Tween(myNode, {width:'100px'}).to({width:'300px'}, 2000).start()
132 | ```
133 |
134 | * [.Tween](#TWEEN.Tween) : object
135 | * [.Tween#setMaxListener(count)](#TWEEN.Tween.Tween+setMaxListener)
136 | * [.Tween#on(event, callback)](#TWEEN.Tween.Tween+on)
137 | * [.Tween#once(event, callback)](#TWEEN.Tween.Tween+once)
138 | * [.Tween#off(event, callback)](#TWEEN.Tween.Tween+off)
139 | * [.Tween#emit(event)](#TWEEN.Tween.Tween+emit)
140 | * [.Tween#isPlaying()](#TWEEN.Tween.Tween+isPlaying) ⇒ boolean
141 | * [.Tween#isStarted()](#TWEEN.Tween.Tween+isStarted) ⇒ boolean
142 | * [.Tween#reverse([state])](#TWEEN.Tween.Tween+reverse)
143 | * [.Tween#reversed()](#TWEEN.Tween.Tween+reversed) ⇒ boolean
144 | * [.Tween#pause()](#TWEEN.Tween.Tween+pause)
145 | * [.Tween#play()](#TWEEN.Tween.Tween+play)
146 | * [.Tween#restart([noDelay])](#TWEEN.Tween.Tween+restart)
147 | * ~~[.Tween#seek(time, [keepPlaying])](#TWEEN.Tween.Tween+seek)~~
148 | * ~~[.Tween#duration(amount)](#TWEEN.Tween.Tween+duration)~~
149 | * [.Tween#to(properties, [duration])](#TWEEN.Tween.Tween+to)
150 | * [.Tween#start(time)](#TWEEN.Tween.Tween+start)
151 | * [.Tween#stop()](#TWEEN.Tween.Tween+stop)
152 | * [.Tween#delay(amount)](#TWEEN.Tween.Tween+delay)
153 | * [.Tween#chainedTweens(arguments)](#TWEEN.Tween.Tween+chainedTweens)
154 | * [.Tween#repeat(amount)](#TWEEN.Tween.Tween+repeat)
155 | * [.Tween#reverseDelay(amount)](#TWEEN.Tween.Tween+reverseDelay)
156 | * [.Tween#yoyo(state, [_easingReverse])](#TWEEN.Tween.Tween+yoyo)
157 | * [.Tween#easing(_easingFunction)](#TWEEN.Tween.Tween+easing)
158 | * [.Tween#interpolation(_interpolationFunction)](#TWEEN.Tween.Tween+interpolation)
159 | * [.Tween#update(time, [preserve], [forceTime])](#TWEEN.Tween.Tween+update)
160 |
161 |
162 |
163 | #### Tween.Tween#setMaxListener(count)
164 | Sets max `event` listener's count to Events system
165 |
166 | **Kind**: static method of [Tween](#TWEEN.Tween)
167 |
168 | | Param | Type | Default | Description |
169 | | --- | --- | --- | --- |
170 | | count | number | 15 | Event listener's count |
171 |
172 |
173 |
174 | #### Tween.Tween#on(event, callback)
175 | Adds `event` to Events system
176 |
177 | **Kind**: static method of [Tween](#TWEEN.Tween)
178 |
179 | | Param | Type | Description |
180 | | --- | --- | --- |
181 | | event | string | Event listener name |
182 | | callback | function | Event listener callback |
183 |
184 |
185 |
186 | #### Tween.Tween#once(event, callback)
187 | Adds `event` to Events system.
188 | Removes itself after fired once
189 |
190 | **Kind**: static method of [Tween](#TWEEN.Tween)
191 |
192 | | Param | Type | Description |
193 | | --- | --- | --- |
194 | | event | string | Event listener name |
195 | | callback | function | Event listener callback |
196 |
197 |
198 |
199 | #### Tween.Tween#off(event, callback)
200 | Removes `event` from Events system
201 |
202 | **Kind**: static method of [Tween](#TWEEN.Tween)
203 |
204 | | Param | Type | Description |
205 | | --- | --- | --- |
206 | | event | string | Event listener name |
207 | | callback | function | Event listener callback |
208 |
209 |
210 |
211 | #### Tween.Tween#emit(event)
212 | Emits/Fired/Trigger `event` from Events system listeners
213 |
214 | **Kind**: static method of [Tween](#TWEEN.Tween)
215 |
216 | | Param | Type | Description |
217 | | --- | --- | --- |
218 | | event | string | Event listener name |
219 |
220 |
221 |
222 | #### Tween.Tween#isPlaying() ⇒ boolean
223 | **Kind**: static method of [Tween](#TWEEN.Tween)
224 | **Returns**: boolean - State of playing of tween
225 | **Example**
226 | ```js
227 | tween.isPlaying() // returns `true` if tween in progress
228 | ```
229 |
230 |
231 | #### Tween.Tween#isStarted() ⇒ boolean
232 | **Kind**: static method of [Tween](#TWEEN.Tween)
233 | **Returns**: boolean - State of started of tween
234 | **Example**
235 | ```js
236 | tween.isStarted() // returns `true` if tween in started
237 | ```
238 |
239 |
240 | #### Tween.Tween#reverse([state])
241 | Reverses the tween state/direction
242 |
243 | **Kind**: static method of [Tween](#TWEEN.Tween)
244 |
245 | | Param | Type | Description |
246 | | --- | --- | --- |
247 | | [state] | boolean | Set state of current reverse |
248 |
249 | **Example**
250 | ```js
251 | tween.reverse()
252 | ```
253 |
254 |
255 | #### Tween.Tween#reversed() ⇒ boolean
256 | **Kind**: static method of [Tween](#TWEEN.Tween)
257 | **Returns**: boolean - State of reversed
258 | **Example**
259 | ```js
260 | tween.reversed() // returns `true` if tween in reversed state
261 | ```
262 |
263 |
264 | #### Tween.Tween#pause()
265 | Pauses tween
266 |
267 | **Kind**: static method of [Tween](#TWEEN.Tween)
268 | **Example**
269 | ```js
270 | tween.pause()
271 | ```
272 |
273 |
274 | #### Tween.Tween#play()
275 | Play/Resume the tween
276 |
277 | **Kind**: static method of [Tween](#TWEEN.Tween)
278 | **Example**
279 | ```js
280 | tween.play()
281 | ```
282 |
283 |
284 | #### Tween.Tween#restart([noDelay])
285 | Restarts tween from initial value
286 |
287 | **Kind**: static method of [Tween](#TWEEN.Tween)
288 |
289 | | Param | Type | Description |
290 | | --- | --- | --- |
291 | | [noDelay] | boolean | If this param is set to `true`, restarts tween without `delay` |
292 |
293 | **Example**
294 | ```js
295 | tween.restart()
296 | ```
297 |
298 |
299 | #### ~~Tween.Tween#seek(time, [keepPlaying])~~
300 | ***Deprecated***
301 |
302 | Seek tween value by `time`. Note: Not works as excepted. PR are welcome
303 |
304 | **Kind**: static method of [Tween](#TWEEN.Tween)
305 |
306 | | Param | Type | Description |
307 | | --- | --- | --- |
308 | | time | Time | Tween update time |
309 | | [keepPlaying] | boolean | When this param is set to `false`, tween pausing after seek |
310 |
311 | **Example**
312 | ```js
313 | tween.seek(500)
314 | ```
315 |
316 |
317 | #### ~~Tween.Tween#duration(amount)~~
318 | ***Deprecated***
319 |
320 | Sets tween duration
321 |
322 | **Kind**: static method of [Tween](#TWEEN.Tween)
323 |
324 | | Param | Type | Description |
325 | | --- | --- | --- |
326 | | amount | number | Duration is milliseconds |
327 |
328 | **Example**
329 | ```js
330 | tween.duration(2000)
331 | ```
332 |
333 |
334 | #### Tween.Tween#to(properties, [duration])
335 | Sets target value and duration
336 |
337 | **Kind**: static method of [Tween](#TWEEN.Tween)
338 |
339 | | Param | Type | Default | Description |
340 | | --- | --- | --- | --- |
341 | | properties | object | | Target value (to value) |
342 | | [duration] | number \| Object | 1000 | Duration of tween |
343 |
344 | **Example**
345 | ```js
346 | let tween = new Tween({x:0}).to({x:100}, 2000)
347 | ```
348 |
349 |
350 | #### Tween.Tween#start(time)
351 | Start the tweening
352 |
353 | **Kind**: static method of [Tween](#TWEEN.Tween)
354 |
355 | | Param | Type | Description |
356 | | --- | --- | --- |
357 | | time | number \| string | setting manual time instead of Current browser timestamp or like `+1000` relative to current timestamp |
358 |
359 | **Example**
360 | ```js
361 | tween.start()
362 | ```
363 |
364 |
365 | #### Tween.Tween#stop()
366 | Stops the tween
367 |
368 | **Kind**: static method of [Tween](#TWEEN.Tween)
369 | **Example**
370 | ```js
371 | tween.stop()
372 | ```
373 |
374 |
375 | #### Tween.Tween#delay(amount)
376 | Set delay of tween
377 |
378 | **Kind**: static method of [Tween](#TWEEN.Tween)
379 |
380 | | Param | Type | Description |
381 | | --- | --- | --- |
382 | | amount | number | Sets tween delay / wait duration |
383 |
384 | **Example**
385 | ```js
386 | tween.delay(500)
387 | ```
388 |
389 |
390 | #### Tween.Tween#chainedTweens(arguments)
391 | Chained tweens
392 |
393 | **Kind**: static method of [Tween](#TWEEN.Tween)
394 |
395 | | Param | Type | Description |
396 | | --- | --- | --- |
397 | | arguments | any | Arguments list |
398 |
399 | **Example**
400 | ```js
401 | tween.chainedTweens(tween1, tween2)
402 | ```
403 |
404 |
405 | #### Tween.Tween#repeat(amount)
406 | Sets how times tween is repeating
407 |
408 | **Kind**: static method of [Tween](#TWEEN.Tween)
409 |
410 | | Param | Type | Description |
411 | | --- | --- | --- |
412 | | amount | amount | the times of repeat |
413 |
414 | **Example**
415 | ```js
416 | tween.repeat(5)
417 | ```
418 |
419 |
420 | #### Tween.Tween#reverseDelay(amount)
421 | Set delay of each repeat alternate of tween
422 |
423 | **Kind**: static method of [Tween](#TWEEN.Tween)
424 |
425 | | Param | Type | Description |
426 | | --- | --- | --- |
427 | | amount | number | Sets tween repeat alternate delay / repeat alternate wait duration |
428 |
429 | **Example**
430 | ```js
431 | tween.reverseDelay(500)
432 | ```
433 |
434 |
435 | #### Tween.Tween#yoyo(state, [_easingReverse])
436 | Set `yoyo` state (enables reverse in repeat)
437 |
438 | **Kind**: static method of [Tween](#TWEEN.Tween)
439 |
440 | | Param | Type | Description |
441 | | --- | --- | --- |
442 | | state | boolean | Enables alternate direction for repeat |
443 | | [_easingReverse] | function | Easing function in reverse direction |
444 |
445 | **Example**
446 | ```js
447 | tween.yoyo(true)
448 | ```
449 |
450 |
451 | #### Tween.Tween#easing(_easingFunction)
452 | Set easing
453 |
454 | **Kind**: static method of [Tween](#TWEEN.Tween)
455 |
456 | | Param | Type | Description |
457 | | --- | --- | --- |
458 | | _easingFunction | function | Easing function, applies in non-reverse direction if Tween#yoyo second argument is applied |
459 |
460 | **Example**
461 | ```js
462 | tween.easing(Easing.Elastic.InOut)
463 | ```
464 |
465 |
466 | #### Tween.Tween#interpolation(_interpolationFunction)
467 | Set interpolation
468 |
469 | **Kind**: static method of [Tween](#TWEEN.Tween)
470 |
471 | | Param | Type | Description |
472 | | --- | --- | --- |
473 | | _interpolationFunction | function | Interpolation function |
474 |
475 | **Example**
476 | ```js
477 | tween.interpolation(Interpolation.Bezier)
478 | ```
479 |
480 |
481 | #### Tween.Tween#update(time, [preserve], [forceTime])
482 | Updates initial object to target value by given `time`
483 |
484 | **Kind**: static method of [Tween](#TWEEN.Tween)
485 |
486 | | Param | Type | Description |
487 | | --- | --- | --- |
488 | | time | Time | Current time |
489 | | [preserve] | boolean | Prevents from removing tween from store |
490 | | [forceTime] | boolean | Forces to be frame rendered, even mismatching time |
491 |
492 | **Example**
493 | ```js
494 | tween.update(100)
495 | ```
496 |
497 |
498 | ### TWEEN.Plugins : object
499 | The plugins store object
500 |
501 | **Kind**: static namespace of [TWEEN](#TWEEN)
502 | **Example**
503 | ```js
504 | let num = Plugins.num = function (node, start, end) {
505 | return t => start + (end - start) * t
506 | }
507 | ```
508 |
509 |
510 | ### TWEEN.now ⇒
511 | Get browser/Node.js current time-stamp
512 |
513 | **Kind**: static constant of [TWEEN](#TWEEN)
514 | **Returns**: Normalised current time-stamp in milliseconds
515 | **Example**
516 | ```js
517 | TWEEN.now
518 | ```
519 |
520 |
521 | ### TWEEN.add(tween)
522 | Adds tween to list
523 |
524 | **Kind**: static method of [TWEEN](#TWEEN)
525 |
526 | | Param | Type | Description |
527 | | --- | --- | --- |
528 | | tween | Tween | Tween instance |
529 |
530 | **Example**
531 | ```js
532 | let tween = new Tween({x:0})
533 | tween.to({x:200}, 1000)
534 | TWEEN.add(tween)
535 | ```
536 |
537 |
538 | ### TWEEN.onTick(fn)
539 | Adds ticker like event
540 |
541 | **Kind**: static method of [TWEEN](#TWEEN)
542 |
543 | | Param | Type | Description |
544 | | --- | --- | --- |
545 | | fn | function | callback |
546 |
547 | **Example**
548 | ```js
549 | TWEEN.onTick(time => console.log(time))
550 | ```
551 |
552 |
553 | ### TWEEN.FrameThrottle(frameCount)
554 | Sets after how much frames empty updating should stop
555 |
556 | **Kind**: static method of [TWEEN](#TWEEN)
557 |
558 | | Param | Type | Default | Description |
559 | | --- | --- | --- | --- |
560 | | frameCount | number | 120 | count of frames that should stop after all tweens removed |
561 |
562 | **Example**
563 | ```js
564 | TWEEN.FrameThrottle(60)
565 | ```
566 |
567 |
568 | ### TWEEN.ToggleLagSmoothing(state)
569 | Handle lag, useful if you have rendering Canvas or DOM objects or using es6-tween plugins
570 |
571 | **Kind**: static method of [TWEEN](#TWEEN)
572 |
573 | | Param | Type | Default | Description |
574 | | --- | --- | --- | --- |
575 | | state | number | true | handle lag state |
576 |
577 | **Example**
578 | ```js
579 | TWEEN.ToggleLagSmoothing(false)
580 | ```
581 |
582 |
583 | ### TWEEN.autoPlay(state)
584 | Runs update loop automaticlly
585 |
586 | **Kind**: static method of [TWEEN](#TWEEN)
587 |
588 | | Param | Type | Description |
589 | | --- | --- | --- |
590 | | state | Boolean | State of auto-run of update loop |
591 |
592 | **Example**
593 | ```js
594 | TWEEN.autoPlay(true)
595 | ```
596 |
597 |
598 | ### TWEEN.removeAll()
599 | Removes all tweens from list
600 |
601 | **Kind**: static method of [TWEEN](#TWEEN)
602 | **Example**
603 | ```js
604 | TWEEN.removeAll() // removes all tweens, stored in global tweens list
605 | ```
606 |
607 |
608 | ### TWEEN.get(tween) ⇒ Tween
609 | **Kind**: static method of [TWEEN](#TWEEN)
610 | **Returns**: Tween - Matched tween
611 |
612 | | Param | Type | Description |
613 | | --- | --- | --- |
614 | | tween | Tween | Tween Instance to be matched |
615 |
616 | **Example**
617 | ```js
618 | TWEEN.get(tween)
619 | ```
620 |
621 |
622 | ### TWEEN.has(tween) ⇒ Boolean
623 | **Kind**: static method of [TWEEN](#TWEEN)
624 | **Returns**: Boolean - Status of Exists tween or not
625 |
626 | | Param | Type | Description |
627 | | --- | --- | --- |
628 | | tween | Tween | Tween Instance to be matched |
629 |
630 | **Example**
631 | ```js
632 | TWEEN.has(tween)
633 | ```
634 |
635 |
636 | ### TWEEN.remove(tween)
637 | Removes tween from list
638 |
639 | **Kind**: static method of [TWEEN](#TWEEN)
640 |
641 | | Param | Type | Description |
642 | | --- | --- | --- |
643 | | tween | Tween | Tween instance |
644 |
645 | **Example**
646 | ```js
647 | TWEEN.remove(tween)
648 | ```
649 |
650 |
651 | ### TWEEN.update([time], [preserve])
652 | Updates global tweens by given time
653 |
654 | **Kind**: static method of [TWEEN](#TWEEN)
655 |
656 | | Param | Type | Description |
657 | | --- | --- | --- |
658 | | [time] | number | Timestamp |
659 | | [preserve] | Boolean | Prevents tween to be removed after finish |
660 |
661 | **Example**
662 | ```js
663 | TWEEN.update(500)
664 | ```
665 |
666 |
667 | ### TWEEN.isRunning() ⇒ Boolean
668 | The state of ticker running
669 |
670 | **Kind**: static method of [TWEEN](#TWEEN)
671 | **Returns**: Boolean - Status of running updates on all tweens
672 | **Example**
673 | ```js
674 | TWEEN.isRunning()
675 | ```
676 |
677 |
678 | ### TWEEN.isLagSmoothing() ⇒ Boolean
679 | Returns state of lag smoothing handling
680 |
681 | **Kind**: static method of [TWEEN](#TWEEN)
682 | **Returns**: Boolean - Status of lag smoothing state
683 | **Example**
684 | ```js
685 | TWEEN.isRunning()
686 | ```
687 |
--------------------------------------------------------------------------------
/src/Tween.js:
--------------------------------------------------------------------------------
1 | import { add, now, Plugins, remove, isRunning, isLagSmoothing } from './core'
2 | import Easing from './Easing'
3 | import Interpolation from './Interpolation'
4 | import NodeCache, { Store } from './NodeCache'
5 | import Selector from './selector'
6 | import {
7 | decompose,
8 | decomposeString,
9 | recompose,
10 | deepCopy,
11 | SET_NESTED,
12 | EVENT_CALLBACK,
13 | CHAINED_TWEENS,
14 | EVENT_UPDATE,
15 | EVENT_COMPLETE,
16 | EVENT_START,
17 | EVENT_REPEAT,
18 | EVENT_REVERSE,
19 | EVENT_PAUSE,
20 | EVENT_PLAY,
21 | EVENT_RESTART,
22 | EVENT_STOP,
23 | EVENT_SEEK,
24 | FRAME_MS,
25 | TOO_LONG_FRAME_MS
26 | } from './constants'
27 |
28 | let _id = 0 // Unique ID
29 | const defaultEasing = Easing.Linear.None
30 |
31 | /**
32 | * Tween main constructor
33 | * @constructor
34 | * @class
35 | * @namespace TWEEN.Tween
36 | * @param {Object|Element} node Node Element or Tween initial object
37 | * @param {Object=} object If Node Element is using, second argument is used for Tween initial object
38 | * @example let tween = new Tween(myNode, {width:'100px'}).to({width:'300px'}, 2000).start()
39 | */
40 | class Tween {
41 | /**
42 | * Easier way to call the Tween
43 | * @param {Element} node DOM Element
44 | * @param {object} object - Initial value
45 | * @param {object} to - Target value
46 | * @param {object} params - Options of tweens
47 | * @example Tween.fromTo(node, {x:0}, {x:200}, {duration:1000})
48 | * @memberof TWEEN.Tween
49 | * @static
50 | */
51 | static fromTo (node, object, to, params = {}) {
52 | params.quickRender = params.quickRender ? params.quickRender : !to
53 | const tween = new Tween(node, object).to(to, params)
54 | if (params.quickRender) {
55 | tween.render().update(tween._startTime)
56 | tween._rendered = false
57 | tween._onStartCallbackFired = false
58 | }
59 | return tween
60 | }
61 | /**
62 | * Easier way calling constructor only applies the `to` value, useful for CSS Animation
63 | * @param {Element} node DOM Element
64 | * @param {object} to - Target value
65 | * @param {object} params - Options of tweens
66 | * @example Tween.to(node, {x:200}, {duration:1000})
67 | * @memberof TWEEN.Tween
68 | * @static
69 | */
70 | static to (node, to, params) {
71 | return Tween.fromTo(node, null, to, params)
72 | }
73 | /**
74 | * Easier way calling constructor only applies the `from` value, useful for CSS Animation
75 | * @param {Element} node DOM Element
76 | * @param {object} from - Initial value
77 | * @param {object} params - Options of tweens
78 | * @example Tween.from(node, {x:200}, {duration:1000})
79 | * @memberof TWEEN.Tween
80 | * @static
81 | */
82 | static from (node, from, params) {
83 | return Tween.fromTo(node, from, null, params)
84 | }
85 | constructor (node, object) {
86 | this.id = _id++
87 | if (!!node && typeof node === 'object' && !object && !node.nodeType) {
88 | object = this.object = node
89 | node = null
90 | } else if (!!node && (node.nodeType || node.length || typeof node === 'string')) {
91 | node = this.node = Selector(node)
92 | object = this.object = NodeCache(node, object, this)
93 | }
94 | this._valuesEnd = null
95 | this._valuesStart = Array.isArray(object) ? [] : {}
96 |
97 | this._duration = 1000
98 | this._easingFunction = defaultEasing
99 | this._easingReverse = defaultEasing
100 | this._interpolationFunction = Interpolation.Linear
101 |
102 | this._startTime = 0
103 | this._initTime = 0
104 | this._delayTime = 0
105 | this._repeat = 0
106 | this._r = 0
107 | this._isPlaying = false
108 | this._yoyo = false
109 | this._reversed = false
110 |
111 | this._onStartCallbackFired = false
112 | this._pausedTime = null
113 | this._isFinite = true
114 | this._maxListener = 15
115 | this._chainedTweensCount = 0
116 | this._prevTime = null
117 |
118 | return this
119 | }
120 |
121 | /**
122 | * Sets max `event` listener's count to Events system
123 | * @param {number} count - Event listener's count
124 | * @memberof TWEEN.Tween
125 | */
126 | setMaxListener (count = 15) {
127 | this._maxListener = count
128 | return this
129 | }
130 |
131 | /**
132 | * Adds `event` to Events system
133 | * @param {string} event - Event listener name
134 | * @param {Function} callback - Event listener callback
135 | * @memberof TWEEN.Tween
136 | */
137 | on (event, callback) {
138 | const { _maxListener } = this
139 | const callbackName = event + EVENT_CALLBACK
140 | for (let i = 0; i < _maxListener; i++) {
141 | const callbackId = callbackName + i
142 | if (!this[callbackId]) {
143 | this[callbackId] = callback
144 | break
145 | }
146 | }
147 | return this
148 | }
149 |
150 | /**
151 | * Adds `event` to Events system.
152 | * Removes itself after fired once
153 | * @param {string} event - Event listener name
154 | * @param {Function} callback - Event listener callback
155 | * @memberof TWEEN.Tween
156 | */
157 | once (event, callback) {
158 | const { _maxListener } = this
159 | const callbackName = event + EVENT_CALLBACK
160 | for (let i = 0; i < _maxListener; i++) {
161 | const callbackId = callbackName + i
162 | if (!this[callbackId]) {
163 | this[callbackId] = (...args) => {
164 | callback.apply(this, args)
165 | this[callbackId] = null
166 | }
167 | break
168 | }
169 | }
170 | return this
171 | }
172 |
173 | /**
174 | * Removes `event` from Events system
175 | * @param {string} event - Event listener name
176 | * @param {Function} callback - Event listener callback
177 | * @memberof TWEEN.Tween
178 | */
179 | off (event, callback) {
180 | const { _maxListener } = this
181 | const callbackName = event + EVENT_CALLBACK
182 | for (let i = 0; i < _maxListener; i++) {
183 | const callbackId = callbackName + i
184 | if (this[callbackId] === callback) {
185 | this[callbackId] = null
186 | }
187 | }
188 | return this
189 | }
190 |
191 | /**
192 | * Emits/Fired/Trigger `event` from Events system listeners
193 | * @param {string} event - Event listener name
194 | * @memberof TWEEN.Tween
195 | */
196 | emit (event, arg1, arg2, arg3) {
197 | const { _maxListener } = this
198 | const callbackName = event + EVENT_CALLBACK
199 |
200 | if (!this[callbackName + 0]) {
201 | return this
202 | }
203 | for (let i = 0; i < _maxListener; i++) {
204 | const callbackId = callbackName + i
205 | if (this[callbackId]) {
206 | this[callbackId](arg1, arg2, arg3)
207 | }
208 | }
209 | return this
210 | }
211 |
212 | /**
213 | * @return {boolean} State of playing of tween
214 | * @example tween.isPlaying() // returns `true` if tween in progress
215 | * @memberof TWEEN.Tween
216 | */
217 | isPlaying () {
218 | return this._isPlaying
219 | }
220 |
221 | /**
222 | * @return {boolean} State of started of tween
223 | * @example tween.isStarted() // returns `true` if tween in started
224 | * @memberof TWEEN.Tween
225 | */
226 | isStarted () {
227 | return this._onStartCallbackFired
228 | }
229 |
230 | /**
231 | * Reverses the tween state/direction
232 | * @example tween.reverse()
233 | * @param {boolean=} state Set state of current reverse
234 | * @memberof TWEEN.Tween
235 | */
236 | reverse (state) {
237 | const { _reversed } = this
238 |
239 | this._reversed = state !== undefined ? state : !_reversed
240 |
241 | return this
242 | }
243 |
244 | /**
245 | * @return {boolean} State of reversed
246 | * @example tween.reversed() // returns `true` if tween in reversed state
247 | * @memberof TWEEN.Tween
248 | */
249 | reversed () {
250 | return this._reversed
251 | }
252 |
253 | /**
254 | * Pauses tween
255 | * @example tween.pause()
256 | * @memberof TWEEN.Tween
257 | */
258 | pause () {
259 | if (!this._isPlaying) {
260 | return this
261 | }
262 |
263 | this._isPlaying = false
264 |
265 | remove(this)
266 | this._pausedTime = now()
267 |
268 | return this.emit(EVENT_PAUSE, this.object)
269 | }
270 |
271 | /**
272 | * Play/Resume the tween
273 | * @example tween.play()
274 | * @memberof TWEEN.Tween
275 | */
276 | play () {
277 | if (this._isPlaying) {
278 | return this
279 | }
280 |
281 | this._isPlaying = true
282 |
283 | this._startTime += now() - this._pausedTime
284 | this._initTime = this._startTime
285 | add(this)
286 | this._pausedTime = now()
287 |
288 | return this.emit(EVENT_PLAY, this.object)
289 | }
290 |
291 | /**
292 | * Restarts tween from initial value
293 | * @param {boolean=} noDelay If this param is set to `true`, restarts tween without `delay`
294 | * @example tween.restart()
295 | * @memberof TWEEN.Tween
296 | */
297 | restart (noDelay) {
298 | this._repeat = this._r
299 | this.reassignValues()
300 |
301 | add(this)
302 |
303 | return this.emit(EVENT_RESTART, this.object)
304 | }
305 |
306 | /**
307 | * Seek tween value by `time`. Note: Not works as excepted. PR are welcome
308 | * @param {Time} time Tween update time
309 | * @param {boolean=} keepPlaying When this param is set to `false`, tween pausing after seek
310 | * @example tween.seek(500)
311 | * @memberof TWEEN.Tween
312 | * @deprecated Not works as excepted, so we deprecated this method
313 | */
314 | seek (time, keepPlaying) {
315 | const { _duration, _initTime, _startTime, _reversed } = this
316 |
317 | let updateTime = _initTime + time
318 | this._isPlaying = true
319 |
320 | if (updateTime < _startTime && _startTime >= _initTime) {
321 | this._startTime -= _duration
322 | this._reversed = !_reversed
323 | }
324 |
325 | this.update(time, false)
326 |
327 | this.emit(EVENT_SEEK, time, this.object)
328 |
329 | return keepPlaying ? this : this.pause()
330 | }
331 |
332 | /**
333 | * Sets tween duration
334 | * @param {number} amount Duration is milliseconds
335 | * @example tween.duration(2000)
336 | * @memberof TWEEN.Tween
337 | * @deprecated Not works as excepted and useless, so we deprecated this method
338 | */
339 | duration (amount) {
340 | this._duration = typeof amount === 'function' ? amount(this._duration) : amount
341 |
342 | return this
343 | }
344 |
345 | /**
346 | * Sets target value and duration
347 | * @param {object} properties Target value (to value)
348 | * @param {number|Object=} [duration=1000] Duration of tween
349 | * @example let tween = new Tween({x:0}).to({x:100}, 2000)
350 | * @memberof TWEEN.Tween
351 | */
352 | to (properties, duration = 1000, maybeUsed) {
353 | this._valuesEnd = properties
354 |
355 | if (typeof duration === 'number' || typeof duration === 'function') {
356 | this._duration = typeof duration === 'function' ? duration(this._duration) : duration
357 | } else if (typeof duration === 'object') {
358 | for (const prop in duration) {
359 | if (typeof this[prop] === 'function') {
360 | const [arg1 = null, arg2 = null, arg3 = null, arg4 = null] = Array.isArray(duration[prop])
361 | ? duration[prop]
362 | : [duration[prop]]
363 | this[prop](arg1, arg2, arg3, arg4)
364 | }
365 | }
366 | }
367 |
368 | return this
369 | }
370 |
371 | /**
372 | * Renders and computes value at first render
373 | * @private
374 | * @memberof TWEEN.Tween
375 | */
376 | render () {
377 | if (this._rendered) {
378 | return this
379 | }
380 | let { _valuesStart, _valuesEnd, object, node, InitialValues } = this
381 |
382 | SET_NESTED(object)
383 | SET_NESTED(_valuesEnd)
384 |
385 | if (node && node.queueID && Store[node.queueID]) {
386 | const prevTweenByNode = Store[node.queueID]
387 | if (prevTweenByNode.propNormaliseRequired && prevTweenByNode.tween !== this) {
388 | for (const property in _valuesEnd) {
389 | if (prevTweenByNode.tween._valuesEnd[property] !== undefined) {
390 | // delete prevTweenByNode.tween._valuesEnd[property];
391 | }
392 | }
393 | prevTweenByNode.normalisedProp = true
394 | prevTweenByNode.propNormaliseRequired = false
395 | }
396 | }
397 |
398 | if (node && InitialValues) {
399 | if (!object || Object.keys(object).length === 0) {
400 | object = this.object = NodeCache(node, InitialValues(node, _valuesEnd), this)
401 | } else if (!_valuesEnd || Object.keys(_valuesEnd).length === 0) {
402 | _valuesEnd = this._valuesEnd = InitialValues(node, object)
403 | }
404 | }
405 | if (!_valuesStart.processed) {
406 | for (const property in _valuesEnd) {
407 | let start = object && object[property] && deepCopy(object[property])
408 | let end = _valuesEnd[property]
409 | if (Plugins[property] && Plugins[property].init) {
410 | Plugins[property].init.call(this, start, end, property, object)
411 | if (start === undefined && _valuesStart[property]) {
412 | start = _valuesStart[property]
413 | }
414 | if (Plugins[property].skipProcess) {
415 | continue
416 | }
417 | }
418 | if (
419 | (typeof start === 'number' && isNaN(start)) ||
420 | start === null ||
421 | end === null ||
422 | start === false ||
423 | end === false ||
424 | start === undefined ||
425 | end === undefined ||
426 | start === end
427 | ) {
428 | continue
429 | }
430 | _valuesStart[property] = start
431 | if (Array.isArray(end)) {
432 | if (!Array.isArray(start)) {
433 | end.unshift(start)
434 | for (let i = 0, len = end.length; i < len; i++) {
435 | if (typeof end[i] === 'string') {
436 | end[i] = decomposeString(end[i])
437 | }
438 | }
439 | } else {
440 | if (end.isString && object[property].isString && !start.isString) {
441 | start.isString = true
442 | } else {
443 | decompose(property, object, _valuesStart, _valuesEnd)
444 | }
445 | }
446 | } else {
447 | decompose(property, object, _valuesStart, _valuesEnd)
448 | }
449 | if (typeof start === 'number' && typeof end === 'string' && end[1] === '=') {
450 | continue
451 | }
452 | }
453 | _valuesStart.processed = true
454 | }
455 |
456 | if (Tween.Renderer && this.node && Tween.Renderer.init) {
457 | Tween.Renderer.init.call(this, object, _valuesStart, _valuesEnd)
458 | this.__render = true
459 | }
460 |
461 | this._rendered = true
462 |
463 | return this
464 | }
465 |
466 | /**
467 | * Start the tweening
468 | * @param {number|string} time setting manual time instead of Current browser timestamp or like `+1000` relative to current timestamp
469 | * @example tween.start()
470 | * @memberof TWEEN.Tween
471 | */
472 | start (time) {
473 | this._startTime = time !== undefined ? (typeof time === 'string' ? now() + parseFloat(time) : time) : now()
474 | this._startTime += this._delayTime
475 | this._initTime = this._prevTime = this._startTime
476 |
477 | this._onStartCallbackFired = false
478 | this._rendered = false
479 | this._isPlaying = true
480 |
481 | add(this)
482 |
483 | return this
484 | }
485 |
486 | /**
487 | * Stops the tween
488 | * @example tween.stop()
489 | * @memberof TWEEN.Tween
490 | */
491 | stop () {
492 | let { _isPlaying, _isFinite, object, _startTime, _duration, _r, _yoyo, _reversed } = this
493 |
494 | if (!_isPlaying) {
495 | return this
496 | }
497 |
498 | let atStart = _isFinite ? (_r + 1) % 2 === 1 : !_reversed
499 |
500 | this._reversed = false
501 |
502 | if (_yoyo && atStart) {
503 | this.update(_startTime)
504 | } else {
505 | this.update(_startTime + _duration)
506 | }
507 | remove(this)
508 |
509 | return this.emit(EVENT_STOP, object)
510 | }
511 |
512 | /**
513 | * Set delay of tween
514 | * @param {number} amount Sets tween delay / wait duration
515 | * @example tween.delay(500)
516 | * @memberof TWEEN.Tween
517 | */
518 | delay (amount) {
519 | this._delayTime = typeof amount === 'function' ? amount(this._delayTime) : amount
520 |
521 | return this
522 | }
523 |
524 | /**
525 | * Chained tweens
526 | * @param {any} arguments Arguments list
527 | * @example tween.chainedTweens(tween1, tween2)
528 | * @memberof TWEEN.Tween
529 | */
530 | chainedTweens () {
531 | this._chainedTweensCount = arguments.length
532 | if (!this._chainedTweensCount) {
533 | return this
534 | }
535 | for (let i = 0, len = this._chainedTweensCount; i < len; i++) {
536 | this[CHAINED_TWEENS + i] = arguments[i]
537 | }
538 |
539 | return this
540 | }
541 |
542 | /**
543 | * Sets how times tween is repeating
544 | * @param {amount} amount the times of repeat
545 | * @example tween.repeat(5)
546 | * @memberof TWEEN.Tween
547 | */
548 | repeat (amount) {
549 | this._repeat = !this._duration ? 0 : typeof amount === 'function' ? amount(this._repeat) : amount
550 | this._r = this._repeat
551 | this._isFinite = isFinite(amount)
552 |
553 | return this
554 | }
555 |
556 | /**
557 | * Set delay of each repeat alternate of tween
558 | * @param {number} amount Sets tween repeat alternate delay / repeat alternate wait duration
559 | * @example tween.reverseDelay(500)
560 | * @memberof TWEEN.Tween
561 | */
562 | reverseDelay (amount) {
563 | this._reverseDelayTime = typeof amount === 'function' ? amount(this._reverseDelayTime) : amount
564 |
565 | return this
566 | }
567 |
568 | /**
569 | * Set `yoyo` state (enables reverse in repeat)
570 | * @param {boolean} state Enables alternate direction for repeat
571 | * @param {Function=} _easingReverse Easing function in reverse direction
572 | * @example tween.yoyo(true)
573 | * @memberof TWEEN.Tween
574 | */
575 | yoyo (state, _easingReverse) {
576 | this._yoyo = typeof state === 'function' ? state(this._yoyo) : state === null ? this._yoyo : state
577 | if (!state) {
578 | this._reversed = false
579 | }
580 | this._easingReverse = _easingReverse || null
581 |
582 | return this
583 | }
584 |
585 | /**
586 | * Set easing
587 | * @param {Function} _easingFunction Easing function, applies in non-reverse direction if Tween#yoyo second argument is applied
588 | * @example tween.easing(Easing.Elastic.InOut)
589 | * @memberof TWEEN.Tween
590 | */
591 | easing (_easingFunction) {
592 | this._easingFunction = _easingFunction
593 |
594 | return this
595 | }
596 |
597 | /**
598 | * Set interpolation
599 | * @param {Function} _interpolationFunction Interpolation function
600 | * @example tween.interpolation(Interpolation.Bezier)
601 | * @memberof TWEEN.Tween
602 | */
603 | interpolation (_interpolationFunction) {
604 | if (typeof _interpolationFunction === 'function') {
605 | this._interpolationFunction = _interpolationFunction
606 | }
607 |
608 | return this
609 | }
610 |
611 | /**
612 | * Reassigns value for rare-case like Tween#restart or for Timeline
613 | * @private
614 | * @memberof TWEEN.Tween
615 | */
616 | reassignValues (time) {
617 | const { _valuesStart, object, _delayTime } = this
618 |
619 | this._isPlaying = true
620 | this._startTime = time !== undefined ? time : now()
621 | this._startTime += _delayTime
622 | this._reversed = false
623 | add(this)
624 |
625 | for (const property in _valuesStart) {
626 | const start = _valuesStart[property]
627 |
628 | object[property] = start
629 | }
630 |
631 | return this
632 | }
633 |
634 | /**
635 | * Updates initial object to target value by given `time`
636 | * @param {Time} time Current time
637 | * @param {boolean=} preserve Prevents from removing tween from store
638 | * @param {boolean=} forceTime Forces to be frame rendered, even mismatching time
639 | * @example tween.update(100)
640 | * @memberof TWEEN.Tween
641 | */
642 | update (time, preserve, forceTime) {
643 | let {
644 | _onStartCallbackFired,
645 | _easingFunction,
646 | _interpolationFunction,
647 | _easingReverse,
648 | _repeat,
649 | _delayTime,
650 | _reverseDelayTime,
651 | _yoyo,
652 | _reversed,
653 | _startTime,
654 | _prevTime,
655 | _duration,
656 | _valuesStart,
657 | _valuesEnd,
658 | object,
659 | _isFinite,
660 | _isPlaying,
661 | __render,
662 | _chainedTweensCount
663 | } = this
664 |
665 | let elapsed
666 | let currentEasing
667 | let property
668 | let propCount = 0
669 |
670 | if (!_duration) {
671 | elapsed = 1
672 | _repeat = 0
673 | } else {
674 | time = time !== undefined ? time : now()
675 |
676 | let delta = time - _prevTime
677 | this._prevTime = time
678 | if (delta > TOO_LONG_FRAME_MS && isRunning() && isLagSmoothing()) {
679 | time -= delta - FRAME_MS
680 | }
681 |
682 | if (!_isPlaying || (time < _startTime && !forceTime)) {
683 | return true
684 | }
685 |
686 | elapsed = (time - _startTime) / _duration
687 | elapsed = elapsed > 1 ? 1 : elapsed
688 | elapsed = _reversed ? 1 - elapsed : elapsed
689 | }
690 |
691 | if (!_onStartCallbackFired) {
692 | if (!this._rendered) {
693 | this.render()
694 | this._rendered = true
695 | }
696 |
697 | this.emit(EVENT_START, object)
698 |
699 | this._onStartCallbackFired = true
700 | }
701 |
702 | currentEasing = _reversed ? _easingReverse || _easingFunction : _easingFunction
703 |
704 | if (!object) {
705 | return true
706 | }
707 |
708 | for (property in _valuesEnd) {
709 | const start = _valuesStart[property]
710 | if ((start === undefined || start === null) && !(Plugins[property] && Plugins[property].update)) {
711 | continue
712 | }
713 | const end = _valuesEnd[property]
714 | const value = currentEasing[property]
715 | ? currentEasing[property](elapsed)
716 | : typeof currentEasing === 'function'
717 | ? currentEasing(elapsed)
718 | : defaultEasing(elapsed)
719 | const _interpolationFunctionCall = _interpolationFunction[property]
720 | ? _interpolationFunction[property]
721 | : typeof _interpolationFunction === 'function'
722 | ? _interpolationFunction
723 | : Interpolation.Linear
724 |
725 | if (typeof end === 'number') {
726 | object[property] = start + (end - start) * value
727 | } else if (Array.isArray(end) && !end.isString && !Array.isArray(start)) {
728 | object[property] = _interpolationFunctionCall(end, value, object[property])
729 | } else if (end && end.update) {
730 | end.update(value)
731 | } else if (typeof end === 'function') {
732 | object[property] = end(value)
733 | } else if (typeof end === 'string' && typeof start === 'number') {
734 | object[property] = start + parseFloat(end[0] + end.substr(2)) * value
735 | } else {
736 | recompose(property, object, _valuesStart, _valuesEnd, value, elapsed)
737 | }
738 | if (Plugins[property] && Plugins[property].update) {
739 | Plugins[property].update.call(this, object[property], start, end, value, elapsed, property)
740 | }
741 | propCount++
742 | }
743 |
744 | if (!propCount) {
745 | remove(this)
746 | return false
747 | }
748 |
749 | if (__render && Tween.Renderer && Tween.Renderer.update) {
750 | Tween.Renderer.update.call(this, object, elapsed)
751 | }
752 |
753 | this.emit(EVENT_UPDATE, object, elapsed, time)
754 |
755 | if (elapsed === 1 || (_reversed && elapsed === 0)) {
756 | if (_repeat > 0 && _duration > 0) {
757 | if (_isFinite) {
758 | this._repeat--
759 | }
760 |
761 | if (_yoyo) {
762 | this._reversed = !_reversed
763 | } else {
764 | for (property in _valuesEnd) {
765 | let end = _valuesEnd[property]
766 | if (typeof end === 'string' && typeof _valuesStart[property] === 'number') {
767 | _valuesStart[property] += parseFloat(end[0] + end.substr(2))
768 | }
769 | }
770 | }
771 |
772 | this.emit(_yoyo && !_reversed ? EVENT_REVERSE : EVENT_REPEAT, object)
773 |
774 | if (_reversed && _reverseDelayTime) {
775 | this._startTime = time - _reverseDelayTime
776 | } else {
777 | this._startTime = time + _delayTime
778 | }
779 |
780 | return true
781 | } else {
782 | if (!preserve) {
783 | this._isPlaying = false
784 | remove(this)
785 | _id--
786 | }
787 | this.emit(EVENT_COMPLETE, object)
788 | this._repeat = this._r
789 |
790 | if (_chainedTweensCount) {
791 | for (let i = 0; i < _chainedTweensCount; i++) {
792 | this[CHAINED_TWEENS + i].start(time + _duration)
793 | }
794 | }
795 |
796 | return false
797 | }
798 | }
799 |
800 | return true
801 | }
802 | }
803 |
804 | export default Tween
805 |
--------------------------------------------------------------------------------
/performance/kute.js:
--------------------------------------------------------------------------------
1 | /* KUTE.js - The Light Tweening Engine
2 | * by dnp_theme
3 | * Licensed under MIT-License
4 | */
5 | (function (root, factory) {
6 | if (typeof define === 'function' && define.amd) {
7 | define([], factory) // AMD. Register as an anonymous module.
8 | } else if (typeof exports === 'object') {
9 | module.exports = factory() // Node, not strict CommonJS
10 | } else {
11 | root.KUTE = factory()
12 | }
13 | }(this, function () {
14 | 'use strict'
15 |
16 | // set a custom scope for KUTE.js
17 | var g = typeof global !== 'undefined' ? global : window, time = g.performance,
18 | body = document.body, tweens = [], tick = null, // tick must be null!!
19 |
20 | // strings
21 | length = 'length',
22 | split = 'split',
23 | indexOf = 'indexOf',
24 | replace = 'replace',
25 |
26 | offsetWidth = 'offsetWidth',
27 | offsetHeight = 'offsetHeight',
28 |
29 | options = 'options',
30 | valuesStart = 'valuesStart',
31 | valuesEnd = 'valuesEnd',
32 | valuesRepeat = 'valuesRepeat',
33 |
34 | element = 'element',
35 | playing = 'playing',
36 |
37 | duration = 'duration',
38 | delay = 'delay',
39 | offset = 'offset',
40 | repeat = 'repeat',
41 | repeatDelay = 'repeatDelay',
42 | yoyo = 'yoyo',
43 | easing = 'easing',
44 | chain = 'chain',
45 | keepHex = 'keepHex',
46 |
47 | style = 'style',
48 | dataTweening = 'data-tweening',
49 | getElementsByTagName = 'getElementsByTagName',
50 | addEventListener = 'addEventListener',
51 | removeEventListener = 'removeEventListener'
52 |
53 | // supported properties
54 | var colorProps = ['color', 'backgroundColor'], // 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+)
55 | boxModelProps = ['top', 'left', 'width', 'height'],
56 | transformFunctions = ['translate3d', 'translateX', 'translateY', 'translateZ', 'rotate', 'translate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'scale'],
57 | scrollProp = ['scroll'], // has no default value, it's calculated on tween start
58 | opacityProp = ['opacity'], // opacity
59 | coreProps = colorProps.concat(opacityProp, boxModelProps, transformFunctions),
60 | defaultPropsValues = {}
61 |
62 | // populate default values object
63 | for (var propertyIndex = 0, allCorePropLength = coreProps[length], coreProp; propertyIndex < allCorePropLength; propertyIndex++) {
64 | coreProp = coreProps[propertyIndex]
65 | if (colorProps[indexOf](coreProp) !== -1) {
66 | defaultPropsValues[coreProp] = 'rgba(0,0,0,0)' // defaultPropsValues[coreProp] = {r:0,g:0,b:0,a:1};
67 | } else if (boxModelProps[indexOf](coreProp) !== -1) {
68 | defaultPropsValues[coreProp] = 0
69 | } else if (coreProp === 'translate3d') { // px
70 | defaultPropsValues[coreProp] = [0, 0, 0]
71 | } else if (coreProp === 'translate') { // px
72 | defaultPropsValues[coreProp] = [0, 0]
73 | } else if (coreProp === 'rotate' || /X|Y|Z/.test(coreProp)) { // deg
74 | defaultPropsValues[coreProp] = 0
75 | } else if (coreProp === 'scale' || coreProp === 'opacity') { // unitless
76 | defaultPropsValues[coreProp] = 1
77 | }
78 | }
79 |
80 | // default tween options, since 1.6.1
81 | var defaultOptions = {
82 | duration: 700,
83 | delay: 0,
84 | offset: 0,
85 | repeat: 0,
86 | repeatDelay: 0,
87 | yoyo: false,
88 | easing: 'linear',
89 | keepHex: false
90 | },
91 | // tools / utils
92 | getPrefix = function () { // returns browser prefix
93 | var prefixes = ['Moz', 'moz', 'Webkit', 'webkit', 'O', 'o', 'Ms', 'ms'], thePrefix
94 | for (var pIndex = 0, pfl = prefixes[length]; pIndex < pfl; pIndex++) {
95 | if (prefixes[pIndex] + 'Transform' in body[style]) { thePrefix = prefixes[pIndex]; break }
96 | }
97 | return thePrefix
98 | },
99 | property = function (propertyToPrefix) { // returns prefixed property | property
100 | var prefixRequired = (!(propertyToPrefix in body[style])), prefix = getPrefix() // is prefix required for property | prefix
101 | return prefixRequired ? prefix + (propertyToPrefix.charAt(0).toUpperCase() + propertyToPrefix.slice(1)) : propertyToPrefix
102 | },
103 | selector = function (el, multi) { // a public selector utility
104 | var requestedElem
105 | if (multi) {
106 | requestedElem = el instanceof Object || typeof el === 'object' ? el : document.querySelectorAll(el)
107 | } else {
108 | requestedElem = typeof el === 'object' ? el : document.querySelector(el)
109 | }
110 | if (requestedElem === null && el !== 'window') throw new TypeError('Element not found or incorrect selector: ' + el)
111 | return requestedElem
112 | },
113 | radToDeg = function (a) { return a * 180 / Math.PI },
114 | trueDimension = function (dimValue, isAngle) { // true dimension returns { v = value, u = unit }
115 | var intValue = parseInt(dimValue) || 0, mUnits = ['px', '%', 'deg', 'rad', 'em', 'rem', 'vh', 'vw'], theUnit
116 | for (var mIndex = 0; mIndex < mUnits[length]; mIndex++) {
117 | if (typeof dimValue === 'string' && dimValue[indexOf](mUnits[mIndex]) !== -1) {
118 | theUnit = mUnits[mIndex]; break
119 | }
120 | }
121 | theUnit = theUnit !== undefined ? theUnit : (isAngle ? 'deg' : 'px')
122 | return { v: intValue, u: theUnit }
123 | },
124 | trueColor = function (colorString) { // replace transparent and transform any color to rgba()/rgb()
125 | if (/rgb|rgba/.test(colorString)) { // first check if it's a rgb string
126 | var vrgb = colorString[replace](/\s|\)/, '')[split]('(')[1][split](','), colorAlpha = vrgb[3] ? vrgb[3] : null
127 | if (!colorAlpha) {
128 | return { r: parseInt(vrgb[0]), g: parseInt(vrgb[1]), b: parseInt(vrgb[2]) }
129 | } else {
130 | return { r: parseInt(vrgb[0]), g: parseInt(vrgb[1]), b: parseInt(vrgb[2]), a: parseFloat(colorAlpha) }
131 | }
132 | } else if (/^#/.test(colorString)) {
133 | var fromHex = hexToRGB(colorString); return { r: fromHex.r, g: fromHex.g, b: fromHex.b }
134 | } else if (/transparent|none|initial|inherit/.test(colorString)) {
135 | return { r: 0, g: 0, b: 0, a: 0 }
136 | } else if (!/^#|^rgb/.test(colorString)) { // maybe we can check for web safe colors
137 | var siteHead = document[getElementsByTagName]('head')[0]; siteHead[style].color = colorString
138 | var webColor = g.getComputedStyle(siteHead, null).color; webColor = /rgb/.test(webColor) ? webColor[replace](/[^\d,]/g, '')[split](',') : [0, 0, 0]
139 | siteHead[style].color = ''; return { r: parseInt(webColor[0]), g: parseInt(webColor[1]), b: parseInt(webColor[2]) }
140 | }
141 | },
142 | rgbToHex = function (r, g, b) { // transform rgb to hex or vice-versa | webkit browsers ignore HEX, always use RGB/RGBA
143 | return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
144 | },
145 | hexToRGB = function (hex) {
146 | var hexShorthand = /^#?([a-f\d])([a-f\d])([a-f\d])$/i // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
147 | hex = hex[replace](hexShorthand, function (m, r, g, b) {
148 | return r + r + g + g + b + b
149 | })
150 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
151 | return result ? {
152 | r: parseInt(result[1], 16),
153 | g: parseInt(result[2], 16),
154 | b: parseInt(result[3], 16)
155 | } : null
156 | },
157 | getInlineStyle = function (el) { // get transform style for element from cssText for .to() method
158 | if (!el) return // if the scroll applies to `window` it returns as it has no styling
159 | var css = el[style].cssText[replace](/\s/g, '')[split](';'), transformObject = {} // the cssText | the resulting transform object
160 |
161 | // if we have any inline style in the cssText attribute, usually it has higher priority
162 | for (var i = 0, csl = css[length]; i < csl; i++) {
163 | if (/transform/i.test(css[i])) {
164 | var tps = css[i][split](':')[1][split](')') // all transform properties
165 | for (var k = 0, tpl = tps[length] - 1; k < tpl; k++) {
166 | var tpv = tps[k][split]('('), tp = tpv[0], tv = tpv[1] // each transform property, the sp is for transform property
167 | if (transformFunctions[indexOf](tp) !== -1) {
168 | transformObject[tp] = /translate3d/.test(tp) ? tv[split](',') : tv
169 | }
170 | }
171 | }
172 | }
173 | return transformObject
174 | },
175 | getCurrentStyle = function (elem, propertyName) { // get computed style property for element for .to() method
176 | var styleAttribute = elem[style], computedStyle = g.getComputedStyle(elem, null) || elem.currentStyle,
177 | prefixedProp = property(propertyName), // the computed style | prefixed property
178 | styleValue = styleAttribute[propertyName] && !/auto|initial|none|unset/.test(styleAttribute[propertyName]) ? styleAttribute[propertyName] : computedStyle[prefixedProp]
179 | if (propertyName !== 'transform' && (prefixedProp in computedStyle || prefixedProp in styleAttribute)) {
180 | if (styleValue) {
181 | if (prefixedProp === 'filter') { // handle IE8 opacity
182 | var filterValue = parseInt(styleValue[split]('=')[1][replace](')', ''))
183 | return parseFloat(filterValue / 100)
184 | } else {
185 | return styleValue
186 | }
187 | } else {
188 | return defaultPropsValues[propertyName]
189 | }
190 | }
191 | },
192 |
193 | // more internals
194 | getAll = function () { return tweens },
195 | removeAll = function () { tweens = [] },
196 | add = function (tw) { tweens.push(tw) },
197 | remove = function (tw) { var i = tweens[indexOf](tw); if (i !== -1) { tweens.splice(i, 1) } },
198 | stop = function () { if (tick) { _cancelAnimationFrame(tick); tick = null } },
199 |
200 | canTouch = ('ontouchstart' in g || navigator && navigator.msMaxTouchPoints) || false, // support Touch?
201 | touchOrWheel = canTouch ? 'touchstart' : 'mousewheel', mouseEnter = 'mouseenter', // events to prevent on scroll
202 | _requestAnimationFrame = g.requestAnimationFrame || g.webkitRequestAnimationFrame || function (c) { return setTimeout(c, 16) },
203 | _cancelAnimationFrame = g.cancelAnimationFrame || g.webkitCancelRequestAnimationFrame || function (c) { return clearTimeout(c) },
204 | transformProperty = property('transform'),
205 |
206 | // true scroll container
207 | html = document[getElementsByTagName]('HTML')[0],
208 | scrollContainer = navigator && /webkit/i.test(navigator.userAgent) || document.compatMode == 'BackCompat' ? body : html,
209 |
210 | // browser detection
211 | isIE = navigator && (new RegExp('MSIE ([0-9]{1,}[\.0-9]{0,})').exec(navigator.userAgent) !== null) ? parseFloat(RegExp.$1) : false,
212 | isIE8 = isIE === 8, // check IE8/IE
213 | isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) // we optimize morph depending on device type
214 |
215 | // KUTE.js INTERPOLATORS
216 | var interpolate = g.Interpolate = {},
217 | number = interpolate.number = function (a, b, v) { // number1, number2, progress
218 | a = +a; b -= a; return a + b * v
219 | },
220 | unit = interpolate.unit = function (a, b, u, v) { // number1, number2, unit, progress
221 | a = +a; b -= a; return (a + b * v) + u
222 | },
223 | color = interpolate.color = function (a, b, v, toHex) { // rgba1, rgba2, progress, convertToHex(true/false)
224 | var _c = {}, c, ep = ')', cm = ',', rgb = 'rgb(', rgba = 'rgba('
225 | for (c in b) { _c[c] = c !== 'a' ? (number(a[c], b[c], v) >> 0 || 0) : (a[c] && b[c]) ? (number(a[c], b[c], v) * 100 >> 0) / 100 : null }
226 | return toHex ? rgbToHex(_c.r, _c.g, _c.b) : !_c.a ? rgb + _c.r + cm + _c.g + cm + _c.b + ep : rgba + _c.r + cm + _c.g + cm + _c.b + cm + _c.a + ep
227 | },
228 | translate = interpolate.translate = isMobile ? function (a, b, u, v) {
229 | var translation = {}
230 | for (var ax in b) {
231 | translation[ax] = (a[ax] === b[ax] ? b[ax] : (a[ax] + (b[ax] - a[ax]) * v) >> 0) + u
232 | }
233 | return translation.x || translation.y ? 'translate(' + translation.x + ',' + translation.y + ')'
234 | : 'translate3d(' + translation.translateX + ',' + translation.translateY + ',' + translation.translateZ + ')'
235 | } : function (a, b, u, v) {
236 | var translation = {}
237 | for (var ax in b) {
238 | translation[ax] = (a[ax] === b[ax] ? b[ax] : ((a[ax] + (b[ax] - a[ax]) * v) * 100 >> 0) / 100) + u
239 | }
240 | return translation.x || translation.y ? 'translate(' + translation.x + ',' + translation.y + ')'
241 | : 'translate3d(' + translation.translateX + ',' + translation.translateY + ',' + translation.translateZ + ')'
242 | },
243 | rotate = interpolate.rotate = function (a, b, u, v) {
244 | var rotation = {}
245 | for (var rx in b) {
246 | rotation[rx] = rx === 'z' ? ('rotate(' + (((a[rx] + (b[rx] - a[rx]) * v) * 100 >> 0) / 100) + u + ')')
247 | : (rx + '(' + (((a[rx] + (b[rx] - a[rx]) * v) * 100 >> 0) / 100) + u + ')')
248 | }
249 | return rotation.z ? rotation.z : (rotation.rotateX || '') + (rotation.rotateY || '') + (rotation.rotateZ || '')
250 | },
251 | skew = interpolate.skew = function (a, b, u, v) {
252 | var skewProp = {}
253 | for (var sx in b) {
254 | skewProp[sx] = sx + '(' + (((a[sx] + (b[sx] - a[sx]) * v) * 10 >> 0) / 10) + u + ')'
255 | }
256 | return (skewProp.skewX || '') + (skewProp.skewY || '')
257 | },
258 | scale = interpolate.scale = function (a, b, v) {
259 | return 'scale(' + (((a + (b - a) * v) * 1000 >> 0) / 1000) + ')'
260 | },
261 |
262 | // KUTE.js DOM update functions
263 | DOM = {},
264 | ticker = function (t) {
265 | var i = 0
266 | while (i < tweens[length]) {
267 | if (update.call(tweens[i], t)) {
268 | i++
269 | } else {
270 | tweens.splice(i, 1)
271 | }
272 | }
273 | tick = _requestAnimationFrame(ticker)
274 | },
275 | update = function (t) {
276 | t = t || time.now()
277 | if (t < this._startTime && this[playing]) { return true }
278 |
279 | var elapsed = Math.min((t - this._startTime) / this[options][duration], 1), progress = this[options][easing](elapsed) // calculate progress
280 |
281 | for (var tweenProp in this[valuesEnd]) { // render the DOM update
282 | DOM[tweenProp](this[element], tweenProp, this[valuesStart][tweenProp], this[valuesEnd][tweenProp], progress, this[options])
283 | }
284 |
285 | if (this[options].update) { this[options].update.call() } // fire the updateCallback
286 |
287 | if (elapsed === 1) {
288 | if (this[options][repeat] > 0) {
289 | if (isFinite(this[options][repeat])) { this[options][repeat]-- }
290 |
291 | if (this[options][yoyo]) { // handle yoyo
292 | this.reversed = !this.reversed
293 | reverse.call(this)
294 | }
295 |
296 | this._startTime = (this[options][yoyo] && !this.reversed) ? t + this[options][repeatDelay] : t // set the right time for delay
297 | return true
298 | } else {
299 | if (this[options].complete) { this[options].complete.call() }
300 |
301 | scrollOut.call(this) // unbind preventing scroll when scroll tween finished
302 |
303 | for (var i = 0, ctl = this[options][chain][length]; i < ctl; i++) { // start animating chained tweens
304 | this[options][chain][i].start()
305 | }
306 |
307 | // stop ticking when finished
308 | close.call(this)
309 | }
310 | return false
311 | }
312 | return true
313 | },
314 |
315 | // applies the transform origin and perspective
316 | perspective = function () {
317 | var el = this[element], ops = this[options]
318 | if (ops.perspective !== undefined && transformProperty in this[valuesEnd]) { // element perspective
319 | this[valuesStart][transformProperty]['perspective'] = this[valuesEnd][transformProperty]['perspective']
320 | }
321 | // element transform origin / we filter it out for svgTransform to fix the Firefox transformOrigin bug https://bugzilla.mozilla.org/show_bug.cgi?id=923193
322 | if (ops.transformOrigin !== undefined && (!('svgTransform' in this[valuesEnd]))) { el[style][property('transformOrigin')] = ops.transformOrigin } // set transformOrigin for CSS3 transforms only
323 | if (ops.perspectiveOrigin !== undefined) { el[style][property('perspectiveOrigin')] = ops.perspectiveOrigin } // element perspective origin
324 | if (ops.parentPerspective !== undefined) { el.parentNode[style][property('perspective')] = ops.parentPerspective + 'px' } // parent perspective
325 | if (ops.parentPerspectiveOrigin !== undefined) { el.parentNode[style][property('perspectiveOrigin')] = ops.parentPerspectiveOrigin } // parent perspective origin
326 | },
327 |
328 | // plugin connector objects
329 | prepareStart = {}, // check current property value when .to() method is used
330 | crossCheck = {}, // checks for differences between start and end value, try to make sure start unit and end unit are same as well as consistent, stack transforms, process SVG paths
331 |
332 | // parse properties object
333 | // string parsing and property specific value processing
334 | parseProperty = { // we already start working on core supported properties
335 | boxModel: function (tweenProp, inputValue) {
336 | if (!(tweenProp in DOM)) {
337 | DOM[tweenProp] = function (elem, tweenProp, a, b, v) {
338 | elem[style][tweenProp] = (v > 0.99 || v < 0.01 ? ((number(a, b, v) * 10) >> 0) / 10 : (number(a, b, v)) >> 0) + 'px'
339 | }
340 | }
341 | var boxValue = trueDimension(inputValue), offsetProp = tweenProp === 'height' ? offsetHeight : offsetWidth
342 | return boxValue.u === '%' ? boxValue.v * this[element][offsetProp] / 100 : boxValue.v
343 | },
344 | transform: function (tweenProp, inputValue) {
345 | if (!(transformProperty in DOM)) {
346 | DOM[transformProperty] = function (elem, tweenProp, a, b, v, o) {
347 | elem[style][tweenProp] = (a.perspective || '') +
348 | ('translate' in a ? translate(a.translate, b.translate, 'px', v) : '') +
349 | ('rotate' in a ? rotate(a.rotate, b.rotate, 'deg', v) : '') +
350 | ('skew' in a ? skew(a.skew, b.skew, 'deg', v) : '') +
351 | ('scale' in a ? scale(a.scale, b.scale, v) : '')
352 | }
353 | }
354 |
355 | // process each transform property
356 | if (/translate/.test(tweenProp)) {
357 | if (tweenProp === 'translate3d') {
358 | var t3d = inputValue[split](','), t3d0 = trueDimension(t3d[0]), t3d1 = trueDimension(t3d[1], t3d2 = trueDimension(t3d[2]))
359 | return {
360 | translateX: t3d0.u === '%' ? (t3d0.v * this[element][offsetWidth] / 100) : t3d0.v,
361 | translateY: t3d1.u === '%' ? (t3d1.v * this[element][offsetHeight] / 100) : t3d1.v,
362 | translateZ: t3d2.u === '%' ? (t3d2.v * (this[element][offsetHeight] + this[element][offsetWidth]) / 200) : t3d2.v // to be changed with something like element and/or parent perspective
363 | }
364 | } else if (/^translate(?:[XYZ])$/.test(tweenProp)) {
365 | var t1d = trueDimension(inputValue), percentOffset = /X/.test(tweenProp) ? this[element][offsetWidth] / 100 : /Y/.test(tweenProp) ? this[element][offsetHeight] / 100 : (this[element][offsetWidth] + this[element][offsetHeight]) / 200
366 |
367 | return t1d.u === '%' ? (t1d.v * percentOffset) : t1d.v
368 | } else if (tweenProp === 'translate') {
369 | var tv = typeof inputValue === 'string' ? inputValue[split](',') : inputValue, t2d = {}, t2dv,
370 | t2d0 = trueDimension(tv[0]), t2d1 = tv[length] ? trueDimension(tv[1]) : {v: 0, u: 'px'}
371 | if (tv instanceof Array) {
372 | t2d.x = t2d0.u === '%' ? (t2d0.v * this[element][offsetWidth] / 100) : t2d0.v,
373 | t2d.y = t2d1.u === '%' ? (t2d1.v * this[element][offsetHeight] / 100) : t2d1.v
374 | } else {
375 | t2dv = trueDimension(tv)
376 | t2d.x = t2dv.u === '%' ? (t2dv.v * this[element][offsetWidth] / 100) : t2dv.v,
377 | t2d.y = 0
378 | }
379 |
380 | return t2d
381 | }
382 | } else if (/rotate|skew/.test(tweenProp)) {
383 | if (/^rotate(?:[XYZ])$|skew(?:[XY])$/.test(tweenProp)) {
384 | var r3d = trueDimension(inputValue, true)
385 | return r3d.u === 'rad' ? radToDeg(r3d.v) : r3d.v
386 | } else if (tweenProp === 'rotate') {
387 | var r2d = {}, r2dv = trueDimension(inputValue, true)
388 | r2d.z = r2dv.u === 'rad' ? radToDeg(r2dv.v) : r2dv.v
389 | return r2d
390 | }
391 | } else if (tweenProp === 'scale') {
392 | return parseFloat(inputValue) // this must be parseFloat(v)
393 | }
394 | },
395 | unitless: function (tweenProp, inputValue) { // scroll | opacity
396 | if (/scroll/.test(tweenProp) && !(tweenProp in DOM)) {
397 | DOM[tweenProp] = function (elem, tweenProp, a, b, v) {
398 | elem.scrollTop = (number(a, b, v)) >> 0
399 | }
400 | } else if (tweenProp === 'opacity') {
401 | if (!(tweenProp in DOM)) {
402 | if (isIE8) {
403 | DOM[tweenProp] = function (elem, tweenProp, a, b, v) {
404 | var st = 'alpha(opacity=', ep = ')'
405 | elem[style].filter = st + ((number(a, b, v) * 100) >> 0) + ep
406 | }
407 | } else {
408 | DOM[tweenProp] = function (elem, tweenProp, a, b, v) {
409 | elem[style].opacity = ((number(a, b, v) * 100) >> 0) / 100
410 | }
411 | }
412 | }
413 | }
414 | return parseFloat(inputValue)
415 | },
416 | colors: function (tweenProp, inputValue) { // colors
417 | if (!(tweenProp in DOM)) {
418 | DOM[tweenProp] = function (elem, tweenProp, a, b, v, o) {
419 | elem[style][tweenProp] = color(a, b, v, o[keepHex])
420 | }
421 | }
422 | return trueColor(inputValue)
423 | }
424 | },
425 |
426 | // process properties for endValues and startValues or one of them
427 | preparePropertiesObject = function (obj, fn) { // this, props object, type: start/end
428 | var propertiesObject = fn === 'start' ? this[valuesStart] : this[valuesEnd],
429 | skewObject = {}, rotateObject = {}, translateObject = {}, transformObject = {}
430 |
431 | for (var x in obj) {
432 | if (transformFunctions[indexOf](x) !== -1) { // transform object gets built here
433 | var prepAxis = ['X', 'Y', 'Z'] // coordinates // translate[x] = pp(x, obj[x]);
434 | if (/^translate(?:[XYZ]|3d)$/.test(x)) { // process translate3d
435 | for (var fnIndex = 0; fnIndex < 3; fnIndex++) {
436 | var translateAxis = prepAxis[fnIndex]
437 | if (/3d/.test(x)) {
438 | translateObject['translate' + translateAxis] = parseProperty.transform.call(this, 'translate' + translateAxis, obj[x][fnIndex])
439 | } else {
440 | translateObject['translate' + translateAxis] = ('translate' + translateAxis in obj) ? parseProperty.transform.call(this, 'translate' + translateAxis, obj['translate' + translateAxis]) : 0
441 | }
442 | }
443 | transformObject['translate'] = translateObject
444 | } else if (/^rotate(?:[XYZ])$|^skew(?:[XY])$/.test(x)) { // process rotation/skew
445 | var objectName = /rotate/.test(x) ? 'rotate' : 'skew',
446 | rotationOrSkew = objectName === 'rotate' ? rotateObject : skewObject
447 | for (var rIndex = 0; rIndex < 3; rIndex++) {
448 | var oneAxis = prepAxis[rIndex]
449 | if (obj[objectName + oneAxis] !== undefined && x !== 'skewZ') {
450 | rotationOrSkew[objectName + oneAxis] = parseProperty.transform.call(this, objectName + oneAxis, obj[objectName + oneAxis])
451 | }
452 | }
453 | transformObject[objectName] = rotationOrSkew
454 | } else if (/(rotate|translate|scale)$/.test(x)) { // process 2d translation / rotation
455 | transformObject[x] = parseProperty.transform.call(this, x, obj[x])
456 | }
457 | propertiesObject[transformProperty] = transformObject
458 | } else {
459 | if (boxModelProps[indexOf](x) !== -1) {
460 | propertiesObject[x] = parseProperty.boxModel.call(this, x, obj[x])
461 | } else if (opacityProp[indexOf](x) !== -1 || x === 'scroll') {
462 | propertiesObject[x] = parseProperty.unitless.call(this, x, obj[x])
463 | } else if (colorProps[indexOf](x) !== -1) {
464 | propertiesObject[x] = parseProperty.colors.call(this, x, obj[x])
465 | } else if (x in parseProperty) { // or any other property from css/ attr / svg / third party plugins
466 | propertiesObject[x] = parseProperty[x].call(this, x, obj[x])
467 | }
468 | }
469 | }
470 | },
471 | reverse = function () {
472 | if (this[options][yoyo]) {
473 | for (var reverseProp in this[valuesEnd]) {
474 | var tmp = this[valuesRepeat][reverseProp]
475 | this[valuesRepeat][reverseProp] = this[valuesEnd][reverseProp]
476 | this[valuesEnd][reverseProp] = tmp
477 | this[valuesStart][reverseProp] = this[valuesRepeat][reverseProp]
478 | }
479 | }
480 | },
481 | close = function () { // when animation is finished reset repeat, yoyo&reversed tweens
482 | if (this[repeat] > 0) { this[options][repeat] = this[repeat] }
483 | if (this[options][yoyo] && this.reversed === true) { reverse.call(this); this.reversed = false }
484 | this[playing] = false
485 |
486 | setTimeout(function () { if (!tweens[length]) { stop() } }, 48) // when all animations are finished, stop ticking after ~3 frames
487 | },
488 | preventScroll = function (eventObj) { // prevent mousewheel or touch events while tweening scroll
489 | var data = body.getAttribute(dataTweening)
490 | if (data && data === 'scroll') { eventObj.preventDefault() }
491 | },
492 | scrollOut = function () { // prevent scroll when tweening scroll
493 | if ('scroll' in this[valuesEnd] && body.getAttribute(dataTweening)) {
494 | document[removeEventListener](touchOrWheel, preventScroll, false)
495 | document[removeEventListener](mouseEnter, preventScroll, false)
496 | body.removeAttribute(dataTweening)
497 | }
498 | },
499 | scrollIn = function () {
500 | if ('scroll' in this[valuesEnd] && !body.getAttribute(dataTweening)) {
501 | document[addEventListener](touchOrWheel, preventScroll, false)
502 | document[addEventListener](mouseEnter, preventScroll, false)
503 | body.setAttribute(dataTweening, 'scroll')
504 | }
505 | },
506 | processEasing = function (fn) {
507 | if (typeof fn === 'function') {
508 | return fn
509 | } else if (typeof fn === 'string') {
510 | return easingFn[fn] // regular Robert Penner Easing Functions
511 | }
512 | },
513 | getStartValues = function () { // stack transform props for .to() chains
514 | var startValues = {}, currentStyle = getInlineStyle(this[element]),
515 | degreeProps = ['rotate', 'skew'], startAxis = ['X', 'Y', 'Z']
516 |
517 | for (var tweenProperty in this[valuesStart]) {
518 | if (transformFunctions[indexOf](tweenProperty) !== -1) {
519 | var r2d = (/(rotate|translate|scale)$/.test(tweenProperty))
520 | if (/translate/.test(tweenProperty) && tweenProperty !== 'translate') {
521 | startValues['translate3d'] = currentStyle['translate3d'] || defaultPropsValues[tweenProperty]
522 | } else if (r2d) { // 2d transforms
523 | startValues[tweenProperty] = currentStyle[tweenProperty] || defaultPropsValues[tweenProperty]
524 | } else if (!r2d && /rotate|skew/.test(tweenProperty)) { // all angles
525 | for (var degIndex = 0; degIndex < 2; degIndex++) {
526 | for (var axisIndex = 0; axisIndex < 3; axisIndex++) {
527 | var s = degreeProps[degIndex] + startAxis[axisIndex]
528 | if (transformFunctions[indexOf](s) !== -1 && (s in this[valuesStart])) { startValues[s] = currentStyle[s] || defaultPropsValues[s] }
529 | }
530 | }
531 | }
532 | } else {
533 | if (tweenProperty !== 'scroll') {
534 | if (tweenProperty === 'opacity' && isIE8) { // handle IE8 opacity
535 | var currentOpacity = getCurrentStyle(this[element], 'filter')
536 | startValues['opacity'] = typeof currentOpacity === 'number' ? currentOpacity : defaultPropsValues['opacity']
537 | } else {
538 | if (coreProps[indexOf](tweenProperty) !== -1) {
539 | startValues[tweenProperty] = getCurrentStyle(this[element], tweenProperty) || d[tweenProperty]
540 | } else { // plugins register here
541 | startValues[tweenProperty] = tweenProperty in prepareStart ? prepareStart[tweenProperty].call(this, tweenProperty, this[valuesStart][tweenProperty]) : 0
542 | }
543 | }
544 | } else {
545 | startValues[tweenProperty] = this[element] === scrollContainer ? (g.pageYOffset || scrollContainer.scrollTop) : this[element].scrollTop
546 | }
547 | }
548 | }
549 | for (var currentProperty in currentStyle) { // also add to startValues values from previous tweens
550 | if (transformFunctions[indexOf](currentProperty) !== -1 && (!(currentProperty in this[valuesStart]))) {
551 | startValues[currentProperty] = currentStyle[currentProperty] || defaultPropsValues[currentProperty]
552 | }
553 | }
554 |
555 | this[valuesStart] = {}
556 | preparePropertiesObject.call(this, startValues, 'start')
557 |
558 | if (transformProperty in this[valuesEnd]) { // let's stack transform
559 | for (var sp in this[valuesStart][transformProperty]) { // sp is the object corresponding to the transform function objects translate / rotate / skew / scale
560 | if (sp !== 'perspective') {
561 | if (typeof this[valuesStart][transformProperty][sp] === 'object') {
562 | for (var spp in this[valuesStart][transformProperty][sp]) { // 3rd level
563 | if (typeof this[valuesEnd][transformProperty][sp] === 'undefined') { this[valuesEnd][transformProperty][sp] = {} }
564 | if (typeof this[valuesStart][transformProperty][sp][spp] === 'number' && typeof this[valuesEnd][transformProperty][sp][spp] === 'undefined') {
565 | this[valuesEnd][transformProperty][sp][spp] = this[valuesStart][transformProperty][sp][spp]
566 | }
567 | }
568 | } else if (typeof this[valuesStart][transformProperty][sp] === 'number') {
569 | if (typeof this[valuesEnd][transformProperty][sp] === 'undefined') { // scale
570 | this[valuesEnd][transformProperty][sp] = this[valuesStart][transformProperty][sp]
571 | }
572 | }
573 | }
574 | }
575 | }
576 | }
577 |
578 | // core easing functions
579 | var easingFn = g.Easing = {}
580 | easingFn.linear = function (t) { return t }
581 | easingFn.easingSinusoidalIn = function (t) { return -Math.cos(t * Math.PI / 2) + 1 }
582 | easingFn.easingSinusoidalOut = function (t) { return Math.sin(t * Math.PI / 2) }
583 | easingFn.easingSinusoidalInOut = function (t) { return -0.5 * (Math.cos(Math.PI * t) - 1) }
584 | easingFn.easingQuadraticIn = function (t) { return t * t }
585 | easingFn.easingQuadraticOut = function (t) { return t * (2 - t) }
586 | easingFn.easingQuadraticInOut = function (t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t }
587 | easingFn.easingCubicIn = function (t) { return t * t * t }
588 | easingFn.easingCubicOut = function (t) { return (--t) * t * t + 1 }
589 | easingFn.easingCubicInOut = function (t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1 }
590 | easingFn.easingQuarticIn = function (t) { return t * t * t * t }
591 | easingFn.easingQuarticOut = function (t) { return 1 - (--t) * t * t * t }
592 | easingFn.easingQuarticInOut = function (t) { return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t }
593 | easingFn.easingQuinticIn = function (t) { return t * t * t * t * t }
594 | easingFn.easingQuinticOut = function (t) { return 1 + (--t) * t * t * t * t }
595 | easingFn.easingQuinticInOut = function (t) { return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t }
596 | easingFn.easingCircularIn = function (t) { return -(Math.sqrt(1 - (t * t)) - 1) }
597 | easingFn.easingCircularOut = function (t) { return Math.sqrt(1 - (t = t - 1) * t) }
598 | easingFn.easingCircularInOut = function (t) { return ((t *= 2) < 1) ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1) }
599 | easingFn.easingExponentialIn = function (t) { return Math.pow(2, 10 * (t - 1)) - 0.001 }
600 | easingFn.easingExponentialOut = function (t) { return 1 - Math.pow(2, -10 * t) }
601 | easingFn.easingExponentialInOut = function (t) { return (t *= 2) < 1 ? 0.5 * Math.pow(2, 10 * (t - 1)) : 0.5 * (2 - Math.pow(2, -10 * (t - 1))) }
602 | easingFn.easingBackIn = function (t) { var s = 1.70158; return t * t * ((s + 1) * t - s) }
603 | easingFn.easingBackOut = function (t) { var s = 1.70158; return --t * t * ((s + 1) * t + s) + 1 }
604 | easingFn.easingBackInOut = function (t) { var s = 1.70158 * 1.525; if ((t *= 2) < 1) return 0.5 * (t * t * ((s + 1) * t - s)); return 0.5 * ((t -= 2) * t * ((s + 1) * t + s) + 2) }
605 | easingFn.easingElasticIn = function (t) {
606 | var s, _kea = 0.1, _kep = 0.4
607 | if (t === 0) return 0; if (t === 1) return 1
608 | if (!_kea || _kea < 1) { _kea = 1; s = _kep / 4 } else s = _kep * Math.asin(1 / _kea) / Math.PI * 2
609 | return -(_kea * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * Math.PI * 2 / _kep))
610 | }
611 | easingFn.easingElasticOut = function (t) {
612 | var s, _kea = 0.1, _kep = 0.4
613 | if (t === 0) return 0; if (t === 1) return 1
614 | if (!_kea || _kea < 1) { _kea = 1; s = _kep / 4 } else s = _kep * Math.asin(1 / _kea) / Math.PI * 2
615 | return (_kea * Math.pow(2, -10 * t) * Math.sin((t - s) * Math.PI * 2 / _kep) + 1)
616 | }
617 | easingFn.easingElasticInOut = function (t) {
618 | var s, _kea = 0.1, _kep = 0.4
619 | if (t === 0) return 0; if (t === 1) return 1
620 | if (!_kea || _kea < 1) { _kea = 1; s = _kep / 4 } else s = _kep * Math.asin(1 / _kea) / Math.PI * 2
621 | if ((t *= 2) < 1) return -0.5 * (_kea * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * Math.PI * 2 / _kep))
622 | return _kea * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * Math.PI * 2 / _kep) * 0.5 + 1
623 | }
624 | easingFn.easingBounceIn = function (t) { return 1 - easingFn.easingBounceOut(1 - t) }
625 | easingFn.easingBounceOut = function (t) {
626 | if (t < (1 / 2.75)) { return 7.5625 * t * t } else if (t < (2 / 2.75)) { return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75 } else if (t < (2.5 / 2.75)) { return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375 } else { return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375 }
627 | }
628 | easingFn.easingBounceInOut = function (t) { if (t < 0.5) return easingFn.easingBounceIn(t * 2) * 0.5; return easingFn.easingBounceOut(t * 2 - 1) * 0.5 + 0.5 }
629 |
630 | // single Tween object construct
631 | var Tween = function (targetElement, startObject, endObject, optionsObj) {
632 | this[element] = 'scroll' in endObject && (targetElement === undefined || targetElement === null) ? scrollContainer : targetElement // element animation is applied to
633 |
634 | this[playing] = false
635 | this.reversed = false
636 | this.paused = false
637 |
638 | this._startTime = null
639 | this._pauseTime = null
640 |
641 | this._startFired = false
642 | this[options] = {}; for (var o in optionsObj) { this[options][o] = optionsObj[o] }
643 | this[options].rpr = optionsObj.rpr || false // internal option to process inline/computed style at start instead of init true/false
644 |
645 | this[valuesRepeat] = {} // internal valuesRepeat
646 | this[valuesEnd] = {} // valuesEnd
647 | this[valuesStart] = {} // valuesStart
648 |
649 | preparePropertiesObject.call(this, endObject, 'end') // valuesEnd
650 | if (this[options].rpr) { this[valuesStart] = startObject } else { preparePropertiesObject.call(this, startObject, 'start') } // valuesStart
651 |
652 | if (this[options].perspective !== undefined && transformProperty in this[valuesEnd]) { // element transform perspective
653 | var perspectiveString = 'perspective(' + parseInt(this[options].perspective) + 'px)'
654 | this[valuesEnd][transformProperty].perspective = perspectiveString
655 | }
656 |
657 | for (var repeatProp in this[valuesEnd]) {
658 | if (repeatProp in crossCheck && !this[options].rpr) crossCheck[repeatProp].call(this) // this is where we do the valuesStart and valuesEnd check for fromTo() method
659 | }
660 |
661 | this[options][chain] = [] // chained Tweens
662 | this[options][easing] = processEasing(optionsObj[easing]) || easingFn[defaultOptions[easing]] || easingFn['linear'] // you can only set a core easing function as default
663 | this[options][repeat] = optionsObj[repeat] || defaultOptions[repeat]
664 | this[options][repeatDelay] = optionsObj[repeatDelay] || defaultOptions[repeatDelay]
665 | this[options][yoyo] = optionsObj[yoyo] || defaultOptions[yoyo]
666 | this[options][duration] = optionsObj[duration] || defaultOptions[duration] // duration option | default
667 | this[options][delay] = optionsObj[delay] || defaultOptions[delay] // delay option | default
668 |
669 | this[repeat] = this[options][repeat] // we cache the number of repeats to be able to put it back after all cycles finish
670 | },
671 | // tween control and chain
672 | TweenProto = Tween.prototype = {
673 | // queue tween object to main frame update
674 | start: function (t) { // move functions that use the ticker outside the prototype to be in the same scope with it
675 | scrollIn.call(this)
676 |
677 | if (this[options].rpr) { getStartValues.apply(this) } // on start we reprocess the valuesStart for TO() method
678 | perspective.apply(this) // apply the perspective and transform origin
679 |
680 | for (var endProp in this[valuesEnd]) {
681 | if (endProp in crossCheck && this[options].rpr) crossCheck[endProp].call(this) // this is where we do the valuesStart and valuesEnd check for to() method
682 | this[valuesRepeat][endProp] = this[valuesStart][endProp]
683 | }
684 |
685 | // now it's a good time to start
686 | tweens.push(this)
687 | this[playing] = true
688 | this.paused = false
689 | this._startFired = false
690 | this._startTime = t || time.now()
691 | this._startTime += this[options][delay]
692 |
693 | if (!this._startFired) {
694 | if (this[options].start) { this[options].start.call() }
695 | this._startFired = true
696 | }
697 | !tick && ticker()
698 | return this
699 | },
700 | play: function () {
701 | if (this.paused && this[playing]) {
702 | this.paused = false
703 | if (this[options].resume) { this[options].resume.call() }
704 | this._startTime += time.now() - this._pauseTime
705 | add(this)
706 | !tick && ticker() // restart ticking if stopped
707 | }
708 | return this
709 | },
710 | resume: function () { return this.play() },
711 | pause: function () {
712 | if (!this.paused && this[playing]) {
713 | remove(this)
714 | this.paused = true
715 | this._pauseTime = time.now()
716 | if (this[options].pause) { this[options].pause.call() }
717 | }
718 | return this
719 | },
720 | stop: function () {
721 | if (!this.paused && this[playing]) {
722 | remove(this)
723 | this[playing] = false
724 | this.paused = false
725 | scrollOut.call(this)
726 |
727 | if (this[options].stop) { this[options].stop.call() }
728 | this.stopChainedTweens()
729 | close.call(this)
730 | }
731 | return this
732 | },
733 | chain: function () { this[options][chain] = arguments; return this },
734 | stopChainedTweens: function () {
735 | for (var i = 0, ctl = this[options][chain][length]; i < ctl; i++) {
736 | this[options][chain][i].stop()
737 | }
738 | }
739 | },
740 |
741 | // the multi elements Tween constructs
742 | TweensTO = function (els, vE, o) { // .to
743 | this.tweens = []; var optionsObj = []
744 | for (var i = 0, tl = els[length]; i < tl; i++) {
745 | optionsObj[i] = o || {}; o[delay] = o[delay] || defaultOptions[delay]
746 | optionsObj[i][delay] = i > 0 ? o[delay] + (o[offset] || defaultOptions[offset]) : o[delay]
747 | this.tweens.push(to(els[i], vE, optionsObj[i]))
748 | }
749 | },
750 | TweensFT = function (els, vS, vE, o) { // .fromTo
751 | this.tweens = []; var optionsObj = []
752 | for (var i = 0, l = els[length]; i < l; i++) {
753 | optionsObj[i] = o || {}; o[delay] = o[delay] || defaultOptions[delay]
754 | optionsObj[i][delay] = i > 0 ? o[delay] + (o[offset] || defaultOptions[offset]) : o[delay]
755 | this.tweens.push(fromTo(els[i], vS, vE, optionsObj[i]))
756 | }
757 | },
758 | ws = TweensTO.prototype = TweensFT.prototype = {
759 | start: function (t) {
760 | t = t || time.now()
761 | for (var i = 0, tl = this.tweens[length]; i < tl; i++) {
762 | this.tweens[i].start(t)
763 | }
764 | return this
765 | },
766 | stop: function () { for (var i = 0, tl = this.tweens[length]; i < tl; i++) { this.tweens[i].stop() } return this },
767 | pause: function () { for (var i = 0, tl = this.tweens[length]; i < tl; i++) { this.tweens[i].pause() } return this },
768 | chain: function () { this.tweens[this.tweens[length] - 1][options][chain] = arguments; return this },
769 | play: function () { for (var i = 0, tl = this.tweens[length]; i < tl; i++) { this.tweens[i].play() } return this },
770 | resume: function () { return this.play() }
771 | },
772 |
773 | // main methods
774 | to = function (element, endObject, optionsObj) {
775 | optionsObj = optionsObj || {}; optionsObj.rpr = true
776 | return new Tween(selector(element), endObject, endObject, optionsObj)
777 | },
778 | fromTo = function (element, startObject, endObject, optionsObj) {
779 | optionsObj = optionsObj || {}
780 | return new Tween(selector(element), startObject, endObject, optionsObj)
781 | },
782 |
783 | // multiple elements tweening
784 | allTo = function (elements, endObject, optionsObj) {
785 | return new TweensTO(selector(elements, true), endObject, optionsObj)
786 | },
787 | allFromTo = function (elements, startObject, endObject, optionsObj) {
788 | return new TweensFT(selector(elements, true), startObject, endObject, optionsObj)
789 | }
790 |
791 | return { // export core methods to public for plugins
792 | property: property,
793 | getPrefix: getPrefix,
794 | selector: selector,
795 | processEasing: processEasing, // utils
796 | defaultOptions: defaultOptions, // default tween options since 1.6.1
797 | to: to,
798 | fromTo: fromTo,
799 | allTo: allTo,
800 | allFromTo: allFromTo, // main methods
801 | ticker: ticker,
802 | tick: tick,
803 | tweens: tweens,
804 | update: update,
805 | dom: DOM, // update
806 | parseProperty: parseProperty,
807 | prepareStart: prepareStart,
808 | crossCheck: crossCheck,
809 | Tween: Tween, // property parsing & preparation | Tween | crossCheck
810 | truD: trueDimension,
811 | truC: trueColor,
812 | rth: rgbToHex,
813 | htr: hexToRGB,
814 | getCurrentStyle: getCurrentStyle // property parsing
815 | }
816 | }))
817 |
--------------------------------------------------------------------------------