Compare commits
290 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae0b200694 | ||
|
|
91fb7aad8f | ||
|
|
3835b6e95c | ||
|
|
5c8b75f15b | ||
|
|
8f5c58195e | ||
|
|
0dac43bc88 | ||
|
|
a17bacbd58 | ||
|
|
2a5bac2bb3 | ||
|
|
e5456b86e9 | ||
|
|
d96d08a36b | ||
|
|
0290fa67cb | ||
|
|
5dfbf91ce3 | ||
|
|
c786e062c0 | ||
|
|
cd0898b67f | ||
|
|
b70d46d387 | ||
|
|
f56e19369a | ||
|
|
b36f26195c | ||
|
|
ebd86bf9e3 | ||
|
|
b0f6220413 | ||
|
|
0efd9a10e4 | ||
|
|
2a309434c1 | ||
|
|
a1f59fe181 | ||
|
|
c011a9368b | ||
|
|
933d61de19 | ||
|
|
bfc3fabc92 | ||
|
|
14585d7a51 | ||
|
|
2ad17fdd00 | ||
|
|
0b7fd91bab | ||
|
|
85d9c09ede | ||
|
|
7a782229dd | ||
|
|
730583caff | ||
|
|
0528e3a0af | ||
|
|
b0a6495748 | ||
|
|
b152aa8fa6 | ||
|
|
65a56cd338 | ||
|
|
64ac54a4d0 | ||
|
|
da4a2108f8 | ||
|
|
6bfa00da75 | ||
|
|
ce0a5192b3 | ||
|
|
072a61533c | ||
|
|
9d9e02fa65 | ||
|
|
3be6838993 | ||
|
|
610ae90742 | ||
|
|
ffa69326af | ||
|
|
000af8a625 | ||
|
|
3ce5b8b590 | ||
|
|
591871079b |
||
|
|
0e2da1baa1 | ||
|
|
ac5c5355b7 | ||
|
|
2119e600ef | ||
|
|
f1dbb2d996 | ||
|
|
af00968b58 | ||
|
|
be367debe0 | ||
|
|
5603a3bc8e | ||
|
|
4d5c37e958 | ||
|
|
0e7e4ce817 | ||
|
|
fed9662776 | ||
|
|
62d5ae1f83 | ||
|
|
12ad62fd09 | ||
|
|
e6a776770d | ||
|
|
95947f5af8 | ||
|
|
7a39544cf0 | ||
|
|
645089f77a | ||
|
|
f3d0789447 | ||
|
|
0435d00b11 | ||
|
|
b3ba7299a0 | ||
|
|
3cd0db546f | ||
|
|
c8b6d85ea0 | ||
|
|
9212dcaeec | ||
|
|
db2595d8d0 | ||
|
|
00fbc38624 | ||
|
|
c16efd44d6 | ||
|
|
c753ade57c | ||
|
|
7d7bd32572 | ||
|
|
7105d48d41 | ||
|
|
f296ffcd56 | ||
|
|
ccd505f6d8 | ||
|
|
fafbf484df | ||
|
|
207597efe7 | ||
|
|
c48200ae47 | ||
|
|
1434ac02fb | ||
|
|
3c829c3475 | ||
|
|
65278aed53 | ||
|
|
4b78605396 | ||
|
|
9cc657b7bf | ||
|
|
c36e4d1967 | ||
|
|
e0d52535f6 | ||
|
|
73adb8344f | ||
|
|
f85ecef387 | ||
|
|
92a37f453b | ||
|
|
751c2e5263 | ||
|
|
ba6c529146 | ||
|
|
16a3eb387c | ||
|
|
40fd867115 | ||
|
|
ba91cd6630 | ||
|
|
2cb0800aed | ||
|
|
3215d770b4 | ||
|
|
38fcf9c127 | ||
|
|
a8ca9a5317 | ||
|
|
b6c64774aa | ||
|
|
4b2cfda1c2 | ||
|
|
e0bc5cf8a2 | ||
|
|
132a6246c0 | ||
|
|
9348792e2d | ||
|
|
0433d479d7 | ||
|
|
eee3554bd0 | ||
|
|
0e917b933b | ||
|
|
842f12bcf1 | ||
|
|
b8fc991476 | ||
|
|
095078005f | ||
|
|
fc75dd130f | ||
|
|
308ee60bf5 | ||
|
|
2679a232be | ||
|
|
67c47a6f08 | ||
|
|
70ee2a448a | ||
|
|
1a44fbe465 | ||
|
|
a92a45f77f | ||
|
|
c3b06308c3 | ||
|
|
d92fed514e | ||
|
|
032f047c6c | ||
|
|
f01ed026a6 | ||
|
|
72a915c051 | ||
|
|
7aa15a43b5 | ||
|
|
bda5756889 | ||
|
|
545e253a30 | ||
|
|
124a0521d1 | ||
|
|
de86e786c4 | ||
|
|
de2fe03985 | ||
|
|
21210c2dd7 | ||
|
|
72dea56f33 | ||
|
|
a6c0be41df | ||
|
|
0b8d77c19b | ||
|
|
35a4cdb8c0 | ||
|
|
e61bc99ec4 | ||
|
|
0bebda1eff | ||
|
|
e165c10d40 | ||
|
|
927bb7e9c0 | ||
|
|
6b5623b20a | ||
|
|
ccb5e6ba73 | ||
|
|
eb9926c028 | ||
|
|
f22be9f8b4 | ||
|
|
1b061eb9a3 | ||
|
|
975216e633 | ||
|
|
b267bd0422 | ||
|
|
ff5d6d139b | ||
|
|
a16720199a | ||
|
|
f2eff7ddbe | ||
|
|
877005df3b | ||
|
|
3d7f6721b9 | ||
|
|
97b4fe4dcf | ||
|
|
3a1f0b20e7 | ||
|
|
5947a72e74 | ||
|
|
c83fbc8862 | ||
|
|
576ce620df | ||
|
|
1fb54ed2d2 | ||
|
|
b67960952e | ||
|
|
728af0a801 | ||
|
|
2960ff6d73 | ||
|
|
1288e1ec89 | ||
|
|
5e6b933bec | ||
|
|
4b42fa40e4 | ||
|
|
cc332f0745 | ||
|
|
b83bb95a1e | ||
|
|
56a0045f89 | ||
|
|
d1e016185b | ||
|
|
c6e7caabc6 | ||
|
|
df9554252c | ||
|
|
9cb1753073 | ||
|
|
ed9f814594 | ||
|
|
f631185602 | ||
|
|
c37c404dfe | ||
|
|
b2c7ab6564 | ||
|
|
e49bce0e20 | ||
|
|
1fbfbc58c7 | ||
|
|
3819cd0f3a | ||
|
|
ee713e86c4 | ||
|
|
a30eab2ff9 | ||
|
|
3e1eb06d26 | ||
|
|
984fa6a5f1 | ||
|
|
f46e780271 | ||
|
|
645a0027b8 | ||
|
|
67c441ccab | ||
|
|
fa5d69ed3e | ||
|
|
362293626f | ||
|
|
ef5da213c1 | ||
|
|
6c8b49ea8a | ||
|
|
f3414f6551 | ||
|
|
a514d71f61 | ||
|
|
571b96e2a9 | ||
|
|
4faa433429 | ||
|
|
7873233e39 | ||
|
|
028ed99e64 | ||
|
|
10d47b89da | ||
|
|
4fca28e269 | ||
|
|
dc17bd3ed5 | ||
|
|
053a1bc2f9 | ||
|
|
e33733f4f3 | ||
|
|
92060dcaab | ||
|
|
cb48bf3c90 | ||
|
|
a1e983c8a2 | ||
|
|
b24989dd71 | ||
|
|
63ab15de08 | ||
|
|
40fb142db5 | ||
|
|
01189cb038 | ||
|
|
ba5a405627 | ||
|
|
688b036437 | ||
|
|
ba21f97e34 | ||
|
|
f4e58a5126 | ||
|
|
162803f6c8 | ||
|
|
f4576d4bca | ||
|
|
7527628aef | ||
|
|
6176a75fe1 | ||
|
|
5bbb709361 | ||
|
|
2564472f53 | ||
|
|
97b6608392 | ||
|
|
92f8dcc338 | ||
|
|
49a418b24e | ||
|
|
d24f73d811 | ||
|
|
35dc80161b | ||
|
|
41e87cc4b2 | ||
|
|
bf2574d082 | ||
|
|
aa59078591 | ||
|
|
83ab68ad74 | ||
|
|
afdfa1ae49 | ||
|
|
3a7857bbe5 | ||
|
|
dc820c5654 | ||
|
|
320cc59b05 | ||
|
|
05bad2c336 | ||
|
|
b31ed62fe6 | ||
|
|
ca7fc23fcc | ||
|
|
b3be076328 | ||
|
|
859e8a7fb2 | ||
|
|
b1550f1111 | ||
|
|
12512274aa | ||
|
|
057cabde2a | ||
|
|
0276f0ef74 | ||
|
|
2ebb6df047 | ||
|
|
36f97142fe | ||
|
|
acfce66a51 | ||
|
|
2075084410 | ||
|
|
eb73a1ba4f | ||
|
|
e181788367 | ||
|
|
e8e2698ea2 | ||
|
|
32a741ab20 | ||
|
|
480ece6a9c | ||
|
|
026f4201ae | ||
|
|
6872923046 | ||
|
|
40f121ab8e | ||
|
|
934d666859 | ||
|
|
976fc30493 | ||
|
|
6181d45689 | ||
|
|
e9a4daa8be | ||
|
|
50291a49a5 | ||
|
|
462a4d254b | ||
|
|
189241b87c | ||
|
|
e2aa72e14b | ||
|
|
37348c3609 | ||
|
|
5c80b15fb7 | ||
|
|
b041dfea55 | ||
|
|
0bde518b4f | ||
|
|
03b1511580 | ||
|
|
ce5a8c83b9 | ||
|
|
402edc2b35 | ||
|
|
3c7d277ca1 | ||
|
|
8e21120720 | ||
|
|
ef92d0938b | ||
|
|
a6dc3fd339 | ||
|
|
ecd63491e3 | ||
|
|
69f7757ce0 | ||
|
|
b8e7af39fa | ||
|
|
b99fb1b38c | ||
|
|
ad727aad34 | ||
|
|
15df42234c | ||
|
|
6d60e6d436 | ||
|
|
ef8b8d1726 | ||
|
|
dafded11c5 | ||
|
|
e0ea467152 | ||
|
|
5525e0774d | ||
|
|
bffc33ee1e | ||
|
|
b052b7f2f4 | ||
|
|
ae8d72159e | ||
|
|
e1acdfd42d | ||
|
|
9007ce79ed | ||
|
|
5aea8340fe | ||
|
|
587f4c0de2 | ||
|
|
fa56bbfbf4 | ||
|
|
5e5e95108c | ||
|
|
9ca0ba1e75 | ||
|
|
5d58a5bffd | ||
|
|
25cc86e192 |
41
.eslintrc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"extends": [
|
||||
// Extend the airbnb eslint config
|
||||
"airbnb-base"
|
||||
// Vue
|
||||
// "plugin:vue/vue3-recommended"
|
||||
],
|
||||
// "parser": "vue-eslint-parser",
|
||||
// "parser": "eslint-plugin-vue",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
// ESLint will not look in parent folders for eslint configs
|
||||
"root": false,
|
||||
// An environment defines global variables that are predefined.
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
// Rule overrides
|
||||
"rules": {
|
||||
// Disable no-restricted-globals for global objects
|
||||
"no-restricted-globals": 0,
|
||||
// Disable no-params-reassign for properties
|
||||
// "no-param-reassign": ["error", { "props": false }],
|
||||
// Allow strict mode (we are not dealing with modules)
|
||||
// "strict": [0],
|
||||
// Allow use of "private methods" - impossible to satisfy
|
||||
"no-underscore-dangle": 0
|
||||
// Disable alert rule till we have a CE in place
|
||||
// "no-alert": 0
|
||||
// Allow extensions on imports
|
||||
// "import/extensions": 0,
|
||||
// Allow exporting mutable 'let' binding
|
||||
// "import/no-mutable-exports": 0,
|
||||
// Allow no named as default / member
|
||||
// "import/no-named-as-default": 0,
|
||||
// "import/no-named-as-default-member": 0
|
||||
}
|
||||
}
|
||||
8
.gitignore
vendored
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
node_modules
|
||||
package-lock.json
|
||||
experiments
|
||||
node_modules/
|
||||
experiments/
|
||||
.npmignore
|
||||
package-lock.json
|
||||
5
.npmignore
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
node_modules/
|
||||
demo/
|
||||
experiments/
|
||||
package-lock.json
|
||||
.gitignore
|
||||
22
LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 thednp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
62
README.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# KUTE.js
|
||||
|
||||
A modern JavaScript animation engine built on ES6+ standards with strong TypeScript definitions and most essential features for the web with easy to use methods to set up high performance, cross-browser animations. The focus is code quality, flexibility, performance and size.
|
||||
|
||||
[](https://www.npmjs.com/package/kute.js)
|
||||
[](http://npm-stat.com/charts.html?package=kute.js)
|
||||
[](https://www.jsdelivr.com/package/npm/kute.js)
|
||||
[](https://cdnjs.com/libraries/kute.js)
|
||||
|
||||
KUTE.js packs a series of components for presentation attributes, SVG transform, draw SVG strokes and path morphing, text string write up or number countdowns, plus additional CSS properties like colors, border-radius or typographic properties.
|
||||
|
||||
For components documentation, examples and other cool tips, check the [demo](http://thednp.github.io/kute.js/).
|
||||
|
||||
|
||||
# Components
|
||||
KUTE.js includes 18 components, but not all of them are bundled with the default distribution package:
|
||||
|
||||
* [backgroundPosition](http://thednp.github.io/kute.js/backgroundPosition.html) - enables the animation for the `backgroundPosition` CSS property
|
||||
* [borderRadius](http://thednp.github.io/kute.js/borderRadius.html) - enables the animation for all the **borderRadius** properties
|
||||
* [boxModel](http://thednp.github.io/kute.js/boxModel.html) - enables the animation for the **boxModel** properties like `top` , `left`, `width`, etc
|
||||
* [clipProperty](http://thednp.github.io/kute.js/clipProperty.html) - enables the animation for the `clip` property
|
||||
* [colorProperties](http://thednp.github.io/kute.js/colorProperties.html) - enables the animation for the **color** properties like `color`, `backgroundColor`
|
||||
* [filterEffects](http://thednp.github.io/kute.js/filterEffects.html) - enables the animation for the `filter` property
|
||||
* [htmlAttributes](http://thednp.github.io/kute.js/htmlAttributes.html) - enables the animation for any numeric as well as some color based **HTML Attributes**
|
||||
* [opacityProperty](http://thednp.github.io/kute.js/opacityProperty.html) - enables the animation for the `opacity` property
|
||||
* [scrollProperty](http://thednp.github.io/kute.js/scrollProperty.html) - enables the animation for the window/Element `scrollTop` Object property
|
||||
* [shadowProperties](http://thednp.github.io/kute.js/shadowProperties.html) - enables the animation for the **shadowProperties** properties: `textShadow` & `boxShadow`
|
||||
* [svgCubicMorph](http://thednp.github.io/kute.js/svgCubicMorph.html) - enables the animation for the `d` Presentation Attribute of the `<path>` SVGElement targets; this implements some [Raphael.js](https://dmitrybaranovskiy.github.io/raphael/) functionality
|
||||
* [svgMorph](http://thednp.github.io/kute.js/svgMorph.html) - enables the animation for the `d` Presentation Attribute of the `<path>` SVGElement targets; this component implements some [D3.js](https://github.com/d3/d3) and [flubber](https://github.com/veltman/flubber) functionality
|
||||
* [svgDraw](http://thednp.github.io/kute.js/svgDraw.html) - enables the animation for the `strokeDasharray` and `strokeDashoffset` CSS properties specific to `<path>` SVGElement
|
||||
* [svgTransform](http://thednp.github.io/kute.js/svgTransform.html) - enables the animation for the `transform` presentation attribute
|
||||
* [textProperties](http://thednp.github.io/kute.js/textProperties.html) - enables the animation for numeric `HTMLTextElement` related CSS properties like `fontSize` or `letterSpacing`
|
||||
* [textWrite](http://thednp.github.io/kute.js/textWrite.html) - enables the animation for the content of various strings
|
||||
* [transformFunctions](http://thednp.github.io/kute.js/transformFunctions.html) - enables the animation for the `transform` CSS3 property, the default component bundled with the official build
|
||||
* transformLegacy - enables the animation for the `transform` CSS3 property on legacy browsers IE9+, not included with the official build, but can be used in your custom builds
|
||||
* [transformMatrix](http://thednp.github.io/kute.js/transformMatrix.html) - enables the animation for the `transform` CSS3 property; this component implements `DOMMatrix()` API and is super light
|
||||
|
||||
All above mentioned components have a BASE version which doesn't include value processing, and their purpose is to provide a way to ship your super light version of your application.
|
||||
|
||||
|
||||
# Wiki
|
||||
For a complete developer guide, usage and stuff like npm, visit [the wiki](https://github.com/thednp/kute.js/wiki).
|
||||
|
||||
|
||||
# Browser Support
|
||||
KUTE.js is redeveloped for maximum performance on modern browsers. Some legacy browsers might some help, so give them a small polyfill set with most essential features required by KUTE.js to work, powered by [minifill](https://github.com/thednp/minifill), try it. For broader projects you might want to consider <a href="https://cdn.polyfill.io/v2/docs/">polyfills</a>.
|
||||
|
||||
|
||||
# Special Thanks
|
||||
* [Mike Bostock](https://bost.ocks.org/mike/) for his awesome [D3.js](https://github.com/d3/d3), one of the sources for our reworked [SVGMorph](http://thednp.github.io/kute.js/svgMorph.html) component.
|
||||
* [Noah Veltman](https://github.com/veltman) for his awesome [flubber](https://github.com/veltman/flubber), another one of the sources for the SVGMorph component.
|
||||
* [Andrew Willems](https://stackoverflow.com/users/5218951/andrew-willems) for his awesome [Stackoverflow answer](https://stackoverflow.com/questions/35560989/javascript-how-to-determine-a-svg-path-draw-direction) resulting in the creation of our [SVGCubicMorph](http://thednp.github.io/kute.js/svgCubicMorph.html) component.
|
||||
* [Dmitry Baranovskiy](https://dmitry.baranovskiy.com/) for his awesome [Raphael.js](https://dmitrybaranovskiy.github.io/raphael/), another source for our SVGCubicMorph component.
|
||||
* [@dalisoft](https://github.com/dalisoft) contributed a great deal to the performance and functionality of previous versions of KUTE.js.
|
||||
|
||||
|
||||
# Contributions
|
||||
* [Contributors & Collaborators](https://github.com/thednp/kute.js/graphs/contributors)
|
||||
|
||||
|
||||
# License
|
||||
[MIT License](https://github.com/thednp/kute.js/blob/master/LICENSE)
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 997 B After Width: | Height: | Size: 997 B |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* KUTE.js Base v2.2.2 (http://thednp.github.io/kute.js)
|
||||
* KUTE.js Base v2.2.3 (http://thednp.github.io/kute.js)
|
||||
* Copyright 2015-2021 © thednp
|
||||
* Licensed under MIT (https://github.com/thednp/kute.js/blob/master/LICENSE)
|
||||
*/
|
||||
|
|
@ -876,7 +876,7 @@
|
|||
return new TweenConstructor(selector(element), startObject, endObject, options);
|
||||
}
|
||||
|
||||
var version = "2.2.2";
|
||||
var version = "2.2.3";
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* KUTE.js Extra v2.2.2 (http://thednp.github.io/kute.js)
|
||||
* KUTE.js Extra v2.2.3 (http://thednp.github.io/kute.js)
|
||||
* Copyright 2015-2021 © thednp
|
||||
* Licensed under MIT (https://github.com/thednp/kute.js/blob/master/LICENSE)
|
||||
*/
|
||||
|
|
@ -5689,7 +5689,7 @@
|
|||
Components[component] = new AnimationDevelopment(compOps);
|
||||
});
|
||||
|
||||
var version = "2.2.2";
|
||||
var version = "2.2.3";
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
4
src/kute.min.js → demo/src/kute.min.js
vendored
4621
dist/kute.esm.js
vendored
Normal file
2
dist/kute.esm.min.js
vendored
Normal file
4675
dist/kute.js
vendored
Normal file
2
dist/kute.min.js
vendored
Normal file
140
dist/polyfill.js
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*!
|
||||
* KUTE.js Polyfill v2.1.1-alpha1 (http://thednp.github.io/kute.js)
|
||||
* Copyright 2015-2021 © thednp
|
||||
* Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
|
||||
*/
|
||||
"use strict";
|
||||
if (!Array.from) {
|
||||
Array.from = (function () {
|
||||
var toStr = Object.prototype.toString;
|
||||
var isCallable = function (fn) {
|
||||
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
|
||||
};
|
||||
var toInteger = function (value) {
|
||||
var number = Number(value);
|
||||
if (isNaN(number)) { return 0; }
|
||||
if (number === 0 || !isFinite(number)) { return number; }
|
||||
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
|
||||
};
|
||||
var maxSafeInteger = Math.pow(2, 53) - 1;
|
||||
var toLength = function (value) {
|
||||
var len = toInteger(value);
|
||||
return Math.min(Math.max(len, 0), maxSafeInteger);
|
||||
};
|
||||
|
||||
return function from(arrayLike/*, mapFn, thisArg */) {
|
||||
var C = this, items = Object(arrayLike);
|
||||
if (arrayLike == null) {
|
||||
throw new TypeError('Array.from requires an array-like object - not null or undefined');
|
||||
}
|
||||
var mapFn = arguments.length > 1 ? arguments[1] : void undefined, T;
|
||||
if (typeof mapFn !== 'undefined') {
|
||||
if (!isCallable(mapFn)) {
|
||||
throw new TypeError('Array.from: when provided, the second argument must be a function');
|
||||
}
|
||||
|
||||
if (arguments.length > 2) {
|
||||
T = arguments[2];
|
||||
}
|
||||
}
|
||||
var len = toLength(items.length);
|
||||
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
|
||||
|
||||
var k = 0;
|
||||
var kValue;
|
||||
while (k < len) {
|
||||
kValue = items[k];
|
||||
if (mapFn) {
|
||||
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
|
||||
} else {
|
||||
A[k] = kValue;
|
||||
}
|
||||
k += 1;
|
||||
}
|
||||
A.length = len;
|
||||
return A;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
// https://github.com/jonathantneal/array-flat-polyfill/blob/master/src/polyfill-flat.js
|
||||
|
||||
if (!Array.prototype.flat) {
|
||||
Object.defineProperty(Array.prototype, 'flat', {
|
||||
configurable: true,
|
||||
value: function flat () {
|
||||
var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]);
|
||||
|
||||
return depth ? Array.prototype.reduce.call(this, function (acc, cur) {
|
||||
if (Array.isArray(cur)) {
|
||||
acc.push.apply(acc, flat.call(cur, depth - 1));
|
||||
} else {
|
||||
acc.push(cur);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []) : Array.prototype.slice.call(this);
|
||||
},
|
||||
writable: true
|
||||
});
|
||||
}
|
||||
|
||||
if (!Array.prototype.includes) {
|
||||
Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
|
||||
var O = Object(this);
|
||||
var len = parseInt(O.length) || 0;
|
||||
if (len === 0) {
|
||||
return false;
|
||||
}
|
||||
var n = parseInt(arguments[1]) || 0;
|
||||
var k;
|
||||
if (n >= 0) {
|
||||
k = n;
|
||||
} else {
|
||||
k = len + n;
|
||||
if (k < 0) {k = 0;}
|
||||
}
|
||||
var currentElement;
|
||||
while (k < len) {
|
||||
currentElement = O[k];
|
||||
if (searchElement === currentElement ||
|
||||
(searchElement !== searchElement && currentElement !== currentElement)) {
|
||||
return true;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.includes) {
|
||||
String.prototype.includes = function(search, start) {
|
||||
if (search instanceof RegExp) {
|
||||
throw TypeError('first argument must not be a RegExp');
|
||||
}
|
||||
if (start === undefined) { start = 0; }
|
||||
return this.indexOf(search, start) !== -1;
|
||||
};
|
||||
}
|
||||
|
||||
if (!Number.isFinite) {
|
||||
Number.isFinite = function(value) {
|
||||
return typeof value === 'number'
|
||||
&& isFinite(value);
|
||||
};
|
||||
}
|
||||
|
||||
if (!Number.isInteger) {
|
||||
Number.isInteger = function(value) {
|
||||
return typeof value === 'number'
|
||||
&& isFinite(value)
|
||||
&& Math.floor(value) === value;
|
||||
};
|
||||
}
|
||||
|
||||
if (!Number.isNaN) {
|
||||
Number.isNaN = function(value) {
|
||||
return typeof value === 'number'
|
||||
&& value !== value;
|
||||
};
|
||||
}
|
||||
3
dist/polyfill.min.js
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// KUTE.js Polyfill v2.1.1-alpha1 | 2021 © thednp | MIT-License
|
||||
"use strict";
|
||||
var r,t,e,n;Array.from||(Array.from=(r=Object.prototype.toString,t=function(t){return"function"==typeof t||"[object Function]"===r.call(t)},e=Math.pow(2,53)-1,n=function(r){var t=function(r){var t=Number(r);return isNaN(t)?0:0!==t&&isFinite(t)?(t>0?1:-1)*Math.floor(Math.abs(t)):t}(r);return Math.min(Math.max(t,0),e)},function(r){var e=this,i=Object(r);if(null==r)throw new TypeError("Array.from requires an array-like object - not null or undefined");var o,a=arguments.length>1?arguments[1]:void 0;if(void 0!==a){if(!t(a))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(o=arguments[2])}for(var u,f=n(i.length),p=t(e)?Object(new e(f)):new Array(f),c=0;c<f;)u=i[c],p[c]=a?void 0===o?a(u,c):a.call(o,u,c):u,c+=1;return p.length=f,p})),Array.prototype.flat||Object.defineProperty(Array.prototype,"flat",{configurable:!0,value:function r(){var t=isNaN(arguments[0])?1:Number(arguments[0]);return t?Array.prototype.reduce.call(this,(function(e,n){return Array.isArray(n)?e.push.apply(e,r.call(n,t-1)):e.push(n),e}),[]):Array.prototype.slice.call(this)},writable:!0}),Array.prototype.includes||(Array.prototype.includes=function(r){var t=Object(this),e=parseInt(t.length)||0;if(0===e)return!1;var n,i,o=parseInt(arguments[1])||0;for(o>=0?n=o:(n=e+o)<0&&(n=0);n<e;){if(r===(i=t[n])||r!=r&&i!=i)return!0;n++}return!1}),String.prototype.includes||(String.prototype.includes=function(r,t){if(r instanceof RegExp)throw TypeError("first argument must not be a RegExp");return void 0===t&&(t=0),-1!==this.indexOf(r,t)}),Number.isFinite||(Number.isFinite=function(r){return"number"==typeof r&&isFinite(r)}),Number.isInteger||(Number.isInteger=function(r){return"number"==typeof r&&isFinite(r)&&Math.floor(r)===r}),Number.isNaN||(Number.isNaN=function(r){return"number"==typeof r&&r!=r});
|
||||
80
package.json
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"name": "kute.js",
|
||||
"version": "2.2.3",
|
||||
"description": "JavaScript animation engine",
|
||||
"main": "dist/kute.min.js",
|
||||
"module": "dist/kute.esm.js",
|
||||
"jsnext": "src/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"types",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"help": "rollup --help",
|
||||
"build1": "npm-run-all --parallel copy-build build-*",
|
||||
"build": "npm run lint:js && npm-run-all --parallel copy-build build-*",
|
||||
"custom": "rollup -c --environment",
|
||||
"fix:js": "eslint src/ --config .eslintrc --fix",
|
||||
"lint:js": "eslint src/ --config .eslintrc",
|
||||
"copy-build": "rollup --environment OUTPUTFILE:demo/src/kute.min.js,DIST:standard,MIN:true,FORMAT:umd -c",
|
||||
"build-standard": "rollup --environment DIST:standard,MIN:false,FORMAT:umd -c",
|
||||
"build:ts": "tsc -d",
|
||||
"build-standard-min": "rollup --environment DIST:standard,MIN:true,FORMAT:umd -c",
|
||||
"build-standard-esm": "rollup --environment DIST:standard,MIN:false,FORMAT:esm -c",
|
||||
"build-standard-esm-min": "rollup --environment DIST:standard,MIN:true,FORMAT:esm -c",
|
||||
"build-base": "rollup --environment OUTPUTFILE:demo/src/kute-base.js,DIST:base,MIN:false,FORMAT:umd -c",
|
||||
"build-base-min": "rollup --environment OUTPUTFILE:demo/src/kute-base.min.js,DIST:base,MIN:true,FORMAT:umd -c",
|
||||
"build-extra": "rollup --environment OUTPUTFILE:demo/src/kute-extra.js,DIST:extra,MIN:false,FORMAT:umd -c",
|
||||
"build-extra-min": "rollup --environment OUTPUTFILE:demo/src/kute-extra.min.js,DIST:extra,MIN:true,FORMAT:umd -c",
|
||||
"polyfill": "npm-run-all --parallel polyfill-unminified polyfill-minified copy-polyfill copy-polyfill-legacy",
|
||||
"copy-polyfill-legacy": "rollup --environment INPUTFILE:src/util/polyfill-legacy.js,OUTPUTFILE:demo/src/polyfill-legacy.min.js,MIN:true -c rollup.polyfill.js",
|
||||
"copy-polyfill": "rollup --environment OUTPUTFILE:demo/src/polyfill.min.js,MIN:true -c rollup.polyfill.js",
|
||||
"polyfill-unminified": "rollup --environment MIN:false -c rollup.polyfill.js",
|
||||
"polyfill-minified": "rollup --environment MIN:true -c rollup.polyfill.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/thednp/kute.js.git"
|
||||
},
|
||||
"keywords": [
|
||||
"kute.js",
|
||||
"svg morph",
|
||||
"svg transform",
|
||||
"css3 transform",
|
||||
"matrix transform",
|
||||
"tweening engine",
|
||||
"animation engine",
|
||||
"javascript animation engine",
|
||||
"javascript animation",
|
||||
"animation",
|
||||
"native javascript"
|
||||
],
|
||||
"author": "thednp",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/thednp/kute.js/issues"
|
||||
},
|
||||
"homepage": "http://thednp.github.io/kute.js",
|
||||
"dependencies": {
|
||||
"cubic-bezier-easing": "^1.0.18",
|
||||
"minifill": "^0.0.16",
|
||||
"shorter-js": "^0.2.6",
|
||||
"svg-path-commander": "0.1.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-buble": "^0.21.3",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^9.0.0",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-vue": "^7.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^2.38.4",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typescript": "^4.5.2"
|
||||
}
|
||||
}
|
||||
58
rollup.config.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
'use strict'
|
||||
import buble from '@rollup/plugin-buble'
|
||||
import {terser} from 'rollup-plugin-terser'
|
||||
import node from '@rollup/plugin-node-resolve'
|
||||
import json from '@rollup/plugin-json'
|
||||
import * as pkg from "./package.json"
|
||||
|
||||
|
||||
let INPUTFILE = process.env.INPUTFILE
|
||||
let OUTPUTFILE = process.env.OUTPUTFILE
|
||||
const DIST = process.env.DIST // base|standard|extra
|
||||
const NAME = DIST.charAt(0).toUpperCase() + DIST.slice(1); // Base|Standard|Extra
|
||||
const MIN = process.env.MIN === 'true' // true/false|unset
|
||||
const FORMAT = process.env.FORMAT // umd|iife|esm
|
||||
|
||||
const year = (new Date).getFullYear()
|
||||
const banner =
|
||||
`/*!
|
||||
* KUTE.js ${NAME} v${pkg.version} (${pkg.homepage})
|
||||
* Copyright 2015-${year} © ${pkg.author}
|
||||
* Licensed under MIT (https://github.com/thednp/kute.js/blob/master/LICENSE)
|
||||
*/`
|
||||
const miniBanner = `// KUTE.js ${NAME} v${pkg.version} | ${pkg.author} © ${year} | ${pkg.license}-License`
|
||||
|
||||
INPUTFILE = INPUTFILE ? INPUTFILE : (DIST === 'standard' ? 'src/index.js' : 'src/index-'+DIST+'.js')
|
||||
OUTPUTFILE = OUTPUTFILE ? OUTPUTFILE : ('dist/kute'+(DIST!=='standard'?'-'+DIST:'')+(FORMAT==='esm'?'.esm':'')+(MIN?'.min':'')+'.js')
|
||||
|
||||
const OUTPUT = {
|
||||
file: OUTPUTFILE,
|
||||
format: FORMAT, // or iife
|
||||
}
|
||||
|
||||
const PLUGINS = [
|
||||
node({mainFields: ['jsnext','module'], dedupe: ['svg-path-commander']}) ,
|
||||
json(),
|
||||
]
|
||||
|
||||
if (FORMAT!=='esm'){
|
||||
PLUGINS.push(buble({objectAssign: 'Object.assign'}));
|
||||
}
|
||||
|
||||
if (MIN){
|
||||
PLUGINS.push(terser({output: {preamble: miniBanner}}));
|
||||
} else {
|
||||
OUTPUT.banner = banner;
|
||||
}
|
||||
|
||||
if (FORMAT!=='esm') {
|
||||
OUTPUT.name = 'KUTE';
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
input: INPUTFILE,
|
||||
output: OUTPUT,
|
||||
plugins: PLUGINS
|
||||
}
|
||||
]
|
||||
54
rollup.polyfill.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
'use strict'
|
||||
import buble from '@rollup/plugin-buble'
|
||||
import node from '@rollup/plugin-node-resolve'
|
||||
import json from '@rollup/plugin-json'
|
||||
import {terser} from 'rollup-plugin-terser'
|
||||
import * as pkg from "./package.json";
|
||||
|
||||
// set headers
|
||||
const year = (new Date).getFullYear()
|
||||
const banner = `/*!
|
||||
* KUTE.js Polyfill v${pkg.version} (${pkg.homepage})
|
||||
* Copyright 2015-${year} © ${pkg.author}
|
||||
* Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
|
||||
*/
|
||||
"use strict";`
|
||||
|
||||
const miniBanner = `// KUTE.js Polyfill v${pkg.version} | ${year} © ${pkg.author} | ${pkg.license}-License
|
||||
"use strict";`
|
||||
|
||||
// set config
|
||||
const MIN = process.env.MIN === 'true' // true/false|unset
|
||||
const FORMAT = 'esm' // umd|iife|esm|cjs
|
||||
|
||||
const INPUTFILE = process.env.INPUTFILE ? process.env.INPUTFILE : 'src/util/polyfill.js'
|
||||
const OUTPUTFILE = process.env.OUTPUTFILE ? process.env.OUTPUTFILE : 'dist/polyfill'+(MIN?'.min':'')+'.js'
|
||||
|
||||
const OUTPUT = {
|
||||
file: OUTPUTFILE,
|
||||
format: FORMAT, // or iife
|
||||
}
|
||||
|
||||
const PLUGINS = [
|
||||
node(),
|
||||
json(),
|
||||
buble(),
|
||||
]
|
||||
|
||||
if (MIN){
|
||||
PLUGINS.push(terser({output: {preamble: miniBanner}}));
|
||||
} else {
|
||||
OUTPUT.banner = banner;
|
||||
}
|
||||
|
||||
// if (FORMAT!=='esm') {
|
||||
// OUTPUT.name = 'BSN';
|
||||
// }
|
||||
|
||||
export default [
|
||||
{
|
||||
input: INPUTFILE,
|
||||
output: OUTPUT,
|
||||
plugins: PLUGINS
|
||||
}
|
||||
]
|
||||
137
src/animation/animation.js
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import supportedProperties from '../objects/supportedProperties';
|
||||
import defaultValues from '../objects/defaultValues';
|
||||
import defaultOptions from '../objects/defaultOptions';
|
||||
import prepareProperty from '../objects/prepareProperty';
|
||||
import prepareStart from '../objects/prepareStart';
|
||||
import onStart from '../objects/onStart';
|
||||
import onComplete from '../objects/onComplete';
|
||||
import crossCheck from '../objects/crossCheck';
|
||||
import linkProperty from '../objects/linkProperty';
|
||||
import Util from '../objects/util';
|
||||
import Interpolate from '../objects/interpolate';
|
||||
|
||||
/**
|
||||
* Animation Class
|
||||
*
|
||||
* Registers components by populating KUTE.js objects and makes sure
|
||||
* no duplicate component / property is allowed.
|
||||
*/
|
||||
export default class Animation {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {KUTE.fullComponent} Component
|
||||
*/
|
||||
constructor(Component) {
|
||||
try {
|
||||
if (Component.component in supportedProperties) {
|
||||
throw Error(`KUTE - ${Component.component} already registered`);
|
||||
} else if (Component.property in defaultValues) {
|
||||
throw Error(`KUTE - ${Component.property} already registered`);
|
||||
}
|
||||
} catch (e) {
|
||||
throw Error(e);
|
||||
}
|
||||
|
||||
const propertyInfo = this;
|
||||
const ComponentName = Component.component;
|
||||
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty, Util }
|
||||
const Functions = {
|
||||
prepareProperty, prepareStart, onStart, onComplete, crossCheck,
|
||||
};
|
||||
const Category = Component.category;
|
||||
const Property = Component.property;
|
||||
const Length = (Component.properties && Component.properties.length)
|
||||
|| (Component.subProperties && Component.subProperties.length);
|
||||
|
||||
// single property
|
||||
// {property,defaultvalue,defaultOptions,Interpolate,functions}
|
||||
|
||||
// category colors, boxModel, borderRadius
|
||||
// {category,properties,defaultvalues,defaultOptions,Interpolate,functions}
|
||||
|
||||
// property with multiple sub properties. Eg transform, filter
|
||||
// {property,subProperties,defaultvalues,defaultOptions,Interpolate,functions}
|
||||
|
||||
// property with multiple sub properties. Eg htmlAttributes
|
||||
// {category,subProperties,defaultvalues,defaultOptions,Interpolate,functions}
|
||||
|
||||
// set supported category/property
|
||||
supportedProperties[ComponentName] = Component.properties
|
||||
|| Component.subProperties || Component.property;
|
||||
|
||||
// set defaultValues
|
||||
if ('defaultValue' in Component) { // value 0 will invalidate
|
||||
defaultValues[Property] = Component.defaultValue;
|
||||
|
||||
// minimal info
|
||||
propertyInfo.supports = `${Property} property`;
|
||||
} else if (Component.defaultValues) {
|
||||
Object.keys(Component.defaultValues).forEach((dv) => {
|
||||
defaultValues[dv] = Component.defaultValues[dv];
|
||||
});
|
||||
|
||||
// minimal info
|
||||
propertyInfo.supports = `${Length || Property} ${Property || Category} properties`;
|
||||
}
|
||||
|
||||
// set additional options
|
||||
if (Component.defaultOptions) {
|
||||
// Object.keys(Component.defaultOptions).forEach((op) => {
|
||||
// defaultOptions[op] = Component.defaultOptions[op];
|
||||
// });
|
||||
Object.assign(defaultOptions, Component.defaultOptions);
|
||||
}
|
||||
|
||||
// set functions
|
||||
if (Component.functions) {
|
||||
Object.keys(Functions).forEach((fn) => {
|
||||
if (fn in Component.functions) {
|
||||
if (typeof (Component.functions[fn]) === 'function') {
|
||||
// if (!Functions[fn][ Category||Property ]) {
|
||||
// Functions[fn][ Category||Property ] = Component.functions[fn];
|
||||
// }
|
||||
if (!Functions[fn][ComponentName]) Functions[fn][ComponentName] = {};
|
||||
if (!Functions[fn][ComponentName][Category || Property]) {
|
||||
Functions[fn][ComponentName][Category || Property] = Component.functions[fn];
|
||||
}
|
||||
} else {
|
||||
Object.keys(Component.functions[fn]).forEach((ofn) => {
|
||||
// !Functions[fn][ofn] && (Functions[fn][ofn] = Component.functions[fn][ofn])
|
||||
if (!Functions[fn][ComponentName]) Functions[fn][ComponentName] = {};
|
||||
if (!Functions[fn][ComponentName][ofn]) {
|
||||
Functions[fn][ComponentName][ofn] = Component.functions[fn][ofn];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// set component interpolation functions
|
||||
if (Component.Interpolate) {
|
||||
Object.keys(Component.Interpolate).forEach((fni) => {
|
||||
const compIntObj = Component.Interpolate[fni];
|
||||
if (typeof (compIntObj) === 'function' && !Interpolate[fni]) {
|
||||
Interpolate[fni] = compIntObj;
|
||||
} else {
|
||||
Object.keys(compIntObj).forEach((sfn) => {
|
||||
if (typeof (compIntObj[sfn]) === 'function' && !Interpolate[fni]) {
|
||||
Interpolate[fni] = compIntObj[sfn];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
linkProperty[ComponentName] = Component.Interpolate;
|
||||
}
|
||||
|
||||
// set component util
|
||||
if (Component.Util) {
|
||||
Object.keys(Component.Util).forEach((fnu) => {
|
||||
if (!Util[fnu]) Util[fnu] = Component.Util[fnu];
|
||||
});
|
||||
}
|
||||
|
||||
return propertyInfo;
|
||||
}
|
||||
}
|
||||
97
src/animation/animationBase.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import supportedProperties from '../objects/supportedProperties';
|
||||
import defaultOptions from '../objects/defaultOptions';
|
||||
import onStart from '../objects/onStart';
|
||||
import onComplete from '../objects/onComplete';
|
||||
import linkProperty from '../objects/linkProperty';
|
||||
import Util from '../objects/util';
|
||||
import Interpolate from '../objects/interpolate';
|
||||
|
||||
/**
|
||||
* Animation Base Class
|
||||
*
|
||||
* Registers components by populating KUTE.js objects and makes sure
|
||||
* no duplicate component / property is allowed.
|
||||
*
|
||||
* This class only registers the minimal amount of component information
|
||||
* required to enable components animation, which means value processing
|
||||
* as well as `to()` and `allTo()` methods are not supported.
|
||||
*/
|
||||
export default class AnimationBase {
|
||||
/**
|
||||
* @class
|
||||
* @param {KUTE.baseComponent} Component
|
||||
*/
|
||||
constructor(Component) {
|
||||
const ComponentName = Component.component;
|
||||
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty }
|
||||
const Functions = { onStart, onComplete };
|
||||
const Category = Component.category;
|
||||
const Property = Component.property;
|
||||
// ESLint
|
||||
this._ = 0;
|
||||
|
||||
// set supported category/property
|
||||
supportedProperties[ComponentName] = Component.properties
|
||||
|| Component.subProperties || Component.property;
|
||||
|
||||
// set additional options
|
||||
if (Component.defaultOptions) {
|
||||
// Object.keys(Component.defaultOptions).forEach((op) => {
|
||||
// defaultOptions[op] = Component.defaultOptions[op];
|
||||
// });
|
||||
Object.assign(defaultOptions, Component.defaultOptions);
|
||||
}
|
||||
|
||||
// set functions
|
||||
if (Component.functions) {
|
||||
Object.keys(Functions).forEach((fn) => {
|
||||
if (fn in Component.functions) {
|
||||
if (typeof (Component.functions[fn]) === 'function') {
|
||||
// if (!Functions[fn][ Category||Property ]) {
|
||||
// Functions[fn][ Category||Property ] = Component.functions[fn];
|
||||
// }
|
||||
if (!Functions[fn][ComponentName]) Functions[fn][ComponentName] = {};
|
||||
if (!Functions[fn][ComponentName][Category || Property]) {
|
||||
Functions[fn][ComponentName][Category || Property] = Component.functions[fn];
|
||||
}
|
||||
} else {
|
||||
Object.keys(Component.functions[fn]).forEach((ofn) => {
|
||||
// if (!Functions[fn][ofn]) Functions[fn][ofn] = Component.functions[fn][ofn];
|
||||
if (!Functions[fn][ComponentName]) Functions[fn][ComponentName] = {};
|
||||
if (!Functions[fn][ComponentName][ofn]) {
|
||||
Functions[fn][ComponentName][ofn] = Component.functions[fn][ofn];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// set interpolate
|
||||
if (Component.Interpolate) {
|
||||
Object.keys(Component.Interpolate).forEach((fni) => {
|
||||
const compIntObj = Component.Interpolate[fni];
|
||||
if (typeof (compIntObj) === 'function' && !Interpolate[fni]) {
|
||||
Interpolate[fni] = compIntObj;
|
||||
} else {
|
||||
Object.keys(compIntObj).forEach((sfn) => {
|
||||
if (typeof (compIntObj[sfn]) === 'function' && !Interpolate[fni]) {
|
||||
Interpolate[fni] = compIntObj[sfn];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
linkProperty[ComponentName] = Component.Interpolate;
|
||||
}
|
||||
|
||||
// set component util
|
||||
if (Component.Util) {
|
||||
Object.keys(Component.Util).forEach((fnu) => {
|
||||
if (!Util[fnu]) Util[fnu] = Component.Util[fnu];
|
||||
});
|
||||
}
|
||||
|
||||
return { name: ComponentName };
|
||||
}
|
||||
}
|
||||
137
src/animation/animationDevelopment.js
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import prepareProperty from '../objects/prepareProperty';
|
||||
import prepareStart from '../objects/prepareStart';
|
||||
import onStart from '../objects/onStart';
|
||||
import onComplete from '../objects/onComplete';
|
||||
import crossCheck from '../objects/crossCheck';
|
||||
import Interpolate from '../objects/interpolate';
|
||||
|
||||
import Animation from './animation';
|
||||
|
||||
/**
|
||||
* Animation Development Class
|
||||
*
|
||||
* Registers components by populating KUTE.js objects and makes sure
|
||||
* no duplicate component / property is allowed.
|
||||
*
|
||||
* In addition to the default class, this one provides more component
|
||||
* information to help you with custom component development.
|
||||
*/
|
||||
export default class AnimationDevelopment extends Animation {
|
||||
/**
|
||||
*
|
||||
* @param {KUTE.fullComponent} args
|
||||
*/
|
||||
constructor(Component) {
|
||||
super(Component);
|
||||
|
||||
const propertyInfo = this;
|
||||
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty, Util }
|
||||
const Functions = {
|
||||
prepareProperty, prepareStart, onStart, onComplete, crossCheck,
|
||||
};
|
||||
const Category = Component.category;
|
||||
const Property = Component.property;
|
||||
const Length = (Component.properties && Component.properties.length)
|
||||
|| (Component.subProperties && Component.subProperties.length);
|
||||
|
||||
// set defaultValues
|
||||
if ('defaultValue' in Component) { // value 0 will invalidate
|
||||
propertyInfo.supports = `${Property} property`;
|
||||
propertyInfo.defaultValue = `${(`${Component.defaultValue}`).length ? 'YES' : 'not set or incorrect'}`;
|
||||
} else if (Component.defaultValues) {
|
||||
propertyInfo.supports = `${Length || Property} ${Property || Category} properties`;
|
||||
propertyInfo.defaultValues = Object.keys(Component.defaultValues).length === Length ? 'YES' : 'Not set or incomplete';
|
||||
}
|
||||
|
||||
// set additional options
|
||||
if (Component.defaultOptions) {
|
||||
propertyInfo.extends = [];
|
||||
|
||||
Object.keys(Component.defaultOptions).forEach((op) => {
|
||||
propertyInfo.extends.push(op);
|
||||
});
|
||||
|
||||
if (propertyInfo.extends.length) {
|
||||
propertyInfo.extends = `with <${propertyInfo.extends.join(', ')}> new option(s)`;
|
||||
} else {
|
||||
delete propertyInfo.extends;
|
||||
}
|
||||
}
|
||||
|
||||
// set functions
|
||||
if (Component.functions) {
|
||||
propertyInfo.interface = [];
|
||||
propertyInfo.render = [];
|
||||
propertyInfo.warning = [];
|
||||
|
||||
Object.keys(Functions).forEach((fnf) => {
|
||||
if (fnf in Component.functions) {
|
||||
if (fnf === 'prepareProperty') propertyInfo.interface.push('fromTo()');
|
||||
if (fnf === 'prepareStart') propertyInfo.interface.push('to()');
|
||||
if (fnf === 'onStart') propertyInfo.render = 'can render update';
|
||||
} else {
|
||||
if (fnf === 'prepareProperty') propertyInfo.warning.push('fromTo()');
|
||||
if (fnf === 'prepareStart') propertyInfo.warning.push('to()');
|
||||
if (fnf === 'onStart') propertyInfo.render = 'no function to render update';
|
||||
}
|
||||
});
|
||||
|
||||
if (propertyInfo.interface.length) {
|
||||
propertyInfo.interface = `${Category || Property} can use [${propertyInfo.interface.join(', ')}] method(s)`;
|
||||
} else {
|
||||
delete propertyInfo.uses;
|
||||
}
|
||||
|
||||
if (propertyInfo.warning.length) {
|
||||
propertyInfo.warning = `${Category || Property} can't use [${propertyInfo.warning.join(', ')}] method(s) because values aren't processed`;
|
||||
} else {
|
||||
delete propertyInfo.warning;
|
||||
}
|
||||
}
|
||||
|
||||
// register Interpolation functions
|
||||
if (Component.Interpolate) {
|
||||
propertyInfo.uses = [];
|
||||
propertyInfo.adds = [];
|
||||
|
||||
Object.keys(Component.Interpolate).forEach((fni) => {
|
||||
const compIntObj = Component.Interpolate[fni];
|
||||
// register new Interpolation functions
|
||||
if (typeof (compIntObj) === 'function') {
|
||||
if (!Interpolate[fni]) {
|
||||
propertyInfo.adds.push(`${fni}`);
|
||||
}
|
||||
propertyInfo.uses.push(`${fni}`);
|
||||
} else {
|
||||
Object.keys(compIntObj).forEach((sfn) => {
|
||||
if (typeof (compIntObj[sfn]) === 'function' && !Interpolate[fni]) {
|
||||
propertyInfo.adds.push(`${sfn}`);
|
||||
}
|
||||
propertyInfo.uses.push(`${sfn}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (propertyInfo.uses.length) {
|
||||
propertyInfo.uses = `[${propertyInfo.uses.join(', ')}] interpolation function(s)`;
|
||||
} else {
|
||||
delete propertyInfo.uses;
|
||||
}
|
||||
|
||||
if (propertyInfo.adds.length) {
|
||||
propertyInfo.adds = `new [${propertyInfo.adds.join(', ')}] interpolation function(s)`;
|
||||
} else {
|
||||
delete propertyInfo.adds;
|
||||
}
|
||||
} else {
|
||||
propertyInfo.critical = `For ${Property || Category} no interpolation function[s] is set`;
|
||||
}
|
||||
|
||||
// set component util
|
||||
if (Component.Util) {
|
||||
propertyInfo.hasUtil = Object.keys(Component.Util).join(',');
|
||||
}
|
||||
|
||||
return propertyInfo;
|
||||
}
|
||||
}
|
||||
57
src/components/backgroundPosition.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import defaultValues from '../objects/defaultValues';
|
||||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import trueDimension from '../util/trueDimension';
|
||||
import { onStartBgPos } from './backgroundPositionBase';
|
||||
|
||||
// Component Functions
|
||||
|
||||
/**
|
||||
* Returns the property computed style.
|
||||
* @param {string} prop the property
|
||||
* @returns {string} the property computed style
|
||||
*/
|
||||
function getBgPos(prop/* , value */) {
|
||||
return getStyleForProperty(this.element, prop) || defaultValues[prop];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} _ the property name
|
||||
* @param {string} value the property value
|
||||
* @returns {number[]} the property tween object
|
||||
*/
|
||||
function prepareBgPos(/* prop, */_, value) {
|
||||
if (value instanceof Array) {
|
||||
const x = trueDimension(value[0]).v;
|
||||
const y = trueDimension(value[1]).v;
|
||||
return [!Number.isNaN(x * 1) ? x : 50, !Number.isNaN(y * 1) ? y : 50];
|
||||
}
|
||||
|
||||
let posxy = value.replace(/top|left/g, 0)
|
||||
.replace(/right|bottom/g, 100)
|
||||
.replace(/center|middle/g, 50);
|
||||
|
||||
posxy = posxy.split(/(,|\s)/g);
|
||||
posxy = posxy.length === 2 ? posxy : [posxy[0], 50];
|
||||
return [trueDimension(posxy[0]).v, trueDimension(posxy[1]).v];
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
const bgPositionFunctions = {
|
||||
prepareStart: getBgPos,
|
||||
prepareProperty: prepareBgPos,
|
||||
onStart: onStartBgPos,
|
||||
};
|
||||
|
||||
// Component Full Object
|
||||
const BackgroundPosition = {
|
||||
component: 'backgroundPositionProp',
|
||||
property: 'backgroundPosition',
|
||||
defaultValue: [50, 50],
|
||||
Interpolate: { numbers },
|
||||
functions: bgPositionFunctions,
|
||||
Util: { trueDimension },
|
||||
};
|
||||
|
||||
export default BackgroundPosition;
|
||||
26
src/components/backgroundPositionBase.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import KEC from '../objects/kute';
|
||||
import numbers from '../interpolation/numbers';
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Sets the property update function.
|
||||
* @param {string} prop the property name
|
||||
*/
|
||||
export function onStartBgPos(prop) {
|
||||
if (this.valuesEnd[prop] && !KEC[prop]) {
|
||||
KEC[prop] = (elem, a, b, v) => {
|
||||
/* eslint-disable -- no-bitwise & no-param-reassign impossible to satisfy */
|
||||
elem.style[prop] = `${(numbers(a[0], b[0], v) * 100 >> 0) / 100}% ${((numbers(a[1], b[1], v) * 100 >> 0) / 100)}%`;
|
||||
/* eslint-enable -- no-bitwise & no-param-reassign impossible to satisfy */
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Component Base Object
|
||||
const BackgroundPositionBase = {
|
||||
component: 'baseBackgroundPosition',
|
||||
property: 'backgroundPosition',
|
||||
Interpolate: { numbers },
|
||||
functions: { onStart: onStartBgPos },
|
||||
};
|
||||
export default BackgroundPositionBase;
|
||||
58
src/components/borderRadius.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import defaultValues from '../objects/defaultValues';
|
||||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import trueDimension from '../util/trueDimension';
|
||||
import units from '../interpolation/units';
|
||||
import { radiusOnStartFn } from './borderRadiusBase';
|
||||
|
||||
// Component Properties
|
||||
const radiusProps = [
|
||||
'borderRadius',
|
||||
'borderTopLeftRadius', 'borderTopRightRadius',
|
||||
'borderBottomLeftRadius', 'borderBottomRightRadius'];
|
||||
|
||||
const radiusValues = {};
|
||||
radiusProps.forEach((x) => { radiusValues[x] = 0; });
|
||||
|
||||
// Component Functions
|
||||
const radiusOnStart = {};
|
||||
radiusProps.forEach((tweenProp) => {
|
||||
radiusOnStart[tweenProp] = radiusOnStartFn;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the current property computed style.
|
||||
* @param {string} tweenProp the property name
|
||||
* @returns {string} the property computed style
|
||||
*/
|
||||
export function getRadius(tweenProp) {
|
||||
return getStyleForProperty(this.element, tweenProp) || defaultValues[tweenProp];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} value the property value
|
||||
* @returns {{v: number, u: string}} the property tween object
|
||||
*/
|
||||
export function prepareRadius(/* tweenProp, */_, value) {
|
||||
return trueDimension(value);
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
export const radiusFunctions = {
|
||||
prepareStart: getRadius,
|
||||
prepareProperty: prepareRadius,
|
||||
onStart: radiusOnStart,
|
||||
};
|
||||
|
||||
// Full Component
|
||||
const BorderRadius = {
|
||||
component: 'borderRadiusProperties',
|
||||
category: 'borderRadius',
|
||||
properties: radiusProps,
|
||||
defaultValues: radiusValues,
|
||||
Interpolate: { units },
|
||||
functions: radiusFunctions,
|
||||
Util: { trueDimension },
|
||||
};
|
||||
|
||||
export default BorderRadius;
|
||||
43
src/components/borderRadiusBase.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import KEC from '../objects/kute';
|
||||
import units from '../interpolation/units';
|
||||
|
||||
/* borderRadius = {
|
||||
category: 'borderRadius',
|
||||
properties : [..],
|
||||
defaultValues: {..},
|
||||
interpolation: {units}
|
||||
} */
|
||||
|
||||
// Component Properties
|
||||
const radiusProps = [
|
||||
'borderRadius',
|
||||
'borderTopLeftRadius', 'borderTopRightRadius',
|
||||
'borderBottomLeftRadius', 'borderBottomRightRadius',
|
||||
];
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Sets the property update function.
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
export function radiusOnStartFn(tweenProp) {
|
||||
if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
// eslint-disable-next-line no-param-reassign -- impossible to satisfy
|
||||
elem.style[tweenProp] = units(a.v, b.v, b.u, v);
|
||||
};
|
||||
}
|
||||
}
|
||||
const radiusOnStart = {};
|
||||
radiusProps.forEach((tweenProp) => {
|
||||
radiusOnStart[tweenProp] = radiusOnStartFn;
|
||||
});
|
||||
|
||||
// Base Component
|
||||
const BorderRadiusBase = {
|
||||
component: 'baseBorderRadius',
|
||||
category: 'borderRadius',
|
||||
Interpolate: { units },
|
||||
functions: { onStart: radiusOnStart },
|
||||
};
|
||||
export default BorderRadiusBase;
|
||||
57
src/components/boxModel.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import defaultValues from '../objects/defaultValues';
|
||||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import trueDimension from '../util/trueDimension';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import { boxModelOnStart } from './boxModelBase';
|
||||
|
||||
// Component Properties
|
||||
const boxModelProperties = ['top', 'left', 'width', 'height', 'right', 'bottom', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
|
||||
'padding', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight',
|
||||
'margin', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight',
|
||||
'borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'outlineWidth'];
|
||||
|
||||
const boxModelValues = {};
|
||||
boxModelProperties.forEach((x) => { boxModelValues[x] = 0; });
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Returns the current property computed style.
|
||||
* @param {string} tweenProp the property name
|
||||
* @returns {string} computed style for property
|
||||
*/
|
||||
function getBoxModel(tweenProp) {
|
||||
return getStyleForProperty(this.element, tweenProp) || defaultValues[tweenProp];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} tweenProp the property name
|
||||
* @param {string} value the property value
|
||||
* @returns {number} the property tween object
|
||||
*/
|
||||
function prepareBoxModel(tweenProp, value) {
|
||||
const boxValue = trueDimension(value); const
|
||||
offsetProp = tweenProp === 'height' ? 'offsetHeight' : 'offsetWidth';
|
||||
return boxValue.u === '%' ? (boxValue.v * this.element[offsetProp]) / 100 : boxValue.v;
|
||||
}
|
||||
const boxPropsOnStart = {};
|
||||
boxModelProperties.forEach((x) => { boxPropsOnStart[x] = boxModelOnStart; });
|
||||
|
||||
// All Component Functions
|
||||
const boxModelFunctions = {
|
||||
prepareStart: getBoxModel,
|
||||
prepareProperty: prepareBoxModel,
|
||||
onStart: boxPropsOnStart,
|
||||
};
|
||||
|
||||
// Component Full Component
|
||||
const BoxModel = {
|
||||
component: 'boxModelProperties',
|
||||
category: 'boxModel',
|
||||
properties: boxModelProperties,
|
||||
defaultValues: boxModelValues,
|
||||
Interpolate: { numbers },
|
||||
functions: boxModelFunctions,
|
||||
};
|
||||
|
||||
export default BoxModel;
|
||||
37
src/components/boxModelBase.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import KEC from '../objects/kute';
|
||||
import numbers from '../interpolation/numbers';
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Sets the update function for the property.
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
export function boxModelOnStart(tweenProp) {
|
||||
if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
/* eslint-disable no-param-reassign -- impossible to satisfy */
|
||||
/* eslint-disable no-bitwise -- impossible to satisfy */
|
||||
elem.style[tweenProp] = `${v > 0.99 || v < 0.01
|
||||
? ((numbers(a, b, v) * 10) >> 0) / 10
|
||||
: (numbers(a, b, v)) >> 0}px`;
|
||||
/* eslint-enable no-bitwise */
|
||||
/* eslint-enable no-param-reassign */
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Component Base Props
|
||||
const baseBoxProps = ['top', 'left', 'width', 'height'];
|
||||
const baseBoxOnStart = {};
|
||||
baseBoxProps.forEach((x) => { baseBoxOnStart[x] = boxModelOnStart; });
|
||||
|
||||
// Component Base
|
||||
const BoxModelBase = {
|
||||
component: 'baseBoxModel',
|
||||
category: 'boxModel',
|
||||
properties: baseBoxProps,
|
||||
Interpolate: { numbers },
|
||||
functions: { onStart: baseBoxOnStart },
|
||||
};
|
||||
|
||||
export default BoxModelBase;
|
||||
56
src/components/boxModelEssential.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import defaultValues from '../objects/defaultValues';
|
||||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import trueDimension from '../util/trueDimension';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import { boxModelOnStart } from './boxModelBase';
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Returns the current property computed style.
|
||||
* @param {string} tweenProp the property name
|
||||
* @returns {string} computed style for property
|
||||
*/
|
||||
function getBoxModel(tweenProp) {
|
||||
return getStyleForProperty(this.element, tweenProp) || defaultValues[tweenProp];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} tweenProp the property name
|
||||
* @param {string} value the property name
|
||||
* @returns {number} the property tween object
|
||||
*/
|
||||
function prepareBoxModel(tweenProp, value) {
|
||||
const boxValue = trueDimension(value);
|
||||
const offsetProp = tweenProp === 'height' ? 'offsetHeight' : 'offsetWidth';
|
||||
return boxValue.u === '%' ? (boxValue.v * this.element[offsetProp]) / 100 : boxValue.v;
|
||||
}
|
||||
|
||||
// Component Base Props
|
||||
const essentialBoxProps = ['top', 'left', 'width', 'height'];
|
||||
const essentialBoxPropsValues = {
|
||||
top: 0, left: 0, width: 0, height: 0,
|
||||
};
|
||||
|
||||
const essentialBoxOnStart = {};
|
||||
essentialBoxProps.forEach((x) => { essentialBoxOnStart[x] = boxModelOnStart; });
|
||||
|
||||
// All Component Functions
|
||||
const essentialBoxModelFunctions = {
|
||||
prepareStart: getBoxModel,
|
||||
prepareProperty: prepareBoxModel,
|
||||
onStart: essentialBoxOnStart,
|
||||
};
|
||||
|
||||
// Component Essential
|
||||
const BoxModelEssential = {
|
||||
component: 'essentialBoxModel',
|
||||
category: 'boxModel',
|
||||
properties: essentialBoxProps,
|
||||
defaultValues: essentialBoxPropsValues,
|
||||
Interpolate: { numbers },
|
||||
functions: essentialBoxModelFunctions,
|
||||
Util: { trueDimension },
|
||||
};
|
||||
|
||||
export default BoxModelEssential;
|
||||
52
src/components/clipProperty.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import trueDimension from '../util/trueDimension';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import { onStartClip } from './clipPropertyBase';
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Returns the current property computed style.
|
||||
* @param {string} tweenProp the property name
|
||||
* @returns {string | number[]} computed style for property
|
||||
*/
|
||||
function getClip(tweenProp/* , value */) {
|
||||
const { element } = this;
|
||||
const currentClip = getStyleForProperty(element, tweenProp);
|
||||
const width = getStyleForProperty(element, 'width');
|
||||
const height = getStyleForProperty(element, 'height');
|
||||
return !/rect/.test(currentClip) ? [0, width, height, 0] : currentClip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} _ the property name
|
||||
* @param {string} value the property value
|
||||
* @returns {number[]} the property tween object
|
||||
*/
|
||||
function prepareClip(/* tweenProp, */_, value) {
|
||||
if (value instanceof Array) {
|
||||
return value.map((x) => trueDimension(x));
|
||||
}
|
||||
let clipValue = value.replace(/rect|\(|\)/g, '');
|
||||
clipValue = /,/g.test(clipValue) ? clipValue.split(',') : clipValue.split(/\s/);
|
||||
return clipValue.map((x) => trueDimension(x));
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
const clipFunctions = {
|
||||
prepareStart: getClip,
|
||||
prepareProperty: prepareClip,
|
||||
onStart: onStartClip,
|
||||
};
|
||||
|
||||
// Component Full
|
||||
const ClipProperty = {
|
||||
component: 'clipProperty',
|
||||
property: 'clip',
|
||||
defaultValue: [0, 0, 0, 0],
|
||||
Interpolate: { numbers },
|
||||
functions: clipFunctions,
|
||||
Util: { trueDimension },
|
||||
};
|
||||
|
||||
export default ClipProperty;
|
||||
36
src/components/clipPropertyBase.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import KEC from '../objects/kute';
|
||||
import numbers from '../interpolation/numbers';
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Sets the property update function.
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
export function onStartClip(tweenProp) {
|
||||
if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
let h = 0; const
|
||||
cl = [];
|
||||
for (h; h < 4; h += 1) {
|
||||
const c1 = a[h].v;
|
||||
const c2 = b[h].v;
|
||||
const cu = b[h].u || 'px';
|
||||
// eslint-disable-next-line no-bitwise -- impossible to satisfy
|
||||
cl[h] = ((numbers(c1, c2, v) * 100 >> 0) / 100) + cu;
|
||||
}
|
||||
// eslint-disable-next-line no-param-reassign -- impossible to satisfy
|
||||
elem.style.clip = `rect(${cl})`;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Component Base
|
||||
const ClipPropertyBase = {
|
||||
component: 'baseClip',
|
||||
property: 'clip',
|
||||
// defaultValue: [0,0,0,0],
|
||||
Interpolate: { numbers },
|
||||
functions: { onStart: onStartClip },
|
||||
};
|
||||
|
||||
export default ClipPropertyBase;
|
||||
65
src/components/colorProperties.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import defaultValues from '../objects/defaultValues';
|
||||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import trueColor from '../util/trueColor';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import colors from '../interpolation/colors';
|
||||
import { onStartColors } from './colorPropertiesBase';
|
||||
|
||||
// Component Properties
|
||||
// supported formats
|
||||
// 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+)
|
||||
const supportedColors = [
|
||||
'color', 'backgroundColor', 'outlineColor',
|
||||
'borderColor', 'borderTopColor', 'borderRightColor',
|
||||
'borderBottomColor', 'borderLeftColor',
|
||||
];
|
||||
|
||||
const defaultColors = {};
|
||||
supportedColors.forEach((tweenProp) => {
|
||||
defaultColors[tweenProp] = '#000';
|
||||
});
|
||||
|
||||
// Component Functions
|
||||
const colorsOnStart = {};
|
||||
supportedColors.forEach((x) => {
|
||||
colorsOnStart[x] = onStartColors;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the current property computed style.
|
||||
* @param {string} prop the property name
|
||||
* @returns {string} property computed style
|
||||
*/
|
||||
function getColor(prop/* , value */) {
|
||||
return getStyleForProperty(this.element, prop) || defaultValues[prop];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} _ the property name
|
||||
* @param {string} value the property value
|
||||
* @returns {KUTE.colorObject} the property tween object
|
||||
*/
|
||||
function prepareColor(/* prop, */_, value) {
|
||||
return trueColor(value);
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
const colorFunctions = {
|
||||
prepareStart: getColor,
|
||||
prepareProperty: prepareColor,
|
||||
onStart: colorsOnStart,
|
||||
};
|
||||
|
||||
// Component Full
|
||||
const colorProperties = {
|
||||
component: 'colorProperties',
|
||||
category: 'colors',
|
||||
properties: supportedColors,
|
||||
defaultValues: defaultColors,
|
||||
Interpolate: { numbers, colors },
|
||||
functions: colorFunctions,
|
||||
Util: { trueColor },
|
||||
};
|
||||
|
||||
export default colorProperties;
|
||||
45
src/components/colorPropertiesBase.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import KEC from '../objects/kute';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import colors from '../interpolation/colors';
|
||||
|
||||
// Component Interpolation
|
||||
// rgba1, rgba2, progress
|
||||
|
||||
// Component Properties
|
||||
// supported formats
|
||||
// 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+)
|
||||
const supportedColors = [
|
||||
'color', 'backgroundColor', 'outlineColor',
|
||||
'borderColor',
|
||||
'borderTopColor', 'borderRightColor',
|
||||
'borderBottomColor', 'borderLeftColor',
|
||||
];
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Sets the property update function.
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
export function onStartColors(tweenProp) {
|
||||
if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
elem.style[tweenProp] = colors(a, b, v);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const colorsOnStart = {};
|
||||
supportedColors.forEach((x) => { colorsOnStart[x] = onStartColors; });
|
||||
|
||||
// Component Base
|
||||
export const baseColors = {
|
||||
component: 'baseColors',
|
||||
category: 'colors',
|
||||
// properties: supportedColors,
|
||||
// defaultValues: defaultColors,
|
||||
Interpolate: { numbers, colors },
|
||||
functions: { onStart: colorsOnStart },
|
||||
};
|
||||
|
||||
export default baseColors;
|
||||
95
src/components/crossBrowserMove.js
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import KEC from '../objects/kute';
|
||||
import getInlineStyle from '../process/getInlineStyle';
|
||||
import defaultValues from '../objects/defaultValues';
|
||||
import trueProperty from '../util/trueProperty';
|
||||
import numbers from '../interpolation/numbers';
|
||||
|
||||
// Component Const
|
||||
const transformProperty = trueProperty('transform');
|
||||
const supportTransform = transformProperty in document.body.style ? 1 : 0;
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Returns the property current style.
|
||||
*/
|
||||
function getComponentCurrentValue(/* tweenProp, value */) {
|
||||
const currentTransform = getInlineStyle(this.element);
|
||||
const { left } = this.element.style;
|
||||
const { top } = this.element.style;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
if (supportTransform && currentTransform.translate) {
|
||||
[x, y] = currentTransform.translate;
|
||||
} else {
|
||||
x = Number.isFinite(left * 1) ? left : defaultValues.move[0];
|
||||
y = Number.isFinite(top * 1) ? top : defaultValues.move[1];
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} _ property name
|
||||
* @param {string} value property value
|
||||
* @returns {number[]} the property tween object
|
||||
*/
|
||||
function prepareComponentValue(/* tweenProp */_, value) {
|
||||
const x = Number.isFinite(value * 1) ? parseInt(value, 10) : parseInt(value[0], 10) || 0;
|
||||
const y = parseInt(value[1], 10) || 0;
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property update function.
|
||||
* @param {string} tweenProp the `path` property
|
||||
*/
|
||||
export function onStartComponent(tweenProp/* , value */) {
|
||||
if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
|
||||
if (supportTransform) {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
/* eslint-disable-next-line no-param-reassign -- impossible to satisfy */
|
||||
elem.style[transformProperty] = `translate(${numbers(a[0], b[0], v)}px,${numbers(a[1], b[1], v)}px)`;
|
||||
};
|
||||
} else {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
if (a[0] || b[0]) {
|
||||
/* eslint-disable-next-line no-param-reassign -- impossible to satisfy */
|
||||
elem.style.left = `${numbers(a[0], b[0], v)}px`;
|
||||
}
|
||||
if (a[1] || b[1]) {
|
||||
/* eslint-disable-next-line no-param-reassign -- impossible to satisfy */
|
||||
elem.style.top = `${numbers(a[1], b[1], v)}px`;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
const componentFunctions = {
|
||||
prepareStart: getComponentCurrentValue,
|
||||
prepareProperty: prepareComponentValue,
|
||||
onStart: onStartComponent,
|
||||
};
|
||||
|
||||
// Base Component
|
||||
export const baseCrossBrowserMove = {
|
||||
component: 'baseCrossBrowserMove',
|
||||
property: 'move',
|
||||
Interpolate: { numbers },
|
||||
functions: { onStart: onStartComponent },
|
||||
};
|
||||
|
||||
// Full Component
|
||||
const crossBrowserMove = {
|
||||
component: 'crossBrowserMove',
|
||||
property: 'move',
|
||||
defaultValue: [0, 0],
|
||||
Interpolate: { numbers },
|
||||
functions: componentFunctions,
|
||||
Util: { trueProperty },
|
||||
};
|
||||
|
||||
export default crossBrowserMove;
|
||||
201
src/components/filterEffects.js
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
import getStyleForProperty from '../process/getStyleForProperty';
|
||||
import defaultValues from '../objects/defaultValues';
|
||||
import trueColor from '../util/trueColor';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import colors from '../interpolation/colors';
|
||||
import { dropshadow, onStartFilter } from './filterEffectsBase';
|
||||
|
||||
/* filterEffects = {
|
||||
property: 'filter',
|
||||
subProperties: {},
|
||||
defaultValue: {},
|
||||
interpolators: {},
|
||||
functions = { prepareStart, prepareProperty, onStart, crossCheck }
|
||||
} */
|
||||
|
||||
// Component Util
|
||||
/**
|
||||
* Returns camelCase filter sub-property.
|
||||
* @param {string} str source string
|
||||
* @returns {string} camelCase property name
|
||||
*/
|
||||
function replaceDashNamespace(str) {
|
||||
return str.replace('-r', 'R').replace('-s', 'S');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `drop-shadow` sub-property object.
|
||||
* @param {(string | number)[]} shadow and `Array` with `drop-shadow` parameters
|
||||
* @returns {KUTE.filterList['dropShadow']} the expected `drop-shadow` values
|
||||
*/
|
||||
function parseDropShadow(shadow) {
|
||||
let newShadow;
|
||||
|
||||
if (shadow.length === 3) { // [h-shadow, v-shadow, color]
|
||||
newShadow = [shadow[0], shadow[1], 0, shadow[2]];
|
||||
} else if (shadow.length === 4) { // ideal [<offset-x>, <offset-y>, <blur-radius>, <color>]
|
||||
newShadow = [shadow[0], shadow[1], shadow[2], shadow[3]];
|
||||
}
|
||||
|
||||
// make sure the values are ready to tween
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
newShadow[i] = parseFloat(newShadow[i]);
|
||||
}
|
||||
// also the color must be a rgb object
|
||||
newShadow[3] = trueColor(newShadow[3]);
|
||||
return newShadow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with current filter sub-properties values.
|
||||
* @param {string} currentStyle the current filter computed style
|
||||
* @returns {{[x: string]: number}} the filter tuple
|
||||
*/
|
||||
function parseFilterString(currentStyle) {
|
||||
const result = {};
|
||||
const fnReg = /(([a-z].*?)\(.*?\))(?=\s([a-z].*?)\(.*?\)|\s*$)/g;
|
||||
const matches = currentStyle.match(fnReg);
|
||||
const fnArray = currentStyle !== 'none' ? matches : 'none';
|
||||
|
||||
if (fnArray instanceof Array) {
|
||||
for (let j = 0, jl = fnArray.length; j < jl; j += 1) {
|
||||
const p = fnArray[j].trim().split(/\((.+)/);
|
||||
const pp = replaceDashNamespace(p[0]);
|
||||
if (pp === 'dropShadow') {
|
||||
const shadowColor = p[1].match(/(([a-z].*?)\(.*?\))(?=\s(.*?))/)[0];
|
||||
const params = p[1].replace(shadowColor, '').split(/\s/).map(parseFloat);
|
||||
result[pp] = params.filter((el) => !Number.isNaN(el)).concat(shadowColor);
|
||||
} else {
|
||||
result[pp] = p[1].replace(/'|"|\)/g, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Returns the current property computed style.
|
||||
* @param {string} tweenProp the property name
|
||||
* @param {string} value the property value
|
||||
* @returns {string} computed style for property
|
||||
*/
|
||||
function getFilter(tweenProp, value) {
|
||||
const currentStyle = getStyleForProperty(this.element, tweenProp);
|
||||
const filterObject = parseFilterString(currentStyle);
|
||||
let fnp;
|
||||
|
||||
Object.keys(value).forEach((fn) => {
|
||||
fnp = replaceDashNamespace(fn);
|
||||
if (!filterObject[fnp]) {
|
||||
filterObject[fnp] = defaultValues[tweenProp][fn];
|
||||
}
|
||||
});
|
||||
|
||||
return filterObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} _ the property name
|
||||
* @param {string} value the property name
|
||||
* @returns {KUTE.filterList} the property tween object
|
||||
*/
|
||||
function prepareFilter(/* tweenProp, */_, value) {
|
||||
const filterObject = {};
|
||||
let fnp;
|
||||
|
||||
// property: range | default
|
||||
// opacity: [0-100%] | 100
|
||||
// blur: [0-Nem] | 0
|
||||
// saturate: [0-N%] | 100
|
||||
// invert: [0-100%] | 0
|
||||
// grayscale: [0-100%] | 0
|
||||
// brightness: [0-N%] | 100
|
||||
// contrast: [0-N%] | 100
|
||||
// sepia: [0-N%] | 0
|
||||
// 'hueRotate': [0-Ndeg] | 0
|
||||
// 'dropShadow': [0,0,0,(r:0,g:0,b:0)] | 0
|
||||
// url: '' | ''
|
||||
|
||||
Object.keys(value).forEach((fn) => {
|
||||
fnp = replaceDashNamespace(fn);
|
||||
if (/hue/.test(fn)) {
|
||||
filterObject[fnp] = parseFloat(value[fn]);
|
||||
} else if (/drop/.test(fn)) {
|
||||
filterObject[fnp] = parseDropShadow(value[fn]);
|
||||
} else if (fn === 'url') {
|
||||
filterObject[fn] = value[fn];
|
||||
// } else if ( /blur|opacity|grayscale|sepia/.test(fn) ) {
|
||||
} else {
|
||||
filterObject[fn] = parseFloat(value[fn]);
|
||||
}
|
||||
});
|
||||
|
||||
return filterObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds missing sub-properties in `valuesEnd` from `valuesStart`.
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
function crossCheckFilter(tweenProp) {
|
||||
if (this.valuesEnd[tweenProp]) {
|
||||
Object.keys(this.valuesStart[tweenProp]).forEach((fn) => {
|
||||
if (!this.valuesEnd[tweenProp][fn]) {
|
||||
this.valuesEnd[tweenProp][fn] = this.valuesStart[tweenProp][fn];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
const filterFunctions = {
|
||||
prepareStart: getFilter,
|
||||
prepareProperty: prepareFilter,
|
||||
onStart: onStartFilter,
|
||||
crossCheck: crossCheckFilter,
|
||||
};
|
||||
|
||||
// Full Component
|
||||
const filterEffects = {
|
||||
component: 'filterEffects',
|
||||
property: 'filter',
|
||||
// opacity function interfere with opacityProperty
|
||||
// subProperties: [
|
||||
// 'blur', 'brightness','contrast','dropShadow',
|
||||
// 'hueRotate','grayscale','invert','opacity','saturate','sepia','url'
|
||||
// ],
|
||||
defaultValue: {
|
||||
opacity: 100,
|
||||
blur: 0,
|
||||
saturate: 100,
|
||||
grayscale: 0,
|
||||
brightness: 100,
|
||||
contrast: 100,
|
||||
sepia: 0,
|
||||
invert: 0,
|
||||
hueRotate: 0,
|
||||
dropShadow: [0, 0, 0, { r: 0, g: 0, b: 0 }],
|
||||
url: '',
|
||||
},
|
||||
Interpolate: {
|
||||
opacity: numbers,
|
||||
blur: numbers,
|
||||
saturate: numbers,
|
||||
grayscale: numbers,
|
||||
brightness: numbers,
|
||||
contrast: numbers,
|
||||
sepia: numbers,
|
||||
invert: numbers,
|
||||
hueRotate: numbers,
|
||||
dropShadow: { numbers, colors, dropshadow },
|
||||
},
|
||||
functions: filterFunctions,
|
||||
Util: {
|
||||
parseDropShadow, parseFilterString, replaceDashNamespace, trueColor,
|
||||
},
|
||||
};
|
||||
|
||||
export default filterEffects;
|
||||
74
src/components/filterEffectsBase.js
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import KEC from '../objects/kute';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import colors from '../interpolation/colors';
|
||||
|
||||
// Component Interpolation
|
||||
/**
|
||||
* Sets the `drop-shadow` sub-property update function.
|
||||
* * disimbiguation `dropshadow` interpolation function and `dropShadow` property
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
export function dropshadow(a, b, v) {
|
||||
const params = [];
|
||||
const unit = 'px';
|
||||
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
params[i] = ((numbers(a[i], b[i], v) * 100 >> 0) / 100) + unit;
|
||||
}
|
||||
return `drop-shadow(${params.concat(colors(a[3], b[3], v)).join(' ')})`;
|
||||
}
|
||||
// Component Functions
|
||||
/**
|
||||
* Sets the property update function.
|
||||
* @param {string} tweenProp the property name
|
||||
*/
|
||||
export function onStartFilter(tweenProp) {
|
||||
if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
|
||||
KEC[tweenProp] = (elem, a, b, v) => {
|
||||
/* eslint-disable-next-line no-param-reassign -- impossible to satisfy */
|
||||
elem.style[tweenProp] = (b.url ? `url(${b.url})` : '')
|
||||
/* eslint-disable no-bitwise -- impossible to satisfy */
|
||||
+ (a.opacity || b.opacity ? `opacity(${((numbers(a.opacity, b.opacity, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.blur || b.blur ? `blur(${((numbers(a.blur, b.blur, v) * 100) >> 0) / 100}em)` : '')
|
||||
+ (a.saturate || b.saturate ? `saturate(${((numbers(a.saturate, b.saturate, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.invert || b.invert ? `invert(${((numbers(a.invert, b.invert, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.grayscale || b.grayscale ? `grayscale(${((numbers(a.grayscale, b.grayscale, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.hueRotate || b.hueRotate ? `hue-rotate(${((numbers(a.hueRotate, b.hueRotate, v) * 100) >> 0) / 100}deg)` : '')
|
||||
+ (a.sepia || b.sepia ? `sepia(${((numbers(a.sepia, b.sepia, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.brightness || b.brightness ? `brightness(${((numbers(a.brightness, b.brightness, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.contrast || b.contrast ? `contrast(${((numbers(a.contrast, b.contrast, v) * 100) >> 0) / 100}%)` : '')
|
||||
+ (a.dropShadow || b.dropShadow ? dropshadow(a.dropShadow, b.dropShadow, v) : '');
|
||||
/* eslint-enable no-bitwise -- impossible to satisfy */
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Base Component
|
||||
const baseFilter = {
|
||||
component: 'baseFilter',
|
||||
property: 'filter',
|
||||
// opacity function interfere with opacityProperty
|
||||
// subProperties: ['blur', 'brightness','contrast','dropShadow',
|
||||
// 'hueRotate','grayscale','invert','opacity','saturate','sepia','url'],
|
||||
// defaultValue: {
|
||||
// opacity: 100, blur: 0, saturate: 100, grayscale: 0,
|
||||
// brightness: 100, contrast: 100, sepia: 0, invert: 0, hueRotate:0,
|
||||
// dropShadow: [0,0,0,{r:0,g:0,b:0}], url:''
|
||||
// },
|
||||
Interpolate: {
|
||||
opacity: numbers,
|
||||
blur: numbers,
|
||||
saturate: numbers,
|
||||
grayscale: numbers,
|
||||
brightness: numbers,
|
||||
contrast: numbers,
|
||||
sepia: numbers,
|
||||
invert: numbers,
|
||||
hueRotate: numbers,
|
||||
dropShadow: { numbers, colors, dropshadow },
|
||||
},
|
||||
functions: { onStart: onStartFilter },
|
||||
};
|
||||
|
||||
export default baseFilter;
|
||||
131
src/components/htmlAttributes.js
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import defaultValues from '../objects/defaultValues';
|
||||
import onStart from '../objects/onStart';
|
||||
import trueColor from '../util/trueColor';
|
||||
import trueDimension from '../util/trueDimension';
|
||||
import numbers from '../interpolation/numbers';
|
||||
import colors from '../interpolation/colors';
|
||||
import { attributes, onStartAttr } from './htmlAttributesBase';
|
||||
|
||||
// Component Name
|
||||
const ComponentName = 'htmlAttributes';
|
||||
|
||||
// Component Properties
|
||||
const svgColors = ['fill', 'stroke', 'stop-color'];
|
||||
|
||||
// Component Util
|
||||
/**
|
||||
* Returns non-camelcase property name.
|
||||
* @param {string} a the camelcase property name
|
||||
* @returns {string} the non-camelcase property name
|
||||
*/
|
||||
function replaceUppercase(a) { return a.replace(/[A-Z]/g, '-$&').toLowerCase(); }
|
||||
|
||||
// Component Functions
|
||||
/**
|
||||
* Returns the current attribute value.
|
||||
* @param {string} _ the property name
|
||||
* @param {string} value the property value
|
||||
* @returns {{[x:string]: string}} attribute value
|
||||
*/
|
||||
export function getAttr(/* tweenProp, */_, value) {
|
||||
const attrStartValues = {};
|
||||
Object.keys(value).forEach((attr) => {
|
||||
// get the value for 'fill-opacity' not fillOpacity
|
||||
// also 'width' not the internal 'width_px'
|
||||
const attribute = replaceUppercase(attr).replace(/_+[a-z]+/, '');
|
||||
const currentValue = this.element.getAttribute(attribute);
|
||||
attrStartValues[attribute] = svgColors.includes(attribute)
|
||||
? (currentValue || 'rgba(0,0,0,0)')
|
||||
: (currentValue || (/opacity/i.test(attr) ? 1 : 0));
|
||||
});
|
||||
|
||||
return attrStartValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property tween object.
|
||||
* @param {string} tweenProp the property name
|
||||
* @param {string} attrObj the property value
|
||||
* @returns {number} the property tween object
|
||||
*/
|
||||
export function prepareAttr(tweenProp, attrObj) { // attr (string),attrObj (object)
|
||||
const attributesObject = {};
|
||||
|
||||
Object.keys(attrObj).forEach((p) => {
|
||||
const prop = replaceUppercase(p);
|
||||
const regex = /(%|[a-z]+)$/;
|
||||
const currentValue = this.element.getAttribute(prop.replace(/_+[a-z]+/, ''));
|
||||
|
||||
if (!svgColors.includes(prop)) {
|
||||
// attributes set with unit suffixes
|
||||
if (currentValue !== null && regex.test(currentValue)) {
|
||||
const unit = trueDimension(currentValue).u || trueDimension(attrObj[p]).u;
|
||||
const suffix = /%/.test(unit) ? '_percent' : `_${unit}`;
|
||||
|
||||
// most "unknown" attributes cannot register into onStart, so we manually add them
|
||||
onStart[ComponentName][prop + suffix] = (tp) => {
|
||||
if (this.valuesEnd[tweenProp] && this.valuesEnd[tweenProp][tp] && !(tp in attributes)) {
|
||||
attributes[tp] = (elem, oneAttr, a, b, v) => {
|
||||
const _p = oneAttr.replace(suffix, '');
|
||||
/* eslint no-bitwise: ["error", { "allow": [">>"] }] */
|
||||
elem.setAttribute(_p, ((numbers(a.v, b.v, v) * 1000 >> 0) / 1000) + b.u);
|
||||
};
|
||||
}
|
||||
};
|
||||
attributesObject[prop + suffix] = trueDimension(attrObj[p]);
|
||||
} else if (!regex.test(attrObj[p]) || currentValue === null
|
||||
|| (currentValue !== null && !regex.test(currentValue))) {
|
||||
// most "unknown" attributes cannot register into onStart, so we manually add them
|
||||
onStart[ComponentName][prop] = (tp) => {
|
||||
if (this.valuesEnd[tweenProp] && this.valuesEnd[tweenProp][tp] && !(tp in attributes)) {
|
||||
attributes[tp] = (elem, oneAttr, a, b, v) => {
|
||||
elem.setAttribute(oneAttr, (numbers(a, b, v) * 1000 >> 0) / 1000);
|
||||
};
|
||||
}
|
||||
};
|
||||
attributesObject[prop] = parseFloat(attrObj[p]);
|
||||
}
|
||||
} else { // colors
|
||||
// most "unknown" attributes cannot register into onStart, so we manually add them
|
||||
onStart[ComponentName][prop] = (tp) => {
|
||||
if (this.valuesEnd[tweenProp] && this.valuesEnd[tweenProp][tp] && !(tp in attributes)) {
|
||||
attributes[tp] = (elem, oneAttr, a, b, v) => {
|
||||
elem.setAttribute(oneAttr, colors(a, b, v));
|
||||
};
|
||||
}
|
||||
};
|
||||
attributesObject[prop] = trueColor(attrObj[p]) || defaultValues.htmlAttributes[p];
|
||||
}
|
||||
});
|
||||
|
||||
return attributesObject;
|
||||
}
|
||||
|
||||
// All Component Functions
|
||||
const attrFunctions = {
|
||||
prepareStart: getAttr,
|
||||
prepareProperty: prepareAttr,
|
||||
onStart: onStartAttr,
|
||||
};
|
||||
|
||||
// Component Full
|
||||
const htmlAttributes = {
|
||||
component: ComponentName,
|
||||
property: 'attr',
|
||||
// the Animation class will need some values to validate this Object attribute
|
||||
subProperties: ['fill', 'stroke', 'stop-color', 'fill-opacity', 'stroke-opacity'],
|
||||
defaultValue: {
|
||||
fill: 'rgb(0,0,0)',
|
||||
stroke: 'rgb(0,0,0)',
|
||||
'stop-color': 'rgb(0,0,0)',
|
||||
opacity: 1,
|
||||
'stroke-opacity': 1,
|
||||
'fill-opacity': 1, // same here
|
||||
},
|
||||
Interpolate: { numbers, colors },
|
||||
functions: attrFunctions,
|
||||
// export to global for faster execution
|
||||
Util: { replaceUppercase, trueColor, trueDimension },
|
||||
};
|
||||
|
||||
export default htmlAttributes;
|
||||