Changes V2.2.0:

* major JSDoc write up
* removed ESLint `no-bitwise` exception, it only applies to specific functions and not the entire code
* the `SVGCubicMorph` component will remove un-necessary `Z` path commands when is the case for better out of the box animation
* fixed a minor disambiguation with `filterEffects` and `drop-shadow` property and its `dropshadow` interpolation function
* TypeScript strong: all files are modules, easy to implement in any third party app
* updated `CubicBezier` and SVGPathCommander
* code cleanup
This commit is contained in:
thednp 2021-12-08 23:43:31 +02:00
parent e5456b86e9
commit 2a5bac2bb3
396 changed files with 11485 additions and 7075 deletions

View file

@ -23,18 +23,19 @@
// Disable no-restricted-globals for global objects // Disable no-restricted-globals for global objects
"no-restricted-globals": 0, "no-restricted-globals": 0,
// Disable no-params-reassign for properties // Disable no-params-reassign for properties
"no-param-reassign": ["error", { "props": false }], // "no-param-reassign": ["error", { "props": false }],
// Allow strict mode (we are not dealing with modules) // Allow strict mode (we are not dealing with modules)
"strict": [0], // "strict": [0],
// Disable bitwise // Allow use of "private methods" - impossible to satisfy
"no-bitwise": 0, "no-underscore-dangle": 0
// Allow use of "private methods"
"no-underscore-dangle": 0,
// Disable alert rule till we have a CE in place // Disable alert rule till we have a CE in place
"no-alert": 0, // "no-alert": 0
// Allow extensions on imports // Allow extensions on imports
"import/extensions": 0, // "import/extensions": 0,
// Allow exporting mutable 'let' binding // Allow exporting mutable 'let' binding
"import/no-mutable-exports": 0 // "import/no-mutable-exports": 0,
// Allow no named as default / member
// "import/no-named-as-default": 0,
// "import/no-named-as-default-member": 0
} }
} }

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
node_modules/ node_modules/
experiments/
.npmignore .npmignore
package-lock.json package-lock.json

View file

@ -1,4 +1,5 @@
node_modules/ node_modules/
demo/ demo/
experiments/
package-lock.json package-lock.json
.gitignore .gitignore

View file

@ -1,6 +1,6 @@
# KUTE.js # KUTE.js
A modern JavaScript animation engine built on ES6+ standards with most essential features for the web, delivering easy to use methods to set up high performance, cross-browser animations. The focus is code quality, flexibility, performance and size. 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.
[![NPM Version](https://img.shields.io/npm/v/kute.js.svg?style=flat-square)](https://www.npmjs.com/package/kute.js) [![NPM Version](https://img.shields.io/npm/v/kute.js.svg?style=flat-square)](https://www.npmjs.com/package/kute.js)
[![NPM Downloads](https://img.shields.io/npm/dm/kute.js.svg?style=flat-square)](http://npm-stat.com/charts.html?package=kute.js) [![NPM Downloads](https://img.shields.io/npm/dm/kute.js.svg?style=flat-square)](http://npm-stat.com/charts.html?package=kute.js)
@ -42,22 +42,10 @@ All above mentioned components have a BASE version which doesn't include value p
For a complete developer guide, usage and stuff like npm, visit [the wiki](https://github.com/thednp/kute.js/wiki). For a complete developer guide, usage and stuff like npm, visit [the wiki](https://github.com/thednp/kute.js/wiki).
# ESLint
If you include KUTE.js in your project, we recommend using the following ESLint rule:
```js
rules: {
// Disable bitwise for isArcCommand & isPathCommand from SVGPathCommander
// as well as the KUTE.js interpolation functions
"no-bitwise": 0,
}
```
Some **SVGPathCommander** as well as **KUTE.js** interpolation functions make use of `|` (OR) and `>>` operators for fastest number operations.
# Browser Support # 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>. 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 # 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. * [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. * [Noah Veltman](https://github.com/veltman) for his awesome [flubber](https://github.com/veltman/flubber), another one of the sources for the SVGMorph component.
@ -65,8 +53,10 @@ KUTE.js is redeveloped for maximum performance on modern browsers. Some legacy b
* [Dmitry Baranovskiy](https://dmitry.baranovskiy.com/) for his awesome [Raphael.js](https://dmitrybaranovskiy.github.io/raphael/), another source for our SVGCubicMorph 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. * [@dalisoft](https://github.com/dalisoft) contributed a great deal to the performance and functionality of previous versions of KUTE.js.
# Contributions # Contributions
* [Contributors &amp; Collaborators](https://github.com/thednp/kute.js/graphs/contributors) * [Contributors &amp; Collaborators](https://github.com/thednp/kute.js/graphs/contributors)
# License # License
[MIT License](https://github.com/thednp/kute.js/blob/master/LICENSE) [MIT License](https://github.com/thednp/kute.js/blob/master/LICENSE)

View file

@ -78,18 +78,18 @@ function complete(){
container.style.display = 'none'; container.style.display = 'none';
} }
var engine = document.getElementById('kute'), var engine = document.getElementById('kute'),
fromCSS = { rotate3d: [ 0, 0,0 ], perspective:600 }, fromCSS = { rotate3d: [ 0, 0,0 ], perspective:600 },
fromMX = { transform: { rotate3d: [ 0, 0,0 ], perspective:600 }}, fromMX = { transform: { rotate3d: [ 0, 0,0 ], perspective:600 }},
toCSS = { rotate3d: [ 360,0,0 ], perspective:600 }, toCSS = { rotate3d: [ 360,0,0 ], perspective:600 },
toMX = { transform: { rotate3d: [ 0,360,0 ], perspective:600 }}, toMX = { transform: { rotate3d: [ 0,360,0 ], perspective:600 }},
ops = { duration: 2000, repeat: 5 } ops = { duration: 2000, repeat: 5 }
// since our engines don't do sync, we make it our own here // since our engines don't do sync, we make it our own here
if (engine.src.indexOf('kute.min.js')>-1) { if (!engine.src.includes('extra')) {
[].slice.call(collection).map((el,i) => { i===lastIdx && (ops.onComplete = complete); tws.push ( KUTE.fromTo(el,fromCSS,toCSS,ops) ) }) [].slice.call(collection).map((el,i) => { i===lastIdx && (ops.onComplete = complete); tws.push ( KUTE.fromTo(el,fromCSS,toCSS,ops) ) })
} }
if (engine.src.indexOf('kute-extra.min.js')>-1) { if (engine.src.includes('extra')) {
[].slice.call(collection).map((el,i) => { i===lastIdx && (ops.onComplete = complete); tws.push ( KUTE.fromTo(el,fromMX,toMX,ops) ) }) [].slice.call(collection).map((el,i) => { i===lastIdx && (ops.onComplete = complete); tws.push ( KUTE.fromTo(el,fromMX,toMX,ops) ) })
} }
@ -98,15 +98,13 @@ function startTest(){
infoContainer.style.display = 'none'; infoContainer.style.display = 'none';
container.style.display = 'block' container.style.display = 'block'
!tws[0].playing && startKUTE(); tws.length && !tws[0].playing && startKUTE();
} }
function startKUTE() { function startKUTE() {
var now = window.performance.now(), count = tws.length; var now = window.performance.now(), count = tws.length;
for (var t=0; t<count; t++){ tws.forEach((t) => t.start(now));
tws[t].start(now)
}
} }
// the start button handle // the start button handle

View file

@ -5,28 +5,22 @@ var morphOps = {
// basic morph // basic morph
var morphTween = KUTE.to('#rectangle', { path: '#star' }, morphOps); var morphTween = KUTE.to('#rectangle', { path: '#star' }, morphOps);
var morphTween1 = KUTE.to('#rectangle1', { path: '#star1' }, morphOps);
var morphTween2 = KUTE.to('#rectangle2', { path: '#star2' }, morphOps); var morphTween2 = KUTE.to('#rectangle2', { path: '#star2' }, morphOps);
var morphBtn = document.getElementById('morphBtn'); var morphBtn = document.getElementById('morphBtn');
morphBtn.addEventListener('click', function(){ morphBtn.addEventListener('click', function(){
!morphTween.playing && morphTween.start(); !morphTween.playing && morphTween.start();
!morphTween1.playing && morphTween1.start();
!morphTween2.playing && morphTween2.start(); !morphTween2.playing && morphTween2.start();
}, false); }, false);
// line to circle // line to circle
var lineMorph = KUTE.to('#line' ,{path:'#circle' }, morphOps); var lineMorph = KUTE.to('#line' ,{path:'#circle' }, morphOps);
var lineMorph1 = KUTE.to('#line1',{path:'#circle1'}, morphOps); var lineMorph1 = KUTE.to('#line1',{path:'#circle1'}, morphOps);
var lineMorph2 = KUTE.to('#line2',{path:'#circle2'}, morphOps);
var lineMorph3 = KUTE.to('#line3',{path:'#circle3'}, morphOps);
var morphBtnClosed = document.getElementById('morphBtnClosed')
var morphBtnClosed = document.getElementById('morphBtnClosed')
morphBtnClosed.addEventListener('click', function(){ morphBtnClosed.addEventListener('click', function(){
!lineMorph.playing && lineMorph.start(); !lineMorph.playing && lineMorph.start();
!lineMorph1.playing && lineMorph1.start(); !lineMorph1.playing && lineMorph1.start();
!lineMorph2.playing && lineMorph2.start();
!lineMorph3.playing && lineMorph3.start();
}, false); }, false);
var morphOps1 = { var morphOps1 = {
@ -63,19 +57,14 @@ var compliMorph2 = KUTE.fromTo('#symbol-left', {path: '#symbol-left'}, { path:
var compliMorph3 = KUTE.fromTo('#symbol-left-clone', {path: '#symbol-left-clone'}, { path: '#mouth' }, morphOps1); var compliMorph3 = KUTE.fromTo('#symbol-left-clone', {path: '#symbol-left-clone'}, { path: '#mouth' }, morphOps1);
var compliMorph4 = KUTE.fromTo('#symbol-right', {path: '#symbol-right'}, { path: '#eye-right' }, morphOps1); var compliMorph4 = KUTE.fromTo('#symbol-right', {path: '#symbol-right'}, { path: '#eye-right' }, morphOps1);
var compliMorph11 = KUTE.fromTo('#rectangle-container1', {path: '#rectangle-container1', attr:{ fill: "#9C27B0"} }, { path: '#circle-container1', attr:{ fill: "#FF5722"} }, morphOps1);
var compliMorph21 = KUTE.fromTo('#symbol-left1', {path: '#symbol-left1'}, { path: '#eye-left1' }, morphOps1);
var compliMorph31 = KUTE.fromTo('#symbol-left-clone1', {path: '#symbol-left-clone1'}, { path: '#mouth1' }, morphOps1);
var compliMorph41 = KUTE.fromTo('#symbol-right1', {path: '#symbol-right1'}, { path: '#eye-right1' }, morphOps1);
var compliMorph12 = KUTE.fromTo('#rectangle-container2', {path: '#rectangle-container2', attr:{ fill: "#e91b1f"} }, { path: '#circle-container2', attr:{ fill: "#FF5722"} }, morphOps1); var compliMorph12 = KUTE.fromTo('#rectangle-container2', {path: '#rectangle-container2', attr:{ fill: "#e91b1f"} }, { path: '#circle-container2', attr:{ fill: "#FF5722"} }, morphOps1);
var compliMorph22 = KUTE.fromTo('#symbol-left2', {path: '#symbol-left2'}, { path: '#eye-left2' }, morphOps1); var compliMorph22 = KUTE.fromTo('#symbol-left2', {path: '#symbol-left2'}, { path: '#eye-left2' }, morphOps1);
var compliMorph32 = KUTE.fromTo('#sample-shape2', {path: '#sample-shape2'}, { path: '#mouth2' }, morphOps1); var compliMorph32 = KUTE.fromTo('#sample-shape2', {path: '#sample-shape2'}, { path: '#mouth2' }, morphOps1);
var compliMorph42 = KUTE.fromTo('#symbol-right2', {path: '#symbol-right2'}, { path: '#eye-right2' }, morphOps1); var compliMorph42 = KUTE.fromTo('#symbol-right2', {path: '#symbol-right2'}, { path: '#eye-right2' }, morphOps1);
compliMorphBtn.addEventListener('click', function(){ compliMorphBtn.addEventListener('click', function(){
!compliMorph1.playing && compliMorph1.start() && compliMorph11.start() && compliMorph12.start(); !compliMorph1.playing && compliMorph1.start() && compliMorph12.start();
!compliMorph2.playing && compliMorph2.start() && compliMorph21.start() && compliMorph22.start(); !compliMorph2.playing && compliMorph2.start() && compliMorph22.start();
!compliMorph3.playing && compliMorph3.start() && compliMorph31.start() && compliMorph32.start(); !compliMorph3.playing && compliMorph3.start() && compliMorph32.start();
!compliMorph4.playing && compliMorph4.start() && compliMorph41.start() && compliMorph42.start(); !compliMorph4.playing && compliMorph4.start() && compliMorph42.start();
}, false); }, false);

View file

@ -203,7 +203,9 @@
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/bootstrap.native/1.0.1/bootstrap-native.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/bootstrap.native/1.0.1/bootstrap-native.min.js"></script>
<!-- <script src="../experiments/CSSMatrix.js"></script> -->
<script id="kute" src="./src/kute-extra.min.js"></script> <script id="kute" src="./src/kute-extra.min.js"></script>
<!-- <script id="kute" src="./src/kute-extra.js"></script> -->
<script src="./assets/js/perf-matrix.js"></script> <script src="./assets/js/perf-matrix.js"></script>
</body> </body>

View file

@ -1,5 +1,5 @@
/*! /*!
* KUTE.js Base v2.1.3 (http://thednp.github.io/kute.js) * KUTE.js Base v2.2.0alpha2 (http://thednp.github.io/kute.js)
* Copyright 2015-2021 © thednp * Copyright 2015-2021 © thednp
* Licensed under MIT (https://github.com/thednp/kute.js/blob/master/LICENSE) * Licensed under MIT (https://github.com/thednp/kute.js/blob/master/LICENSE)
*/ */
@ -9,21 +9,24 @@
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.KUTE = factory()); (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.KUTE = factory());
})(this, (function () { 'use strict'; })(this, (function () { 'use strict';
var KUTE = {}; /**
* The KUTE.js Execution Context
*/
var KEC = {};
var Tweens = []; var Tweens = [];
var globalObject; var gl0bal;
if (typeof global !== 'undefined') { globalObject = global; } if (typeof global !== 'undefined') { gl0bal = global; }
else if (typeof window !== 'undefined') { globalObject = window.self; } else if (typeof window !== 'undefined') { gl0bal = window.self; }
else { globalObject = {}; } else { gl0bal = {}; }
var globalObject$1 = globalObject; var globalObject = gl0bal;
// KUTE.js INTERPOLATE FUNCTIONS // KUTE.js INTERPOLATE FUNCTIONS
// ============================= // =============================
var Interpolate = {}; var interpolate = {};
// schedule property specific function on animation start // schedule property specific function on animation start
// link property update function to KUTE.js execution context // link property update function to KUTE.js execution context
@ -31,13 +34,13 @@
// Include a performance.now polyfill. // Include a performance.now polyfill.
// source https://github.com/tweenjs/tween.js/blob/master/src/Now.ts // source https://github.com/tweenjs/tween.js/blob/master/src/Now.ts
var now; var performanceNow;
// In node.js, use process.hrtime. // In node.js, use process.hrtime.
// eslint-disable-next-line // eslint-disable-next-line
// @ts-ignore // @ts-ignore
if (typeof self === 'undefined' && typeof process !== 'undefined' && process.hrtime) { if (typeof self === 'undefined' && typeof process !== 'undefined' && process.hrtime) {
now = function () { performanceNow = function () {
// eslint-disable-next-line // eslint-disable-next-line
// @ts-ignore // @ts-ignore
var time = process.hrtime(); var time = process.hrtime();
@ -49,24 +52,27 @@
// In a browser, use self.performance.now if it is available. // In a browser, use self.performance.now if it is available.
// This must be bound, because directly assigning this function // This must be bound, because directly assigning this function
// leads to an invocation exception in Chrome. // leads to an invocation exception in Chrome.
now = self.performance.now.bind(self.performance); performanceNow = self.performance.now.bind(self.performance);
} else if (typeof Date !== 'undefined' && Date.now) { } else if (typeof Date !== 'undefined' && Date.now) {
// Use Date.now if it is available. // Use Date.now if it is available.
now = Date.now; performanceNow = Date.now;
} else { } else {
// Otherwise, use 'new Date().getTime()'. // Otherwise, use 'new Date().getTime()'.
now = function () { return new Date().getTime(); }; performanceNow = function () { return new Date().getTime(); };
} }
var now$1 = now; var now = performanceNow;
var Time = {}; var Time = {};
Time.now = now$1; Time.now = now;
// const that = window.self || window || {};
// Time.now = that.performance.now.bind(that.performance);
// eslint-disable-next-line import/no-mutable-exports -- impossible to satisfy
var Tick = 0; var Tick = 0;
/**
*
* @param {number | Date} time
*/
var Ticker = function (time) { var Ticker = function (time) {
var i = 0; var i = 0;
while (i < Tweens.length) { while (i < Tweens.length) {
@ -87,38 +93,43 @@
Tick = null; Tick = null;
Object.keys(onStart).forEach(function (obj) { Object.keys(onStart).forEach(function (obj) {
if (typeof (onStart[obj]) === 'function') { if (typeof (onStart[obj]) === 'function') {
if (KUTE[obj]) { delete KUTE[obj]; } if (KEC[obj]) { delete KEC[obj]; }
} else { } else {
Object.keys(onStart[obj]).forEach(function (prop) { Object.keys(onStart[obj]).forEach(function (prop) {
if (KUTE[prop]) { delete KUTE[prop]; } if (KEC[prop]) { delete KEC[prop]; }
}); });
} }
}); });
Object.keys(Interpolate).forEach(function (i) { Object.keys(interpolate).forEach(function (i) {
if (KUTE[i]) { delete KUTE[i]; } if (KEC[i]) { delete KEC[i]; }
}); });
} }
}, 64); }, 64);
} }
// KUTE.js render update functions // render update functions
// =============================== // =======================
var Render = { var Render = {
Tick: Tick, Ticker: Ticker, Tweens: Tweens, Time: Time, Tick: Tick, Ticker: Ticker, Tweens: Tweens, Time: Time,
}; };
Object.keys(Render).forEach(function (blob) { Object.keys(Render).forEach(function (blob) {
if (!KUTE[blob]) { if (!KEC[blob]) {
KUTE[blob] = blob === 'Time' ? Time.now : Render[blob]; KEC[blob] = blob === 'Time' ? Time.now : Render[blob];
} }
}); });
globalObject$1._KUTE = KUTE; globalObject._KUTE = KEC;
var defaultOptions = { var defaultOptions = {
duration: 700, duration: 700,
delay: 0, delay: 0,
easing: 'linear', easing: 'linear',
repeat: 0,
repeatDelay: 0,
yoyo: false,
resetStart: false,
offset: 0,
}; };
// link properties to interpolate functions // link properties to interpolate functions
@ -138,30 +149,46 @@
var Util = {}; var Util = {};
var connect = {}; var connect = {};
/** @type {KUTE.TweenBase | KUTE.Tween | KUTE.TweenExtra} */
connect.tween = null;
connect.processEasing = null;
// Select Robert Penner's Easing Functions // Select Robert Penner's Easing Functions
// updated for ESLint // updated for ESLint
var Easing = { var Easing = {
/** @type {KUTE.easingFunction} */
linear: function (t) { return t; }, linear: function (t) { return t; },
/** @type {KUTE.easingFunction} */
easingQuadraticIn: function (t) { return t * t; }, easingQuadraticIn: function (t) { return t * t; },
/** @type {KUTE.easingFunction} */
easingQuadraticOut: function (t) { return t * (2 - t); }, easingQuadraticOut: function (t) { return t * (2 - t); },
/** @type {KUTE.easingFunction} */
easingQuadraticInOut: function (t) { return (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t); }, easingQuadraticInOut: function (t) { return (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t); },
/** @type {KUTE.easingFunction} */
easingCubicIn: function (t) { return t * t * t; }, easingCubicIn: function (t) { return t * t * t; },
/** @type {KUTE.easingFunction} */
easingCubicOut: function (t0) { var t = t0 - 1; return t * t * t + 1; }, easingCubicOut: function (t0) { var t = t0 - 1; return t * t * t + 1; },
/** @type {KUTE.easingFunction} */
easingCubicInOut: function (t) { return (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1); }, easingCubicInOut: function (t) { return (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1); },
/** @type {KUTE.easingFunction} */
easingCircularIn: function (t) { return -(Math.sqrt(1 - (t * t)) - 1); }, easingCircularIn: function (t) { return -(Math.sqrt(1 - (t * t)) - 1); },
/** @type {KUTE.easingFunction} */
easingCircularOut: function (t0) { var t = t0 - 1; return Math.sqrt(1 - t * t); }, easingCircularOut: function (t0) { var t = t0 - 1; return Math.sqrt(1 - t * t); },
/** @type {KUTE.easingFunction} */
easingCircularInOut: function (t0) { easingCircularInOut: function (t0) {
var t = t0 * 2; var t = t0 * 2;
if (t < 1) { return -0.5 * (Math.sqrt(1 - t * t) - 1); } if (t < 1) { return -0.5 * (Math.sqrt(1 - t * t) - 1); }
t -= 2; return 0.5 * (Math.sqrt(1 - t * t) + 1); t -= 2; return 0.5 * (Math.sqrt(1 - t * t) + 1);
}, },
/** @type {KUTE.easingFunction} */
easingBackIn: function (t) { var s = 1.70158; return t * t * ((s + 1) * t - s); }, easingBackIn: function (t) { var s = 1.70158; return t * t * ((s + 1) * t - s); },
/** @type {KUTE.easingFunction} */
easingBackOut: function (t0) { easingBackOut: function (t0) {
var s = 1.70158; var s = 1.70158;
var t = t0 - 1; var t = t0 - 1;
return t * t * ((s + 1) * t + s) + 1; return t * t * ((s + 1) * t + s) + 1;
}, },
/** @type {KUTE.easingFunction} */
easingBackInOut: function (t0) { easingBackInOut: function (t0) {
var s = 1.70158 * 1.525; var s = 1.70158 * 1.525;
var t = t0 * 2; var t = t0 * 2;
@ -170,6 +197,12 @@
}, },
}; };
/**
* Returns a valid `easingFunction`.
*
* @param {KUTE.easingFunction | string} fn function name or constructor name
* @returns {KUTE.easingFunction} a valid easing function
*/
function processEasing(fn) { function processEasing(fn) {
if (typeof fn === 'function') { if (typeof fn === 'function') {
return fn; return fn;
@ -181,19 +214,42 @@
connect.processEasing = processEasing; connect.processEasing = processEasing;
function add (tw) { return Tweens.push(tw); } /**
* KUTE.add(Tween)
*
* @param {KUTE.Tween} tw a new tween to add
*/
var add = function (tw) { return Tweens.push(tw); };
function remove (tw) { /**
* KUTE.remove(Tween)
*
* @param {KUTE.Tween} tw a new tween to add
*/
var remove = function (tw) {
var i = Tweens.indexOf(tw); var i = Tweens.indexOf(tw);
if (i !== -1) { Tweens.splice(i, 1); } if (i !== -1) { Tweens.splice(i, 1); }
} };
function getAll () { return Tweens; } /**
* KUTE.add(Tween)
*
* @return {KUTE.Tween[]} tw a new tween to add
*/
var getAll = function () { return Tweens; };
function removeAll () { Tweens.length = 0; } /**
* KUTE.removeAll()
*/
var removeAll = function () { Tweens.length = 0; };
// all supported properties
var supportedProperties = {}; var supportedProperties = {};
/**
* linkInterpolation
* @this {KUTE.Tween}
*/
function linkInterpolation() { function linkInterpolation() {
var this$1$1 = this; var this$1$1 = this;
// DON'T change // DON'T change
@ -205,18 +261,18 @@
if (typeof (componentLink[fnObj]) === 'function' // ATTR, colors, scroll, boxModel, borderRadius if (typeof (componentLink[fnObj]) === 'function' // ATTR, colors, scroll, boxModel, borderRadius
&& Object.keys(this$1$1.valuesEnd).some(function (i) { return (componentProps && componentProps.includes(i)) && Object.keys(this$1$1.valuesEnd).some(function (i) { return (componentProps && componentProps.includes(i))
|| (i === 'attr' && Object.keys(this$1$1.valuesEnd[i]).some(function (j) { return componentProps && componentProps.includes(j); })); })) { || (i === 'attr' && Object.keys(this$1$1.valuesEnd[i]).some(function (j) { return componentProps && componentProps.includes(j); })); })) {
if (!KUTE[fnObj]) { KUTE[fnObj] = componentLink[fnObj]; } if (!KEC[fnObj]) { KEC[fnObj] = componentLink[fnObj]; }
} else { } else {
Object.keys(this$1$1.valuesEnd).forEach(function (prop) { Object.keys(this$1$1.valuesEnd).forEach(function (prop) {
var propObject = this$1$1.valuesEnd[prop]; var propObject = this$1$1.valuesEnd[prop];
if (propObject instanceof Object) { if (propObject instanceof Object) {
Object.keys(propObject).forEach(function (i) { Object.keys(propObject).forEach(function (i) {
if (typeof (componentLink[i]) === 'function') { // transformCSS3 if (typeof (componentLink[i]) === 'function') { // transformCSS3
if (!KUTE[i]) { KUTE[i] = componentLink[i]; } if (!KEC[i]) { KEC[i] = componentLink[i]; }
} else { } else {
Object.keys(componentLink[fnObj]).forEach(function (j) { Object.keys(componentLink[fnObj]).forEach(function (j) {
if (componentLink[i] && typeof (componentLink[i][j]) === 'function') { // transformMatrix if (componentLink[i] && typeof (componentLink[i][j]) === 'function') { // transformMatrix
if (!KUTE[j]) { KUTE[j] = componentLink[i][j]; } if (!KEC[j]) { KEC[j] = componentLink[i][j]; }
} }
}); });
} }
@ -228,7 +284,7 @@
}); });
} }
var Internals = { var internals = {
add: add, add: add,
remove: remove, remove: remove,
getAll: getAll, getAll: getAll,
@ -237,7 +293,15 @@
linkInterpolation: linkInterpolation, linkInterpolation: linkInterpolation,
}; };
// a public selector utility /**
* selector
*
* A selector utility for KUTE.js.
*
* @param {KUTE.selectorType} el target(s) or string selector
* @param {boolean | number} multi when true returns an array/collection of elements
* @returns {Element | Element[] | null}
*/
function selector(el, multi) { function selector(el, multi) {
try { try {
var requestedElem; var requestedElem;
@ -256,12 +320,17 @@
} }
} }
// Animation class /**
* 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.
*/
var AnimationBase = function AnimationBase(Component) { var AnimationBase = function AnimationBase(Component) {
return this.setComponent(Component);
};
AnimationBase.prototype.setComponent = function setComponent (Component) {
var ComponentName = Component.component; var ComponentName = Component.component;
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty } // const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty }
var Functions = { onStart: onStart, onComplete: onComplete }; var Functions = { onStart: onStart, onComplete: onComplete };
@ -276,9 +345,10 @@
// set additional options // set additional options
if (Component.defaultOptions) { if (Component.defaultOptions) {
Object.keys(Component.defaultOptions).forEach(function (op) { // Object.keys(Component.defaultOptions).forEach((op) => {
defaultOptions[op] = Component.defaultOptions[op]; // defaultOptions[op] = Component.defaultOptions[op];
}); // });
Object.assign(defaultOptions, Component.defaultOptions);
} }
// set functions // set functions
@ -310,12 +380,12 @@
if (Component.Interpolate) { if (Component.Interpolate) {
Object.keys(Component.Interpolate).forEach(function (fni) { Object.keys(Component.Interpolate).forEach(function (fni) {
var compIntObj = Component.Interpolate[fni]; var compIntObj = Component.Interpolate[fni];
if (typeof (compIntObj) === 'function' && !Interpolate[fni]) { if (typeof (compIntObj) === 'function' && !interpolate[fni]) {
Interpolate[fni] = compIntObj; interpolate[fni] = compIntObj;
} else { } else {
Object.keys(compIntObj).forEach(function (sfn) { Object.keys(compIntObj).forEach(function (sfn) {
if (typeof (compIntObj[sfn]) === 'function' && !Interpolate[fni]) { if (typeof (compIntObj[sfn]) === 'function' && !interpolate[fni]) {
Interpolate[fni] = compIntObj[sfn]; interpolate[fni] = compIntObj[sfn];
} }
}); });
} }
@ -334,62 +404,132 @@
return { name: ComponentName }; return { name: ComponentName };
}; };
/**
* Perspective Interpolation Function.
*
* @param {number} a start value
* @param {number} b end value
* @param {string} u unit
* @param {number} v progress
* @returns {string} the perspective function in string format
*/
function perspective(a, b, u, v) { function perspective(a, b, u, v) {
// eslint-disable-next-line no-bitwise
return ("perspective(" + (((a + (b - a) * v) * 1000 >> 0) / 1000) + u + ")"); return ("perspective(" + (((a + (b - a) * v) * 1000 >> 0) / 1000) + u + ")");
} }
/**
* Translate 3D Interpolation Function.
*
* @param {number[]} a start [x,y,z] position
* @param {number[]} b end [x,y,z] position
* @param {string} u unit, usually `px` degrees
* @param {number} v progress
* @returns {string} the interpolated 3D translation string
*/
function translate3d(a, b, u, v) { function translate3d(a, b, u, v) {
var translateArray = []; var translateArray = [];
for (var ax = 0; ax < 3; ax += 1) { for (var ax = 0; ax < 3; ax += 1) {
translateArray[ax] = (a[ax] || b[ax] translateArray[ax] = (a[ax] || b[ax]
// eslint-disable-next-line no-bitwise
? ((a[ax] + (b[ax] - a[ax]) * v) * 1000 >> 0) / 1000 : 0) + u; ? ((a[ax] + (b[ax] - a[ax]) * v) * 1000 >> 0) / 1000 : 0) + u;
} }
return ("translate3d(" + (translateArray.join(',')) + ")"); return ("translate3d(" + (translateArray.join(',')) + ")");
} }
/**
* 3D Rotation Interpolation Function.
*
* @param {number} a start [x,y,z] angles
* @param {number} b end [x,y,z] angles
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated 3D rotation string
*/
function rotate3d(a, b, u, v) { function rotate3d(a, b, u, v) {
var rotateStr = ''; var rotateStr = '';
// eslint-disable-next-line no-bitwise
rotateStr += a[0] || b[0] ? ("rotateX(" + (((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u + ")") : ''; rotateStr += a[0] || b[0] ? ("rotateX(" + (((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u + ")") : '';
// eslint-disable-next-line no-bitwise
rotateStr += a[1] || b[1] ? ("rotateY(" + (((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u + ")") : ''; rotateStr += a[1] || b[1] ? ("rotateY(" + (((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u + ")") : '';
// eslint-disable-next-line no-bitwise
rotateStr += a[2] || b[2] ? ("rotateZ(" + (((a[2] + (b[2] - a[2]) * v) * 1000 >> 0) / 1000) + u + ")") : ''; rotateStr += a[2] || b[2] ? ("rotateZ(" + (((a[2] + (b[2] - a[2]) * v) * 1000 >> 0) / 1000) + u + ")") : '';
return rotateStr; return rotateStr;
} }
/**
* Translate 2D Interpolation Function.
*
* @param {number[]} a start [x,y] position
* @param {number[]} b end [x,y] position
* @param {string} u unit, usually `px` degrees
* @param {number} v progress
* @returns {string} the interpolated 2D translation string
*/
function translate(a, b, u, v) { function translate(a, b, u, v) {
var translateArray = []; var translateArray = [];
// eslint-disable-next-line no-bitwise
translateArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u; translateArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u;
// eslint-disable-next-line no-bitwise
translateArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0'; translateArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0';
return ("translate(" + (translateArray.join(',')) + ")"); return ("translate(" + (translateArray.join(',')) + ")");
} }
/**
* 2D Rotation Interpolation Function.
*
* @param {number} a start angle
* @param {number} b end angle
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated rotation
*/
function rotate(a, b, u, v) { function rotate(a, b, u, v) {
// eslint-disable-next-line no-bitwise
return ("rotate(" + (((a + (b - a) * v) * 1000 >> 0) / 1000) + u + ")"); return ("rotate(" + (((a + (b - a) * v) * 1000 >> 0) / 1000) + u + ")");
} }
/**
* Scale Interpolation Function.
*
* @param {number} a start scale
* @param {number} b end scale
* @param {number} v progress
* @returns {string} the interpolated scale
*/
function scale(a, b, v) { function scale(a, b, v) {
// eslint-disable-next-line no-bitwise
return ("scale(" + (((a + (b - a) * v) * 1000 >> 0) / 1000) + ")"); return ("scale(" + (((a + (b - a) * v) * 1000 >> 0) / 1000) + ")");
} }
/**
* Skew Interpolation Function.
*
* @param {number} a start {x,y} angles
* @param {number} b end {x,y} angles
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated string value of skew(s)
*/
function skew(a, b, u, v) { function skew(a, b, u, v) {
var skewArray = []; var skewArray = [];
// eslint-disable-next-line no-bitwise
skewArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u; skewArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u;
// eslint-disable-next-line no-bitwise
skewArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0'; skewArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0';
return ("skew(" + (skewArray.join(',')) + ")"); return ("skew(" + (skewArray.join(',')) + ")");
} }
/* transformFunctions = {
property: 'transform',
subProperties,
defaultValues,
Interpolate: {translate,rotate,skew,scale},
functions } */
// same to svg transform, attr
// Component Functions // Component Functions
/**
* Sets the property update function.
* * same to svgTransform, htmlAttributes
* @param {string} tweenProp the property name
*/
function onStartTransform(tweenProp) { function onStartTransform(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
KUTE[tweenProp] = function (elem, a, b, v) { KEC[tweenProp] = function (elem, a, b, v) {
// eslint-disable-next-line no-param-reassign
elem.style[tweenProp] = (a.perspective || b.perspective ? perspective(a.perspective, b.perspective, 'px', v) : '') // one side might be 0 elem.style[tweenProp] = (a.perspective || b.perspective ? perspective(a.perspective, b.perspective, 'px', v) : '') // one side might be 0
+ (a.translate3d ? translate3d(a.translate3d, b.translate3d, 'px', v) : '') // array [x,y,z] + (a.translate3d ? translate3d(a.translate3d, b.translate3d, 'px', v) : '') // array [x,y,z]
+ (a.rotate3d ? rotate3d(a.rotate3d, b.rotate3d, 'deg', v) : '') // array [x,y,z] + (a.rotate3d ? rotate3d(a.rotate3d, b.rotate3d, 'deg', v) : '') // array [x,y,z]
@ -400,7 +540,7 @@
} }
// Base Component // Base Component
var BaseTransform = { var TransformFunctionsBase = {
component: 'baseTransform', component: 'baseTransform',
property: 'transform', property: 'transform',
functions: { onStart: onStartTransform }, functions: { onStart: onStartTransform },
@ -415,7 +555,15 @@
}, },
}; };
function numbers(a, b, v) { // number1, number2, progress /**
* Numbers Interpolation Function.
*
* @param {number} a start value
* @param {number} b end value
* @param {number} v progress
* @returns {number} the interpolated number
*/
function numbers(a, b, v) {
var A = +a; var A = +a;
var B = b - a; var B = b - a;
// a = +a; b -= a; // a = +a; b -= a;
@ -423,12 +571,20 @@
} }
// Component Functions // Component Functions
/**
* Sets the update function for the property.
* @param {string} tweenProp the property name
*/
function boxModelOnStart(tweenProp) { function boxModelOnStart(tweenProp) {
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
KUTE[tweenProp] = function (elem, a, b, v) { KEC[tweenProp] = function (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 elem.style[tweenProp] = (v > 0.99 || v < 0.01
? ((numbers(a, b, v) * 10) >> 0) / 10 ? ((numbers(a, b, v) * 10) >> 0) / 10
: (numbers(a, b, v)) >> 0) + "px"; : (numbers(a, b, v)) >> 0) + "px";
/* eslint-enable no-bitwise */
/* eslint-enable no-param-reassign */
}; };
} }
} }
@ -439,7 +595,7 @@
baseBoxProps.forEach(function (x) { baseBoxOnStart[x] = boxModelOnStart; }); baseBoxProps.forEach(function (x) { baseBoxOnStart[x] = boxModelOnStart; });
// Component Base // Component Base
var baseBoxModel = { var BoxModelBase = {
component: 'baseBoxModel', component: 'baseBoxModel',
category: 'boxModel', category: 'boxModel',
properties: baseBoxProps, properties: baseBoxProps,
@ -455,17 +611,23 @@
} */ } */
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
function onStartOpacity(tweenProp/* , value */) { function onStartOpacity(tweenProp/* , value */) {
// opacity could be 0 sometimes, we need to check regardless // opacity could be 0 sometimes, we need to check regardless
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
KUTE[tweenProp] = function (elem, a, b, v) { KEC[tweenProp] = function (elem, a, b, v) {
/* eslint-disable */
elem.style[tweenProp] = ((numbers(a, b, v) * 1000) >> 0) / 1000; elem.style[tweenProp] = ((numbers(a, b, v) * 1000) >> 0) / 1000;
/* eslint-enable */
}; };
} }
} }
// Base Component // Base Component
var baseOpacity = { var OpacityPropertyBase = {
component: 'baseOpacity', component: 'baseOpacity',
property: 'opacity', property: 'opacity',
// defaultValue: 1, // defaultValue: 1,
@ -473,13 +635,13 @@
functions: { onStart: onStartOpacity }, functions: { onStart: onStartOpacity },
}; };
// import {baseCrossBrowserMove} from '../components/crossBrowserMove.js' // import {baseCrossBrowserMove} from '../components/crossBrowserMove'
// support for kute-base.js ends here // support for kute-base ends here
var Components = { var Components = {
Transform: new AnimationBase(BaseTransform), Transform: new AnimationBase(TransformFunctionsBase),
BoxModel: new AnimationBase(baseBoxModel), BoxModel: new AnimationBase(BoxModelBase),
Opacity: new AnimationBase(baseOpacity), Opacity: new AnimationBase(OpacityPropertyBase),
}; };
function queueStart() { function queueStart() {
@ -500,21 +662,28 @@
linkInterpolation.call(this); linkInterpolation.call(this);
} }
// single Tween object construct /**
// TweenBase is meant to be use for pre-processed values * The `TweenBase` constructor creates a new `Tween` object
* for a single `HTMLElement` and returns it.
*
* `TweenBase` is meant to be used with pre-processed values.
*/
var TweenBase = function TweenBase(targetElement, startObject, endObject, opsObject) { var TweenBase = function TweenBase(targetElement, startObject, endObject, opsObject) {
var this$1$1 = this; var this$1$1 = this;
// element animation is applied to // element animation is applied to
this.element = targetElement; this.element = targetElement;
/** @type {boolean} */
this.playing = false; this.playing = false;
/** @type {number?} */
this._startTime = null; this._startTime = null;
/** @type {boolean} */
this._startFired = false; this._startFired = false;
this.valuesEnd = endObject; // valuesEnd // type is set via KUTE.tweenProps
this.valuesStart = startObject; // valuesStart this.valuesEnd = endObject;
this.valuesStart = startObject;
// OPTIONS // OPTIONS
var options = opsObject || {}; var options = opsObject || {};
@ -522,8 +691,11 @@
// used by to() method and expects object : {} / false // used by to() method and expects object : {} / false
this._resetStart = options.resetStart || 0; this._resetStart = options.resetStart || 0;
// you can only set a core easing function as default // you can only set a core easing function as default
/** @type {KUTE.easingOption} */
this._easing = typeof (options.easing) === 'function' ? options.easing : connect.processEasing(options.easing); this._easing = typeof (options.easing) === 'function' ? options.easing : connect.processEasing(options.easing);
/** @type {number} */
this._duration = options.duration || defaultOptions.duration; // duration option | default this._duration = options.duration || defaultOptions.duration; // duration option | default
/** @type {number} */
this._delay = options.delay || defaultOptions.delay; // delay option | default this._delay = options.delay || defaultOptions.delay; // delay option | default
// set other options // set other options
@ -542,22 +714,24 @@
var easingFnName = this._easing.name; var easingFnName = this._easing.name;
if (!onStart[easingFnName]) { if (!onStart[easingFnName]) {
onStart[easingFnName] = function easingFn(prop) { onStart[easingFnName] = function easingFn(prop) {
if (!KUTE[prop] && prop === this._easing.name) { KUTE[prop] = this._easing; } if (!KEC[prop] && prop === this._easing.name) { KEC[prop] = this._easing; }
}; };
} }
return this; return this;
}; };
// tween prototype /**
// queue tween object to main frame update * Starts tweening
// move functions that use the ticker outside the prototype to be in the same scope with it * @param {number?} time the tween start time
* @returns {TweenBase} this instance
*/
TweenBase.prototype.start = function start (time) { TweenBase.prototype.start = function start (time) {
// now it's a good time to start // now it's a good time to start
add(this); add(this);
this.playing = true; this.playing = true;
this._startTime = typeof time !== 'undefined' ? time : KUTE.Time(); this._startTime = typeof time !== 'undefined' ? time : KEC.Time();
this._startTime += this._delay; this._startTime += this._delay;
if (!this._startFired) { if (!this._startFired) {
@ -574,6 +748,10 @@
return this; return this;
}; };
/**
* Stops tweening
* @returns {TweenBase} this instance
*/
TweenBase.prototype.stop = function stop () { TweenBase.prototype.stop = function stop () {
if (this.playing) { if (this.playing) {
remove(this); remove(this);
@ -587,6 +765,9 @@
return this; return this;
}; };
/**
* Trigger internal completion callbacks.
*/
TweenBase.prototype.close = function close () { TweenBase.prototype.close = function close () {
var this$1$1 = this; var this$1$1 = this;
@ -601,20 +782,33 @@
stop.call(this); stop.call(this);
}; };
/**
* Schedule another tween instance to start once this one completes.
* @param {KUTE.chainOption} args the tween animation start time
* @returns {TweenBase} this instance
*/
TweenBase.prototype.chain = function chain (args) { TweenBase.prototype.chain = function chain (args) {
this._chain = []; this._chain = [];
this._chain = args.length ? args : this._chain.concat(args); this._chain = args.length ? args : this._chain.concat(args);
return this; return this;
}; };
/**
* Stop tweening the chained tween instances.
*/
TweenBase.prototype.stopChainedTweens = function stopChainedTweens () { TweenBase.prototype.stopChainedTweens = function stopChainedTweens () {
if (this._chain && this._chain.length) { this._chain.forEach(function (tw) { return tw.stop(); }); } if (this._chain && this._chain.length) { this._chain.forEach(function (tw) { return tw.stop(); }); }
}; };
/**
* Update the tween on each tick.
* @param {number} time the tick time
* @returns {boolean} this instance
*/
TweenBase.prototype.update = function update (time) { TweenBase.prototype.update = function update (time) {
var this$1$1 = this; var this$1$1 = this;
var T = time !== undefined ? time : KUTE.Time(); var T = time !== undefined ? time : KEC.Time();
var elapsed; var elapsed;
@ -628,7 +822,7 @@
// render the update // render the update
Object.keys(this.valuesEnd).forEach(function (tweenProp) { Object.keys(this.valuesEnd).forEach(function (tweenProp) {
KUTE[tweenProp](this$1$1.element, KEC[tweenProp](this$1$1.element,
this$1$1.valuesStart[tweenProp], this$1$1.valuesStart[tweenProp],
this$1$1.valuesEnd[tweenProp], this$1$1.valuesEnd[tweenProp],
progress); progress);
@ -665,13 +859,32 @@
// Update Tween Interface // Update Tween Interface
connect.tween = TweenBase; connect.tween = TweenBase;
var TweenConstructor = connect.tween;
/**
* The `KUTE.fromTo()` static method returns a new Tween object
* for a single `HTMLElement` at a given state.
*
* @param {Element} element target element
* @param {KUTE.tweenProps} startObject
* @param {KUTE.tweenProps} endObject
* @param {KUTE.tweenOptions} optionsObj tween options
* @returns {KUTE.Tween} the resulting Tween object
*/
function fromTo(element, startObject, endObject, optionsObj) { function fromTo(element, startObject, endObject, optionsObj) {
var options = optionsObj || {}; var options = optionsObj || {};
var TweenConstructor = connect.tween;
return new TweenConstructor(selector(element), startObject, endObject, options); return new TweenConstructor(selector(element), startObject, endObject, options);
} }
var version = "2.1.3"; var version = "2.2.0alpha2";
// @ts-ignore
/**
* A global namespace for library version.
* @type {string}
*/
var Version = version;
var indexBase = { var indexBase = {
Animation: AnimationBase, Animation: AnimationBase,
@ -684,10 +897,10 @@
Easing: Easing, Easing: Easing,
Util: Util, Util: Util,
Render: Render, Render: Render,
Interpolate: Interpolate, Interpolate: interpolate,
Internals: Internals, Internals: internals,
Selector: selector, Selector: selector,
Version: version, Version: Version,
}; };
return indexBase; return indexBase;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -94,9 +94,9 @@
<p>The component will process paths and out of the box will provide the closest possible interpolation by default. It also implements a series of solutions from <p>The component will process paths and out of the box will provide the closest possible interpolation by default. It also implements a series of solutions from
<a href="https://github.com/paperjs/paper.js/">Paper.js</a> to determine paths draw direction and automatically reverse one of them for most accurate presentation and as a result <a href="https://github.com/paperjs/paper.js/">Paper.js</a> to determine paths draw direction and automatically reverse one of them for most accurate presentation and as a result
the previously featured options <kbd>reverseFirstPath</kbd> and <kbd>reverseSecondPath</kbd> have been deprecated.</p> the previously featured options <kbd>reverseFirstPath</kbd> and <kbd>reverseSecondPath</kbd> have been deprecated.</p>
<p>The main difference with the <a href="svgMorph.html">SVG Morph</a> component is the fact that this components is converting all path commands to <i>cubicBezierTo</i>, <p>The main difference with the <a href="svgMorph.html">SVG Morph</a> component is the fact that this components is converting all path commands to <i>cubicBezierTo</i>, giving it
giving it the upper hand over the original morph component. While the other component will spend time to process the path data and create polygons, this component should deliver the upper hand over the original morph component in many regards. While the other component will spend time to process the path data and create polygons, this component should
the animation faster and using considerably less power.</p> deliver the animation faster and using considerably less power.</p>
<p>All path processing is powered by our <a href="https://github.com/thednp/svg-path-commander">SVGPathCommander</a> starting KUTE.js version 2.0.14, which aims to modernize and <p>All path processing is powered by our <a href="https://github.com/thednp/svg-path-commander">SVGPathCommander</a> starting KUTE.js version 2.0.14, which aims to modernize and
improve the path processing and enable transition from closed to and from un-closed shapes.</p> improve the path processing and enable transition from closed to and from un-closed shapes.</p>
</div> </div>
@ -131,13 +131,9 @@ var tween = KUTE.to('#rectangle', { path: 'M301.113,12.011l99.25,179.996l201.864
<div class="featurettes"> <div class="featurettes">
<svg class="example-box-model example-box" id="morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"> <svg class="example-box-model example-box" id="morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<path id="rectangle" class="bg-red" d="M559,597.4H43.6c-21,0-38-17-38-38V44c0-21,17-38,38-38H559c21,0,38,17,38,38v515.4 C597,580.4,580,597.4,559,597.4z"/> <path id="rectangle" class="bg-olive" d="M559,597.4H43.6c-21,0-38-17-38-38V44c0-21,17-38,38-38H559c21,0,38,17,38,38v515.4 C597,580.4,580,597.4,559,597.4z"/>
<path id="star" style="visibility:hidden" d="M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808 l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011z"/> <path id="star" style="visibility:hidden" d="M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808 l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011z"/>
</svg> </svg>
<svg class="example-box-model example-box" id="morph-example1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<path id="rectangle1" class="bg-olive" d="M559,597.4H43.6c-21,0-38-17-38-38V44c0-21,17-38,38-38H559c21,0,38,17,38,38v515.4 C597,580.4,580,597.4,559,597.4"/>
<path id="star1" style="visibility:hidden" d="M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808 l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011"/>
</svg>
<svg class="example-box-model example-box" id="morph-example2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"> <svg class="example-box-model example-box" id="morph-example2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<path id="rectangle2" class="bg-blue" d="M559,597.4H302.1H43.6c-21,0-38-17-38-38V300V44c0-21,17-38,38-38H300h259c21,0,38,17,38,38 <path id="rectangle2" class="bg-blue" d="M559,597.4H302.1H43.6c-21,0-38-17-38-38V300V44c0-21,17-38,38-38H300h259c21,0,38,17,38,38
v257.7v257.7C597,580.4,580,597.4,559,597.4"/> v257.7v257.7C597,580.4,580,597.4,559,597.4"/>
@ -153,15 +149,12 @@ var tween = KUTE.to('#rectangle', { path: 'M301.113,12.011l99.25,179.996l201.864
<p><b>Some takeaways:</b></p> <p><b>Some takeaways:</b></p>
<ul> <ul>
<li>The <b class="text-red">red shape</b> and its corresponding end shape are both the originals, un-edited shapes, both have the <code>Z</code> path command, notice a strange line at the bottom-right of the rectangle <li>The <b class="text-olive">olive shape</b> and its corresponding end shape are both the originals, un-edited shapes.</li>
during the animation. We'll have another example about that line.</li>
<li>The <b class="text-olive">olive shape</b> and its corresponding end shape both have been edited by removing the <code>Z</code> path command, notice the strange line during the animation is gone, also a different
presentation.</li>
<li>The <b class="text-blue">blue shape</b> and its corresponding end shape have been edited by removing their <code>Z</code> path commands and by adding additional curve points using a vector graphics editor to match <li>The <b class="text-blue">blue shape</b> and its corresponding end shape have been edited by removing their <code>Z</code> path commands and by adding additional curve points using a vector graphics editor to match
the amount of points in both shapes.</li> the amount of points in both shapes.</li>
</ul> </ul>
<p>In this example we focus on experimentation to discover ways to optimize the morph animation so that the points travel optimal distance. Keep in mind that the <code>Z</code> path command is actually a shorthand <p>In this example we focus on experimentation to discover ways to optimize the morph animation so that the points travel optimal distance. Keep in mind that the <code>Z</code> path command is actually a shorthand
for <code>L</code> (line path command), sometimes it's required to close the shape, our shapes here happen to be OK without it.</p> for <code>L</code> (line path command), sometimes it's required to close the shape, however the path processing tools will remove it or replace it when converting path segments to <code>C</code> cubic-bezier.</p>
<p>Each morph animation as well as each pair of shapes can have its own quirks. You can use the technique on your shapes to optimize the animation to your style. Chris Coyier wrote <p>Each morph animation as well as each pair of shapes can have its own quirks. You can use the technique on your shapes to optimize the animation to your style. Chris Coyier wrote
<a href="https://css-tricks.com/svg-shape-morphing-works/">an excelent article</a> in which he explains the terminology and workflow on how SVG morphing animation works with simple examples.</p> <a href="https://css-tricks.com/svg-shape-morphing-works/">an excelent article</a> in which he explains the terminology and workflow on how SVG morphing animation works with simple examples.</p>
@ -192,14 +185,6 @@ var tween = KUTE.to('#line', { path: '#circle' }).start();
<path id="line1" fill="transparent" stroke="#4CAF50" stroke-linejoin="round" stroke-width="15" d="M10 300 L580 300"/> <path id="line1" fill="transparent" stroke="#4CAF50" stroke-linejoin="round" stroke-width="15" d="M10 300 L580 300"/>
<path id="circle1" style="visibility:hidden" d="M10,300a290,290 0 1,1 580,0a290,290 0 1,1 -580,0z"/> <path id="circle1" style="visibility:hidden" d="M10,300a290,290 0 1,1 580,0a290,290 0 1,1 -580,0z"/>
</svg> </svg>
<svg class="example-box-model example-box" id="morph-example-closed2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<path id="line2" fill="transparent" stroke="#2196F3" stroke-linejoin="round" stroke-width="15" d="M10 300 L580 300z"/>
<path id="circle2" style="visibility:hidden" d="M10,300a290,290 0 1,1 580,0a290,290 0 1,1 -580,0"/>
</svg>
<svg class="example-box-model example-box" id="morph-example-closed3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<path id="line3" fill="transparent" stroke="#e91b1f" stroke-linejoin="round" stroke-width="15" d="M10 300 L580 300"/>
<path id="circle3" style="visibility:hidden" d="M10,300a290,290 0 1,1 580,0a290,290 0 1,1 -580,0"/>
</svg>
<div class="example-buttons"> <div class="example-buttons">
<a id="morphBtnClosed" class="btn btn-green" href="javascript:void(0)">Start</a> <a id="morphBtnClosed" class="btn btn-green" href="javascript:void(0)">Start</a>
</div> </div>
@ -208,16 +193,12 @@ var tween = KUTE.to('#line', { path: '#circle' }).start();
<p>As you can see, the functionality of this component is very different from the <a href="svgMorph.html">svgMorph</a> component in the sense that it will <p>As you can see, the functionality of this component is very different from the <a href="svgMorph.html">svgMorph</a> component in the sense that it will
morph shapes as authored. If you replay the above animations, here are a few takeaways:</p> morph shapes as authored. If you replay the above animations, here are a few takeaways:</p>
<ul> <ul>
<li>the <b class="text-orange">orange</b> line and its corresponding shape are both closed, this makes the last <code>Z</code> path command behave like a regular <li>the <b class="text-orange">orange</b> line is <b>closed</b>, this makes the last <code>Z</code> path command behave like a regular line;</li>
line, perhaps not the best visual presentation;</li> <li>the <b class="text-green">green</b> line is <b>not closed</b>, and the presentation looks quite different compared to the other example as well as
<li>the <b class="text-green">green</b> line is not closed, but its corresponding shape is, still the <code>Z</code> path command seems to cause trouble, while the other <a href="./cubicMorph.html">cubicMorph</a> component.</li>
the presentation looks a bit different;</li>
<li>the <b class="text-blue">blue</b> line is now closed, but its corresponding shape isn't and with the <code>Z</code> path command missing from the second shape,
the animation looks significantly better;</li>
<li>the <b class="text-red">red</b> line and its corresponding shape are both not closed, another combination that delivers excellent outcome.</li>
</ul> </ul>
<p>As you can see, this is another case where easy steps can be made to optimize the visual presentation. Keep in mind that stroke attributes like <p>This is the visual presentation you can expect with this component. Keep in mind that stroke attributes like <code>stroke-linejoin</code> such can have
<code>stroke-linejoin</code> such can have a small impact on your animation, particularly on start and end.</p> a small impact on your animation, particularly on start and end points.</p>
<h3>Subpath Example</h3> <h3>Subpath Example</h3>
@ -310,31 +291,6 @@ var tween = KUTE.to('#line', { path: '#circle' }).start();
<path id="rectangle-container" fill="#2196F3" mask="url(#symbol)" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path> <path id="rectangle-container" fill="#2196F3" mask="url(#symbol)" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
<path id="circle-container" style="visibility: hidden;" d="M0,256a256,256 0 1,0 512,0a256,256 0 1,0 -512,0z"></path> <path id="circle-container" style="visibility: hidden;" d="M0,256a256,256 0 1,0 512,0a256,256 0 1,0 -512,0z"></path>
</svg> </svg>
<svg class="example-box-model example-box" id="complex-morph-example1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513">
<defs>
<mask id="symbol1">
<rect width="100%" height="100%" fill="#fff"></rect>
<path id="symbol-left1" fill="#000" d="M155.889 333.394h-55.632c-3.351 0-5.854-1.504-7.271-3.792-1.467-2.379-1.542-5.464 0-8.534l59.11-104.313c0.063-0.114 0.063-0.19 0-0.316l-37.615-65.116c-1.556-3.098-1.783-6.157-0.316-8.534 1.417-2.301 4.235-3.477 7.586-3.477h55.632c8.535 0 12.72 5.499 15.489 10.431 0 0 38.020 66.33 38.249 66.696-2.252 3.97-60.059 106.21-60.059 106.21-2.844 5.131-6.852 10.745-15.173 10.745z"></path>
<path id="symbol-left-clone1" fill="#000" d="M155.889 333.394h-55.632c-3.351 0-5.854-1.504-7.271-3.792-1.467-2.379-1.542-5.464 0-8.534l59.11-104.313c0.063-0.114 0.063-0.19 0-0.316l-37.615-65.116c-1.556-3.098-1.783-6.157-0.316-8.534 1.417-2.301 4.235-3.477 7.586-3.477h55.632c8.535 0 12.72 5.499 15.489 10.431 0 0 38.020 66.33 38.249 66.696-2.252 3.97-60.059 106.21-60.059 106.21-2.844 5.131-6.852 10.745-15.173 10.745z"></path>
<path id="symbol-right1" fill="#000" d="M418.956 75.269l-123.176 217.79c-0.075 0.115-0.075 0.255 0 0.367l78.431 143.295c1.556 3.084 1.593 6.221 0.113 8.597-1.415 2.288-4.033 3.552-7.383 3.552h-55.57c-8.522 0-12.783-5.663-15.54-10.596 0 0-78.848-144.646-79.050-145.023 3.944-6.98 123.797-219.523 123.797-219.523 2.984-5.362 6.587-10.596 14.894-10.596h56.203c3.351 0 5.981 1.265 7.396 3.553 1.466 2.376 1.428 5.511-0.115 8.584z"></path>
<path id="eye-right1" style="visibility: hidden;" d="M352,128c2.6,0,5,0.5,7.4,1.3c2.3,0.8,4.5,2,6.6,3.6c10.6,7.8,18,24.2,18,43.1c0,16.2-5.3,30.5-13.5,39.2
c-3.1,3.3-6.6,5.8-10.5,7.3c-2.6,1-5.3,1.5-8,1.5c-4,0-7.8-1.1-11.3-3.1c-2.7-1.6-5.3-3.7-7.6-6.2c-7.9-8.7-13-22.8-13-38.7
c0-19.2,7.5-35.7,18.4-43.4c1.9-1.4,4-2.5,6.1-3.2C346.9,128.5,349.4,128,352,128z"></path>
<path id="eye-left1" style="visibility: hidden;" d="M176,156c10.4,0,19.7,1.4,27.5,3.9c14.5,4.7,23.5,13.4,23.5,24.8c0,3.7,1.9,21.5-0.1,24.8
c-3.3-5.5-9.2-10.3-16.7-13.9c-5.6-2.7-12.2-4.8-19.4-6c-4.7-0.8-9.6-1.2-14.7-1.2c-8.9,0-17.3,1.3-24.7,3.5
c-12.2,3.7-21.6,10-26.3,17.6c-2-3.3-0.1-21.1-0.1-24.8c0-11.3,8.8-19.9,23-24.6c3.7-1.2,7.8-2.2,12.2-2.9
C165.1,156.4,170.4,156,176,156z"></path>
<path id="mouth1" style="visibility: hidden;" d="M250.2,416c-42.9,0-82-16.6-111.5-43.9c-7-6.5-13.5-13.6-19.4-21.2c-3.8-4.9-7.3-10-10.6-15.4
c5.6,4.4,11.9,8.2,18.7,11.5c7.1,3.4,14.8,6.2,23,8.4c33.9,9.2,76.7,8.9,120.9,0.1c47.2-9.3,87.3-26.8,114.5-50.3
c6-5.1,11.3-10.6,16-16.3c5.6-6.9,10.3-14.2,13.8-21.8c-1.2,9.2-3.1,18.2-5.7,26.9c-2.6,8.8-5.9,17.3-9.7,25.5
C373.1,376.7,316.1,416,250.2,416L250.2,416z"></path>
</mask>
</defs>
<path id="rectangle-container1" fill="#9C27B0" mask="url(#symbol1)" d="M426.7,0H85.3C38.4,0,0,38.4,0,85.3v341.3c0,47,38.4,85.3,85.3,85.3h341.3
c46.9,0,85.3-38.4,85.3-85.3V85.3C512,38.4,473.6,0,426.7,0z"></path>
<path id="circle-container1" style="visibility: hidden;" d="M0,256c0,100.9,59.8,165.3,72,177.9c11.2,11.6,77.7,78.1,184,78.1c14.5,0,115.8-1.7,190.7-85.3
C510.1,356,512,274.1,512,256c0-18.9-2.1-96.7-61-165.9C375.7,1.8,269.4,0,256,0C241,0,141.3,1.7,66.6,83.7C1.9,154.8,0,237.9,0,256 z"></path>
</svg>
<svg class="example-box-model example-box" id="complex-morph-example2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513"> <svg class="example-box-model example-box" id="complex-morph-example2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513">
<defs> <defs>
<mask id="symbol2"> <mask id="symbol2">
@ -372,7 +328,7 @@ var tween = KUTE.to('#line', { path: '#circle' }).start();
<ul> <ul>
<li>Starting with KUTE.js version 2.0.14 the component implements <a href="https://github.com/thednp/svg-path-commander">SVGPathCommander</a> for path processing, solving previous issues with over-optimized <li>Starting with KUTE.js version 2.0.14 the component implements <a href="https://github.com/thednp/svg-path-commander">SVGPathCommander</a> for path processing, solving previous issues with over-optimized
path strings among other issues. You can try the <a href="https://thednp.github.io/svg-path-commander/">SVGPathCommander demo page</a> to prepare your path strings.</li> path strings among other issues. You can try the <a href="https://thednp.github.io/svg-path-commander/">SVGPathCommander demo page</a> to prepare your path strings.</li>
<li>Since animation works only with <code>path</code> <b>SVGElement</b>s, you might need a <a href="https://github.com/Waest/SVGPathConverter" target="_blank">convertToPath</a> utility.</li> <li>Since animation works only with <code>path</code> <b>SVGElement</b>s, you might need a <a href="https://thednp.github.io/svg-path-commander/convert.html" target="_blank">shapeToPath</a> utility.</li>
<li>Both SVG morph components will always animate first sub-path from both starting and ending shapes, and for any case hopefully this demo will guide you in mastering the technique.</li> <li>Both SVG morph components will always animate first sub-path from both starting and ending shapes, and for any case hopefully this demo will guide you in mastering the technique.</li>
<li>In some cases your start and end shapes don't have a very close size, you can use your vector graphics editor of choice or <a href="https://github.com/Waest/SVGPathConverter">SVGPathCommander</a> <li>In some cases your start and end shapes don't have a very close size, you can use your vector graphics editor of choice or <a href="https://github.com/Waest/SVGPathConverter">SVGPathCommander</a>
to apply a scale transformation to your shapes' path commands.</li> to apply a scale transformation to your shapes' path commands.</li>
@ -400,13 +356,10 @@ var tween = KUTE.to('#line', { path: '#circle' }).start();
</div> </div>
<!-- /.site-wrapper --> <!-- /.site-wrapper -->
<!-- JavaScript =============================================== --> <!-- JavaScript =============================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="./src/polyfill.min.js"></script> <script src="./src/polyfill.min.js"></script>
<!-- <script src="./src/kute-extra.js"></script> --> <script src="./src/kute-extra.js"></script>
<script src="./src/kute-extra.min.js"></script>
<script src="./assets/js/svgCubicMorph.js"></script> <script src="./assets/js/svgCubicMorph.js"></script>
<script src="./assets/js/prism.js"></script> <script src="./assets/js/prism.js"></script>
<script src="./assets/js/scripts.js"></script> <script src="./assets/js/scripts.js"></script>

View file

@ -381,7 +381,7 @@ var tween2 = KUTE.to('#triangle', { path: '#square' }).start();
<li>Starting with KUTE.js version 2.0.14 the component implements <a href="https://github.com/thednp/svg-path-commander">SVGPathCommander</a> for path processing, solving previous issues with over-optimized <li>Starting with KUTE.js version 2.0.14 the component implements <a href="https://github.com/thednp/svg-path-commander">SVGPathCommander</a> for path processing, solving previous issues with over-optimized
path strings among other issues. You can try the <a href="https://thednp.github.io/svg-path-commander/">SVGPathCommander demo page</a> to prepare your path strings.</li> path strings among other issues. You can try the <a href="https://thednp.github.io/svg-path-commander/">SVGPathCommander demo page</a> to prepare your path strings.</li>
<li>Since <b>SVG Morph</b> animation works only with <code>path</code> elements, you might need a <code>convertToPath</code> feature, so <li>Since <b>SVG Morph</b> animation works only with <code>path</code> elements, you might need a <code>convertToPath</code> feature, so
<a href="https://github.com/Waest/SVGPathConverter" target="_blank">grab one here</a>.</li> <a href="https://thednp.github.io/svg-path-commander/convert.html" target="_blank">grab one here</a>.</li>
<li>Both SVG morph components will always animate first sub-path from both starting and ending shapes, and for any case hopefully this demo will guide you in mastering the technique.</li> <li>Both SVG morph components will always animate first sub-path from both starting and ending shapes, and for any case hopefully this demo will guide you in mastering the technique.</li>
<li>In some cases your start and end shapes don't have a very close size, you can use your vector graphics editor of choice or <a href="https://github.com/Waest/SVGPathConverter">SVGPathCommander</a> <li>In some cases your start and end shapes don't have a very close size, you can use your vector graphics editor of choice or <a href="https://github.com/Waest/SVGPathConverter">SVGPathCommander</a>
to apply a scale transformation to your shapes' path commands.</li> to apply a scale transformation to your shapes' path commands.</li>
@ -419,8 +419,7 @@ var tween2 = KUTE.to('#triangle', { path: '#square' }).start();
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="./src/polyfill.min.js"></script> <script src="./src/polyfill.min.js"></script>
<script src="./src/kute.min.js"></script> <script src="../dist/kute.js"></script>
<!-- <script src="../dist/kute.js"></script> -->
<script src="./assets/js/prism.js"></script> <script src="./assets/js/prism.js"></script>
<script src="./assets/js/scripts.js"></script> <script src="./assets/js/scripts.js"></script>
<script src="./assets/js/svgMorph.js"></script> <script src="./assets/js/svgMorph.js"></script>

2504
dist/kute.esm.js vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

2475
dist/kute.js vendored

File diff suppressed because it is too large Load diff

4
dist/kute.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{ {
"name": "kute.js", "name": "kute.js",
"version": "2.1.3", "version": "2.2.0alpha2",
"description": "JavaScript animation engine", "description": "JavaScript animation engine",
"main": "dist/kute.min.js", "main": "dist/kute.min.js",
"module": "dist/kute.esm.js", "module": "dist/kute.esm.js",
@ -23,7 +23,7 @@
"lint:js": "eslint src/ --config .eslintrc", "lint:js": "eslint src/ --config .eslintrc",
"copy-build": "rollup --environment OUTPUTFILE:demo/src/kute.min.js,DIST:standard,MIN:true,FORMAT:umd -c", "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-standard": "rollup --environment DIST:standard,MIN:false,FORMAT:umd -c",
"build-ts": "tsc -d", "build:ts": "tsc -d",
"build-standard-min": "rollup --environment DIST:standard,MIN:true,FORMAT:umd -c", "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": "rollup --environment DIST:standard,MIN:false,FORMAT:esm -c",
"build-standard-esm-min": "rollup --environment DIST:standard,MIN:true,FORMAT:esm -c", "build-standard-esm-min": "rollup --environment DIST:standard,MIN:true,FORMAT:esm -c",
@ -61,10 +61,10 @@
}, },
"homepage": "http://thednp.github.io/kute.js", "homepage": "http://thednp.github.io/kute.js",
"dependencies": { "dependencies": {
"cubic-bezier-easing": "^1.0.8", "cubic-bezier-easing": "^1.0.14",
"minifill": "^0.0.16", "minifill": "^0.0.16",
"shorter-js": "^0.2.1", "shorter-js": "^0.2.6",
"svg-path-commander": "0.1.7" "svg-path-commander": "0.1.17"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-buble": "^0.21.3", "@rollup/plugin-buble": "^0.21.3",
@ -77,6 +77,6 @@
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"rollup": "^2.38.4", "rollup": "^2.38.4",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"typescript": "^4.4.4" "typescript": "^4.5.2"
} }
} }

View file

@ -36,7 +36,7 @@ const PLUGINS = [
] ]
if (FORMAT!=='esm'){ if (FORMAT!=='esm'){
PLUGINS.push(buble()); PLUGINS.push(buble({objectAssign: 'Object.assign'}));
} }
if (MIN){ if (MIN){

View file

@ -1,36 +1,37 @@
import supportedProperties from '../objects/supportedProperties.js'; import supportedProperties from '../objects/supportedProperties';
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import defaultOptions from '../objects/defaultOptions.js'; import defaultOptions from '../objects/defaultOptions';
import prepareProperty from '../objects/prepareProperty.js'; import prepareProperty from '../objects/prepareProperty';
import prepareStart from '../objects/prepareStart.js'; import prepareStart from '../objects/prepareStart';
import onStart from '../objects/onStart.js'; import onStart from '../objects/onStart';
import onComplete from '../objects/onComplete.js'; import onComplete from '../objects/onComplete';
import crossCheck from '../objects/crossCheck.js'; import crossCheck from '../objects/crossCheck';
import linkProperty from '../objects/linkProperty.js'; import linkProperty from '../objects/linkProperty';
import Util from '../objects/util.js'; import Util from '../objects/util';
import Interpolate from '../objects/interpolate.js'; import Interpolate from '../objects/interpolate';
// Animation class /**
// * builds KUTE components * Animation Class
// * populate KUTE objects *
// * AnimatonBase creates a KUTE.js build for pre-made Tween objects * Registers components by populating KUTE.js objects and makes sure
// * AnimatonDevelopment can help you debug your new components * no duplicate component / property is allowed.
*/
export default class Animation { export default class Animation {
/**
* @constructor
* @param {KUTE.fullComponent} Component
*/
constructor(Component) { constructor(Component) {
try { try {
if (Component.component in supportedProperties) { if (Component.component in supportedProperties) {
throw Error(`KUTE.js - ${Component.component} already registered`); throw Error(`KUTE - ${Component.component} already registered`);
} else if (Component.property in defaultValues) { } else if (Component.property in defaultValues) {
throw Error(`KUTE.js - ${Component.property} already registered`); throw Error(`KUTE - ${Component.property} already registered`);
} else {
this.setComponent(Component);
} }
} catch (e) { } catch (e) {
throw Error(e); throw Error(e);
} }
}
setComponent(Component) {
const propertyInfo = this; const propertyInfo = this;
const ComponentName = Component.component; const ComponentName = Component.component;
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty, Util } // const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty, Util }
@ -75,9 +76,10 @@ export default class Animation {
// set additional options // set additional options
if (Component.defaultOptions) { if (Component.defaultOptions) {
Object.keys(Component.defaultOptions).forEach((op) => { // Object.keys(Component.defaultOptions).forEach((op) => {
defaultOptions[op] = Component.defaultOptions[op]; // defaultOptions[op] = Component.defaultOptions[op];
}); // });
Object.assign(defaultOptions, Component.defaultOptions);
} }
// set functions // set functions
@ -105,7 +107,7 @@ export default class Animation {
}); });
} }
// set component interpolate // set component interpolation functions
if (Component.Interpolate) { if (Component.Interpolate) {
Object.keys(Component.Interpolate).forEach((fni) => { Object.keys(Component.Interpolate).forEach((fni) => {
const compIntObj = Component.Interpolate[fni]; const compIntObj = Component.Interpolate[fni];

View file

@ -1,18 +1,27 @@
import supportedProperties from '../objects/supportedProperties.js'; import supportedProperties from '../objects/supportedProperties';
import defaultOptions from '../objects/defaultOptions.js'; import defaultOptions from '../objects/defaultOptions';
import onStart from '../objects/onStart.js'; import onStart from '../objects/onStart';
import onComplete from '../objects/onComplete.js'; import onComplete from '../objects/onComplete';
import linkProperty from '../objects/linkProperty.js'; import linkProperty from '../objects/linkProperty';
import Util from '../objects/util.js'; import Util from '../objects/util';
import Interpolate from '../objects/interpolate.js'; import Interpolate from '../objects/interpolate';
// Animation class /**
* 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 { export default class AnimationBase {
/**
* @class
* @param {KUTE.baseComponent} Component
*/
constructor(Component) { constructor(Component) {
return this.setComponent(Component);
}
setComponent(Component) {
const ComponentName = Component.component; const ComponentName = Component.component;
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty } // const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty }
const Functions = { onStart, onComplete }; const Functions = { onStart, onComplete };
@ -27,9 +36,10 @@ export default class AnimationBase {
// set additional options // set additional options
if (Component.defaultOptions) { if (Component.defaultOptions) {
Object.keys(Component.defaultOptions).forEach((op) => { // Object.keys(Component.defaultOptions).forEach((op) => {
defaultOptions[op] = Component.defaultOptions[op]; // defaultOptions[op] = Component.defaultOptions[op];
}); // });
Object.assign(defaultOptions, Component.defaultOptions);
} }
// set functions // set functions

View file

@ -1,22 +1,28 @@
import prepareProperty from '../objects/prepareProperty.js'; import prepareProperty from '../objects/prepareProperty';
import prepareStart from '../objects/prepareStart.js'; import prepareStart from '../objects/prepareStart';
import onStart from '../objects/onStart.js'; import onStart from '../objects/onStart';
import onComplete from '../objects/onComplete.js'; import onComplete from '../objects/onComplete';
import crossCheck from '../objects/crossCheck.js'; import crossCheck from '../objects/crossCheck';
import Interpolate from '../objects/interpolate.js'; import Interpolate from '../objects/interpolate';
import Animation from './animation.js'; import Animation from './animation';
// AnimationDevelopment class /**
* 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 { export default class AnimationDevelopment extends Animation {
constructor(...args) { /**
super(...args); *
* @param {KUTE.fullComponent} args
this.setComponent(...args); */
} constructor(Component) {
super(Component);
setComponent(Component) {
super.setComponent(Component);
const propertyInfo = this; const propertyInfo = this;
// const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty, Util } // const Objects = { defaultValues, defaultOptions, Interpolate, linkProperty, Util }

View file

@ -1,22 +1,27 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import { onStartBgPos } from './backgroundPositionBase.js'; import { onStartBgPos } from './backgroundPositionBase';
/* bgPosProp = {
property: 'backgroundPosition',
defaultValue: [0,0],
interpolators: {numbers},
functions = { prepareStart, prepareProperty, onStart }
} */
// Component Functions // Component Functions
/**
* Returns the property computed style.
* @param {string} prop the property
* @returns {string} the property computed style
*/
function getBgPos(prop/* , value */) { function getBgPos(prop/* , value */) {
return getStyleForProperty(this.element, prop) || defaultValues[prop]; return getStyleForProperty(this.element, prop) || defaultValues[prop];
} }
function prepareBgPos(prop, value) { /**
* 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) { if (value instanceof Array) {
const x = trueDimension(value[0]).v; const x = trueDimension(value[0]).v;
const y = trueDimension(value[1]).v; const y = trueDimension(value[1]).v;

View file

@ -1,27 +1,26 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
/* bgPosProp = {
property: 'backgroundPosition',
defaultValue: [0,0],
interpolators: {numbers},
functions = { prepareStart, prepareProperty, onStart }
} */
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} prop the property name
*/
export function onStartBgPos(prop) { export function onStartBgPos(prop) {
if (this.valuesEnd[prop] && !KUTE[prop]) { if (this.valuesEnd[prop] && !KEC[prop]) {
KUTE[prop] = (elem, a, b, v) => { 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)}%`; 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 // Component Base Object
const baseBgPosOps = { const BackgroundPositionBase = {
component: 'baseBackgroundPosition', component: 'baseBackgroundPosition',
property: 'backgroundPosition', property: 'backgroundPosition',
Interpolate: { numbers }, Interpolate: { numbers },
functions: { onStart: onStartBgPos }, functions: { onStart: onStartBgPos },
}; };
export default baseBgPosOps; export default BackgroundPositionBase;

View file

@ -1,19 +1,14 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import units from '../interpolation/units.js'; import units from '../interpolation/units';
import { radiusOnStartFn } from './borderRadiusBase.js'; import { radiusOnStartFn } from './borderRadiusBase';
/* borderRadius = {
category: 'borderRadius',
properties : [..],
defaultValues: {..},
interpolation: {units}
} */
// Component Properties // Component Properties
const radiusProps = ['borderRadius', const radiusProps = [
'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius']; 'borderRadius',
'borderTopLeftRadius', 'borderTopRightRadius',
'borderBottomLeftRadius', 'borderBottomRightRadius'];
const radiusValues = {}; const radiusValues = {};
radiusProps.forEach((x) => { radiusValues[x] = 0; }); radiusProps.forEach((x) => { radiusValues[x] = 0; });
@ -24,11 +19,21 @@ radiusProps.forEach((tweenProp) => {
radiusOnStart[tweenProp] = radiusOnStartFn; 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) { export function getRadius(tweenProp) {
return getStyleForProperty(this.element, tweenProp) || defaultValues[tweenProp]; return getStyleForProperty(this.element, tweenProp) || defaultValues[tweenProp];
} }
export function prepareRadius(tweenProp, value) { /**
* 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); return trueDimension(value);
} }

View file

@ -1,5 +1,5 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import units from '../interpolation/units.js'; import units from '../interpolation/units';
/* borderRadius = { /* borderRadius = {
category: 'borderRadius', category: 'borderRadius',
@ -9,13 +9,21 @@ import units from '../interpolation/units.js';
} */ } */
// Component Properties // Component Properties
const radiusProps = ['borderRadius', const radiusProps = [
'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius']; 'borderRadius',
'borderTopLeftRadius', 'borderTopRightRadius',
'borderBottomLeftRadius', 'borderBottomRightRadius',
];
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function radiusOnStartFn(tweenProp) { export function radiusOnStartFn(tweenProp) {
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { 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); elem.style[tweenProp] = units(a.v, b.v, b.u, v);
}; };
} }
@ -26,10 +34,10 @@ radiusProps.forEach((tweenProp) => {
}); });
// Base Component // Base Component
const baseBorderRadius = { const BorderRadiusBase = {
component: 'baseBorderRadius', component: 'baseBorderRadius',
category: 'borderRadius', category: 'borderRadius',
Interpolate: { units }, Interpolate: { units },
functions: { onStart: radiusOnStart }, functions: { onStart: radiusOnStart },
}; };
export default baseBorderRadius; export default BorderRadiusBase;

View file

@ -1,8 +1,8 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { boxModelOnStart } from './boxModelBase.js'; import { boxModelOnStart } from './boxModelBase';
// Component Properties // Component Properties
const boxModelProperties = ['top', 'left', 'width', 'height', 'right', 'bottom', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', const boxModelProperties = ['top', 'left', 'width', 'height', 'right', 'bottom', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
@ -14,9 +14,21 @@ const boxModelValues = {};
boxModelProperties.forEach((x) => { boxModelValues[x] = 0; }); boxModelProperties.forEach((x) => { boxModelValues[x] = 0; });
// Component Functions // Component Functions
/**
* Returns the current property computed style.
* @param {string} tweenProp the property name
* @returns {string} computed style for property
*/
function getBoxModel(tweenProp) { function getBoxModel(tweenProp) {
return getStyleForProperty(this.element, tweenProp) || defaultValues[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) { function prepareBoxModel(tweenProp, value) {
const boxValue = trueDimension(value); const const boxValue = trueDimension(value); const
offsetProp = tweenProp === 'height' ? 'offsetHeight' : 'offsetWidth'; offsetProp = tweenProp === 'height' ? 'offsetHeight' : 'offsetWidth';
@ -33,7 +45,7 @@ const boxModelFunctions = {
}; };
// Component Full Component // Component Full Component
const boxModel = { const BoxModel = {
component: 'boxModelProperties', component: 'boxModelProperties',
category: 'boxModel', category: 'boxModel',
properties: boxModelProperties, properties: boxModelProperties,
@ -42,4 +54,4 @@ const boxModel = {
functions: boxModelFunctions, functions: boxModelFunctions,
}; };
export default boxModel; export default BoxModel;

View file

@ -1,13 +1,21 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
// Component Functions // Component Functions
/**
* Sets the update function for the property.
* @param {string} tweenProp the property name
*/
export function boxModelOnStart(tweenProp) { export function boxModelOnStart(tweenProp) {
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { 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 elem.style[tweenProp] = `${v > 0.99 || v < 0.01
? ((numbers(a, b, v) * 10) >> 0) / 10 ? ((numbers(a, b, v) * 10) >> 0) / 10
: (numbers(a, b, v)) >> 0}px`; : (numbers(a, b, v)) >> 0}px`;
/* eslint-enable no-bitwise */
/* eslint-enable no-param-reassign */
}; };
} }
} }
@ -18,7 +26,7 @@ const baseBoxOnStart = {};
baseBoxProps.forEach((x) => { baseBoxOnStart[x] = boxModelOnStart; }); baseBoxProps.forEach((x) => { baseBoxOnStart[x] = boxModelOnStart; });
// Component Base // Component Base
const baseBoxModel = { const BoxModelBase = {
component: 'baseBoxModel', component: 'baseBoxModel',
category: 'boxModel', category: 'boxModel',
properties: baseBoxProps, properties: baseBoxProps,
@ -26,4 +34,4 @@ const baseBoxModel = {
functions: { onStart: baseBoxOnStart }, functions: { onStart: baseBoxOnStart },
}; };
export default baseBoxModel; export default BoxModelBase;

View file

@ -1,13 +1,25 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { boxModelOnStart } from './boxModelBase.js'; import { boxModelOnStart } from './boxModelBase';
// Component Functions // Component Functions
/**
* Returns the current property computed style.
* @param {string} tweenProp the property name
* @returns {string} computed style for property
*/
function getBoxModel(tweenProp) { function getBoxModel(tweenProp) {
return getStyleForProperty(this.element, tweenProp) || defaultValues[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) { function prepareBoxModel(tweenProp, value) {
const boxValue = trueDimension(value); const boxValue = trueDimension(value);
const offsetProp = tweenProp === 'height' ? 'offsetHeight' : 'offsetWidth'; const offsetProp = tweenProp === 'height' ? 'offsetHeight' : 'offsetWidth';
@ -31,7 +43,7 @@ const essentialBoxModelFunctions = {
}; };
// Component Essential // Component Essential
const essentialBoxModel = { const BoxModelEssential = {
component: 'essentialBoxModel', component: 'essentialBoxModel',
category: 'boxModel', category: 'boxModel',
properties: essentialBoxProps, properties: essentialBoxProps,
@ -41,4 +53,4 @@ const essentialBoxModel = {
Util: { trueDimension }, Util: { trueDimension },
}; };
export default essentialBoxModel; export default BoxModelEssential;

View file

@ -1,16 +1,29 @@
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { onStartClip } from './clipPropertyBase.js'; import { onStartClip } from './clipPropertyBase';
// Component Functions // 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 */) { function getClip(tweenProp/* , value */) {
const currentClip = getStyleForProperty(this.element, tweenProp); const { element } = this;
const width = getStyleForProperty(this.element, 'width'); const currentClip = getStyleForProperty(element, tweenProp);
const height = getStyleForProperty(this.element, 'height'); const width = getStyleForProperty(element, 'width');
const height = getStyleForProperty(element, 'height');
return !/rect/.test(currentClip) ? [0, width, height, 0] : currentClip; return !/rect/.test(currentClip) ? [0, width, height, 0] : currentClip;
} }
function prepareClip(tweenProp, value) {
/**
* 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) { if (value instanceof Array) {
return value.map((x) => trueDimension(x)); return value.map((x) => trueDimension(x));
} }
@ -27,7 +40,7 @@ const clipFunctions = {
}; };
// Component Full // Component Full
const clipProperty = { const ClipProperty = {
component: 'clipProperty', component: 'clipProperty',
property: 'clip', property: 'clip',
defaultValue: [0, 0, 0, 0], defaultValue: [0, 0, 0, 0],
@ -36,4 +49,4 @@ const clipProperty = {
Util: { trueDimension }, Util: { trueDimension },
}; };
export default clipProperty; export default ClipProperty;

View file

@ -1,24 +1,31 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartClip(tweenProp) { export function onStartClip(tweenProp) {
if (this.valuesEnd[tweenProp] && !KUTE[tweenProp]) { if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
let h = 0; const let h = 0; const
cl = []; cl = [];
for (h; h < 4; h += 1) { for (h; h < 4; h += 1) {
const c1 = a[h].v; const c2 = b[h].v; const const c1 = a[h].v;
cu = b[h].u || 'px'; 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; 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})`; elem.style.clip = `rect(${cl})`;
}; };
} }
} }
// Component Base // Component Base
const baseClip = { const ClipPropertyBase = {
component: 'baseClip', component: 'baseClip',
property: 'clip', property: 'clip',
// defaultValue: [0,0,0,0], // defaultValue: [0,0,0,0],
@ -26,4 +33,4 @@ const baseClip = {
functions: { onStart: onStartClip }, functions: { onStart: onStartClip },
}; };
export default baseClip; export default ClipPropertyBase;

View file

@ -1,15 +1,18 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueColor from '../util/trueColor.js'; import trueColor from '../util/trueColor';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
import { onStartColors } from './colorPropertiesBase.js'; import { onStartColors } from './colorPropertiesBase';
// Component Interpolation
// Component Properties // Component Properties
// supported formats // supported formats
// 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+) // 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+)
const supportedColors = ['color', 'backgroundColor', 'borderColor', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'outlineColor']; const supportedColors = [
'color', 'backgroundColor', 'outlineColor',
'borderColor', 'borderTopColor', 'borderRightColor',
'borderBottomColor', 'borderLeftColor',
];
const defaultColors = {}; const defaultColors = {};
supportedColors.forEach((tweenProp) => { supportedColors.forEach((tweenProp) => {
@ -22,10 +25,22 @@ supportedColors.forEach((x) => {
colorsOnStart[x] = onStartColors; colorsOnStart[x] = onStartColors;
}); });
/**
* Returns the current property computed style.
* @param {string} prop the property name
* @returns {string} property computed style
*/
function getColor(prop/* , value */) { function getColor(prop/* , value */) {
return getStyleForProperty(this.element, prop) || defaultValues[prop]; return getStyleForProperty(this.element, prop) || defaultValues[prop];
} }
function prepareColor(prop, value) {
/**
* 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); return trueColor(value);
} }

View file

@ -1,6 +1,6 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
// Component Interpolation // Component Interpolation
// rgba1, rgba2, progress // rgba1, rgba2, progress
@ -8,13 +8,22 @@ import colors from '../interpolation/colors.js';
// Component Properties // Component Properties
// supported formats // supported formats
// 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+) // 'hex', 'rgb', 'rgba' '#fff' 'rgb(0,0,0)' / 'rgba(0,0,0,0)' 'red' (IE9+)
const supportedColors = ['color', 'backgroundColor', 'borderColor', const supportedColors = [
'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'outlineColor']; 'color', 'backgroundColor', 'outlineColor',
'borderColor',
'borderTopColor', 'borderRightColor',
'borderBottomColor', 'borderLeftColor',
];
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartColors(tweenProp) { export function onStartColors(tweenProp) {
if (this.valuesEnd[tweenProp] && !KUTE[tweenProp]) { if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
// eslint-disable-next-line no-param-reassign
elem.style[tweenProp] = colors(a, b, v); elem.style[tweenProp] = colors(a, b, v);
}; };
} }

View file

@ -1,14 +1,17 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import getInlineStyle from '../process/getInlineStyle.js'; import getInlineStyle from '../process/getInlineStyle';
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import trueProperty from '../util/trueProperty.js'; import trueProperty from '../util/trueProperty';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
// Component Const // Component Const
const transformProperty = trueProperty('transform'); const transformProperty = trueProperty('transform');
const supportTransform = transformProperty in document.body.style ? 1 : 0; const supportTransform = transformProperty in document.body.style ? 1 : 0;
// Component Functions // Component Functions
/**
* Returns the property current style.
*/
function getComponentCurrentValue(/* tweenProp, value */) { function getComponentCurrentValue(/* tweenProp, value */) {
const currentTransform = getInlineStyle(this.element); const currentTransform = getInlineStyle(this.element);
const { left } = this.element.style; const { left } = this.element.style;
@ -25,25 +28,38 @@ function getComponentCurrentValue(/* tweenProp, value */) {
return [x, y]; return [x, y];
} }
function prepareComponentValue(tweenProp, value) { /**
* 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 x = Number.isFinite(value * 1) ? parseInt(value, 10) : parseInt(value[0], 10) || 0;
const y = parseInt(value[1], 10) || 0; const y = parseInt(value[1], 10) || 0;
return [x, y]; return [x, y];
} }
/**
* Sets the property update function.
* @param {string} tweenProp the `path` property
*/
export function onStartComponent(tweenProp/* , value */) { export function onStartComponent(tweenProp/* , value */) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
if (supportTransform) { if (supportTransform) {
KUTE[tweenProp] = (elem, a, b, v) => { 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)`; elem.style[transformProperty] = `translate(${numbers(a[0], b[0], v)}px,${numbers(a[1], b[1], v)}px)`;
}; };
} else { } else {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
if (a[0] || b[0]) { 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`; elem.style.left = `${numbers(a[0], b[0], v)}px`;
} }
if (a[1] || b[1]) { 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`; elem.style.top = `${numbers(a[1], b[1], v)}px`;
} }
}; };

View file

@ -1,9 +1,9 @@
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import trueColor from '../util/trueColor.js'; import trueColor from '../util/trueColor';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
import { dropShadow, onStartFilter } from './filterEffectsBase.js'; import { dropshadow, onStartFilter } from './filterEffectsBase';
/* filterEffects = { /* filterEffects = {
property: 'filter', property: 'filter',
@ -14,10 +14,20 @@ import { dropShadow, onStartFilter } from './filterEffectsBase.js';
} */ } */
// Component Util // Component Util
/**
* Returns camelCase filter sub-property.
* @param {string} str source string
* @returns {string} camelCase property name
*/
function replaceDashNamespace(str) { function replaceDashNamespace(str) {
return str.replace('-r', 'R').replace('-s', 'S'); 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) { function parseDropShadow(shadow) {
let newShadow; let newShadow;
@ -36,6 +46,11 @@ function parseDropShadow(shadow) {
return newShadow; 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) { function parseFilterString(currentStyle) {
const result = {}; const result = {};
const fnReg = /(([a-z].*?)\(.*?\))(?=\s([a-z].*?)\(.*?\)|\s*$)/g; const fnReg = /(([a-z].*?)\(.*?\))(?=\s([a-z].*?)\(.*?\)|\s*$)/g;
@ -60,6 +75,12 @@ function parseFilterString(currentStyle) {
} }
// Component Functions // 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) { function getFilter(tweenProp, value) {
const currentStyle = getStyleForProperty(this.element, tweenProp); const currentStyle = getStyleForProperty(this.element, tweenProp);
const filterObject = parseFilterString(currentStyle); const filterObject = parseFilterString(currentStyle);
@ -74,7 +95,14 @@ function getFilter(tweenProp, value) {
return filterObject; return filterObject;
} }
function prepareFilter(tweenProp, value) {
/**
* 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 = {}; const filterObject = {};
let fnp; let fnp;
@ -108,6 +136,10 @@ function prepareFilter(tweenProp, value) {
return filterObject; return filterObject;
} }
/**
* Adds missing sub-properties in `valuesEnd` from `valuesStart`.
* @param {string} tweenProp the property name
*/
function crossCheckFilter(tweenProp) { function crossCheckFilter(tweenProp) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
Object.keys(this.valuesStart[tweenProp]).forEach((fn) => { Object.keys(this.valuesStart[tweenProp]).forEach((fn) => {
@ -158,7 +190,7 @@ const filterEffects = {
sepia: numbers, sepia: numbers,
invert: numbers, invert: numbers,
hueRotate: numbers, hueRotate: numbers,
dropShadow: { numbers, colors, dropShadow }, dropShadow: { numbers, colors, dropshadow },
}, },
functions: filterFunctions, functions: filterFunctions,
Util: { Util: {

View file

@ -1,30 +1,34 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
/* filterEffects = {
property: 'filter',
subProperties: {},
defaultValue: {},
interpolators: {},
functions = { prepareStart, prepareProperty, onStart, crossCheck }
} */
// Component Interpolation // Component Interpolation
export function dropShadow(a, b, v) { /**
* 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 params = [];
const unit = 'px'; const unit = 'px';
for (let i = 0; i < 3; i += 1) { 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; params[i] = ((numbers(a[i], b[i], v) * 100 >> 0) / 100) + unit;
} }
return `drop-shadow(${params.concat(colors(a[3], b[3], v)).join(' ')})`; return `drop-shadow(${params.concat(colors(a[3], b[3], v)).join(' ')})`;
} }
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartFilter(tweenProp) { export function onStartFilter(tweenProp) {
if (this.valuesEnd[tweenProp] && !KUTE[tweenProp]) { if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
/* eslint-disable-next-line no-param-reassign -- impossible to satisfy */
elem.style[tweenProp] = (b.url ? `url(${b.url})` : '') 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.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.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.saturate || b.saturate ? `saturate(${((numbers(a.saturate, b.saturate, v) * 100) >> 0) / 100}%)` : '')
@ -34,7 +38,8 @@ export function onStartFilter(tweenProp) {
+ (a.sepia || b.sepia ? `sepia(${((numbers(a.sepia, b.sepia, v) * 100) >> 0) / 100}%)` : '') + (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.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.contrast || b.contrast ? `contrast(${((numbers(a.contrast, b.contrast, v) * 100) >> 0) / 100}%)` : '')
+ (a.dropShadow || b.dropShadow ? dropShadow(a.dropShadow, b.dropShadow, v) : ''); + (a.dropShadow || b.dropShadow ? dropshadow(a.dropShadow, b.dropShadow, v) : '');
/* eslint-enable no-bitwise -- impossible to satisfy */
}; };
} }
} }
@ -61,7 +66,7 @@ const baseFilter = {
sepia: numbers, sepia: numbers,
invert: numbers, invert: numbers,
hueRotate: numbers, hueRotate: numbers,
dropShadow: { numbers, colors, dropShadow }, dropShadow: { numbers, colors, dropshadow },
}, },
functions: { onStart: onStartFilter }, functions: { onStart: onStartFilter },
}; };

View file

@ -1,10 +1,10 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import onStart from '../objects/onStart.js'; import onStart from '../objects/onStart';
import trueColor from '../util/trueColor.js'; import trueColor from '../util/trueColor';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
import { attributes, onStartAttr } from './htmlAttributesBase.js'; import { attributes, onStartAttr } from './htmlAttributesBase';
// Component Name // Component Name
const ComponentName = 'htmlAttributes'; const ComponentName = 'htmlAttributes';
@ -13,13 +13,25 @@ const ComponentName = 'htmlAttributes';
const svgColors = ['fill', 'stroke', 'stop-color']; const svgColors = ['fill', 'stroke', 'stop-color'];
// Component Util // 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(); } function replaceUppercase(a) { return a.replace(/[A-Z]/g, '-$&').toLowerCase(); }
// Component Functions // Component Functions
export function getAttr(tweenProp, value) { /**
* 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 = {}; const attrStartValues = {};
Object.keys(value).forEach((attr) => { Object.keys(value).forEach((attr) => {
// get the value for 'fill-opacity' not fillOpacity, also 'width' not the internal 'width_px' // get the value for 'fill-opacity' not fillOpacity
// also 'width' not the internal 'width_px'
const attribute = replaceUppercase(attr).replace(/_+[a-z]+/, ''); const attribute = replaceUppercase(attr).replace(/_+[a-z]+/, '');
const currentValue = this.element.getAttribute(attribute); const currentValue = this.element.getAttribute(attribute);
attrStartValues[attribute] = svgColors.includes(attribute) attrStartValues[attribute] = svgColors.includes(attribute)
@ -30,6 +42,12 @@ export function getAttr(tweenProp, value) {
return attrStartValues; 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) export function prepareAttr(tweenProp, attrObj) { // attr (string),attrObj (object)
const attributesObject = {}; const attributesObject = {};
@ -49,6 +67,7 @@ export function prepareAttr(tweenProp, attrObj) { // attr (string),attrObj (obje
if (this.valuesEnd[tweenProp] && this.valuesEnd[tweenProp][tp] && !(tp in attributes)) { if (this.valuesEnd[tweenProp] && this.valuesEnd[tweenProp][tp] && !(tp in attributes)) {
attributes[tp] = (elem, oneAttr, a, b, v) => { attributes[tp] = (elem, oneAttr, a, b, v) => {
const _p = oneAttr.replace(suffix, ''); const _p = oneAttr.replace(suffix, '');
/* eslint no-bitwise: ["error", { "allow": [">>"] }] */
elem.setAttribute(_p, ((numbers(a.v, b.v, v) * 1000 >> 0) / 1000) + b.u); elem.setAttribute(_p, ((numbers(a.v, b.v, v) * 1000 >> 0) / 1000) + b.u);
}; };
} }

View file

@ -1,6 +1,6 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
// Component Name // Component Name
const ComponentName = 'baseHTMLAttributes'; const ComponentName = 'baseHTMLAttributes';
@ -10,18 +10,30 @@ const attributes = {};
export { attributes }; export { attributes };
export const onStartAttr = { export const onStartAttr = {
/**
* onStartAttr.attr
*
* Sets the sub-property update function.
* @param {string} tweenProp the property name
*/
attr(tweenProp) { attr(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
KUTE[tweenProp] = (elem, vS, vE, v) => { KEC[tweenProp] = (elem, vS, vE, v) => {
Object.keys(vE).forEach((oneAttr) => { Object.keys(vE).forEach((oneAttr) => {
KUTE.attributes[oneAttr](elem, oneAttr, vS[oneAttr], vE[oneAttr], v); KEC.attributes[oneAttr](elem, oneAttr, vS[oneAttr], vE[oneAttr], v);
}); });
}; };
} }
}, },
/**
* onStartAttr.attributes
*
* Sets the update function for the property.
* @param {string} tweenProp the property name
*/
attributes(tweenProp) { attributes(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd.attr) { if (!KEC[tweenProp] && this.valuesEnd.attr) {
KUTE[tweenProp] = attributes; KEC[tweenProp] = attributes;
} }
}, },
}; };

View file

@ -1,20 +1,24 @@
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { onStartOpacity } from './opacityPropertyBase.js'; import { onStartOpacity } from './opacityPropertyBase';
/* opacityProperty = {
property: 'opacity',
defaultValue: 1,
interpolators: {numbers},
functions = { prepareStart, prepareProperty, onStart }
} */
// Component Functions // Component Functions
/**
* Returns the current property computed style.
* @param {string} tweenProp the property name
* @returns {string} computed style for property
*/
function getOpacity(tweenProp/* , value */) { function getOpacity(tweenProp/* , value */) {
return getStyleForProperty(this.element, tweenProp); return getStyleForProperty(this.element, tweenProp);
} }
function prepareOpacity(tweenProp, value) { /**
* Returns the property tween object.
* @param {string} _ the property name
* @param {string} value the property value
* @returns {number} the property tween object
*/
function prepareOpacity(/* tweenProp, */_, value) {
return parseFloat(value); // opacity always FLOAT return parseFloat(value); // opacity always FLOAT
} }
@ -26,7 +30,7 @@ const opacityFunctions = {
}; };
// Full Component // Full Component
const opacityProperty = { const OpacityProperty = {
component: 'opacityProperty', component: 'opacityProperty',
property: 'opacity', property: 'opacity',
defaultValue: 1, defaultValue: 1,
@ -34,4 +38,4 @@ const opacityProperty = {
functions: opacityFunctions, functions: opacityFunctions,
}; };
export default opacityProperty; export default OpacityProperty;

View file

@ -1,5 +1,5 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
/* opacityProperty = { /* opacityProperty = {
property: 'opacity', property: 'opacity',
@ -9,17 +9,23 @@ import numbers from '../interpolation/numbers.js';
} */ } */
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartOpacity(tweenProp/* , value */) { export function onStartOpacity(tweenProp/* , value */) {
// opacity could be 0 sometimes, we need to check regardless // opacity could be 0 sometimes, we need to check regardless
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
/* eslint-disable */
elem.style[tweenProp] = ((numbers(a, b, v) * 1000) >> 0) / 1000; elem.style[tweenProp] = ((numbers(a, b, v) * 1000) >> 0) / 1000;
/* eslint-enable */
}; };
} }
} }
// Base Component // Base Component
const baseOpacity = { const OpacityPropertyBase = {
component: 'baseOpacity', component: 'baseOpacity',
property: 'opacity', property: 'opacity',
// defaultValue: 1, // defaultValue: 1,
@ -27,4 +33,4 @@ const baseOpacity = {
functions: { onStart: onStartOpacity }, functions: { onStart: onStartOpacity },
}; };
export default baseOpacity; export default OpacityPropertyBase;

View file

@ -1,5 +1,4 @@
import supportPassive from 'shorter-js/src/boolean/supportPassive.js'; import numbers from '../interpolation/numbers';
import numbers from '../interpolation/numbers.js';
import { import {
scrollContainer, scrollContainer,
@ -10,9 +9,13 @@ import {
getScrollTargets, getScrollTargets,
preventScroll, preventScroll,
toggleScrollEvents, toggleScrollEvents,
} from './scrollPropertyBase.js'; } from './scrollPropertyBase';
// Component Functions // Component Functions
/**
* Returns the current property computed style.
* @returns {number} computed style for property
*/
function getScroll() { function getScroll() {
this.element = ('scroll' in this.valuesEnd) && (!this.element || this.element === window) this.element = ('scroll' in this.valuesEnd) && (!this.element || this.element === window)
? scrollContainer : this.element; ? scrollContainer : this.element;
@ -22,7 +25,13 @@ function getScroll() {
: this.element.scrollTop; : this.element.scrollTop;
} }
function prepareScroll(prop, value) { /**
* Returns the property tween object.
* @param {string} _ the property name
* @param {string} value the property value
* @returns {number} the property tween object
*/
function prepareScroll(/* prop, */_, value) {
return parseInt(value, 10); return parseInt(value, 10);
} }
@ -35,7 +44,7 @@ const scrollFunctions = {
}; };
// Full Component // Full Component
const scrollProperty = { const ScrollProperty = {
component: 'scrollProperty', component: 'scrollProperty',
property: 'scroll', property: 'scroll',
defaultValue: 0, defaultValue: 0,
@ -43,8 +52,8 @@ const scrollProperty = {
functions: scrollFunctions, functions: scrollFunctions,
// export stuff to global // export stuff to global
Util: { Util: {
preventScroll, scrollIn, scrollOut, getScrollTargets, toggleScrollEvents, supportPassive, preventScroll, scrollIn, scrollOut, getScrollTargets, toggleScrollEvents,
}, },
}; };
export default scrollProperty; export default ScrollProperty;

View file

@ -1,8 +1,8 @@
import supportPassive from 'shorter-js/src/boolean/supportPassive.js'; import passiveHandler from 'shorter-js/src/misc/passiveHandler';
import mouseHoverEvents from 'shorter-js/src/strings/mouseHoverEvents.js'; import mouseHoverEvents from 'shorter-js/src/strings/mouseHoverEvents';
import supportTouch from 'shorter-js/src/boolean/supportTouch.js'; import supportTouch from 'shorter-js/src/boolean/supportTouch';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
// Component Util // Component Util
// events preventing scroll // events preventing scroll
@ -14,22 +14,36 @@ export const scrollContainer = navigator && /(EDGE|Mac)/i.test(navigator.userAge
? document.body ? document.body
: document.documentElement; : document.documentElement;
// scroll event options /**
// it's important to stop propagating when animating scroll * Prevent further scroll events until scroll animation is over.
const passiveHandler = supportPassive ? { passive: false } : false; * @param {Event} e event object
*/
// prevent mousewheel or touch events while tweening scroll
export function preventScroll(e) { export function preventScroll(e) {
if (this.scrolling) e.preventDefault(); if (this.scrolling) e.preventDefault();
} }
/**
* Returns the scroll element / target.
* @returns {{el: Element, st: Element}}
*/
export function getScrollTargets() { export function getScrollTargets() {
const el = this.element; const el = this.element;
return el === scrollContainer ? { el: document, st: document.body } : { el, st: el }; return el === scrollContainer ? { el: document, st: document.body } : { el, st: el };
} }
/**
* Toggles scroll prevention callback on scroll events.
* @param {string} action addEventListener / removeEventListener
* @param {Element} element target
*/
export function toggleScrollEvents(action, element) { export function toggleScrollEvents(action, element) {
element[action](mouseHoverEvents[0], preventScroll, passiveHandler); element[action](mouseHoverEvents[0], preventScroll, passiveHandler);
element[action](touchOrWheel, preventScroll, passiveHandler); element[action](touchOrWheel, preventScroll, passiveHandler);
} }
/**
* Action performed before scroll animation start.
*/
export function scrollIn() { export function scrollIn() {
const targets = getScrollTargets.call(this); const targets = getScrollTargets.call(this);
@ -39,6 +53,9 @@ export function scrollIn() {
targets.st.style.pointerEvents = 'none'; targets.st.style.pointerEvents = 'none';
} }
} }
/**
* Action performed when scroll animation ends.
*/
export function scrollOut() { // prevent scroll when tweening scroll export function scrollOut() { // prevent scroll when tweening scroll
const targets = getScrollTargets.call(this); const targets = getScrollTargets.call(this);
@ -50,23 +67,35 @@ export function scrollOut() { // prevent scroll when tweening scroll
} }
// Component Functions // Component Functions
/**
* * Sets the scroll target.
* * Adds the scroll prevention event listener.
* * Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartScroll(tweenProp) { export function onStartScroll(tweenProp) {
// checking 0 will NOT add the render function // checking 0 will NOT add the render function
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
this.element = ('scroll' in this.valuesEnd) && (!this.element || this.element === window) this.element = ('scroll' in this.valuesEnd) && (!this.element || this.element === window)
? scrollContainer : this.element; ? scrollContainer : this.element;
scrollIn.call(this); scrollIn.call(this);
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
/* eslint-disable */
elem.scrollTop = (numbers(a, b, v)) >> 0; elem.scrollTop = (numbers(a, b, v)) >> 0;
/* eslint-enable */
}; };
} }
} }
/**
* Removes the scroll prevention event listener.
*/
export function onCompleteScroll(/* tweenProp */) { export function onCompleteScroll(/* tweenProp */) {
scrollOut.call(this); scrollOut.call(this);
} }
// Base Component // Base Component
const baseScroll = { const ScrollPropertyBase = {
component: 'baseScroll', component: 'baseScroll',
property: 'scroll', property: 'scroll',
// defaultValue: 0, // defaultValue: 0,
@ -77,8 +106,8 @@ const baseScroll = {
}, },
// unfortunatelly scroll needs all them no matter the packaging // unfortunatelly scroll needs all them no matter the packaging
Util: { Util: {
preventScroll, scrollIn, scrollOut, getScrollTargets, supportPassive, preventScroll, scrollIn, scrollOut, getScrollTargets,
}, },
}; };
export default baseScroll; export default ScrollPropertyBase;

View file

@ -1,19 +1,25 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueColor from '../util/trueColor.js'; import trueColor from '../util/trueColor';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
import { onStartShadow } from './shadowPropertiesBase.js'; import { onStartShadow } from './shadowPropertiesBase';
// Component Properties // Component Properties
const shadowProps = ['boxShadow', 'textShadow']; const shadowProps = ['boxShadow', 'textShadow'];
// Component Util // Component Util
// box-shadow: none | h-shadow v-shadow blur spread color inset|initial|inherit /**
// text-shadow: none | offset-x offset-y blur-radius color |initial|inherit * Return the box-shadow / text-shadow tween object.
// utility function to process values accordingly * * box-shadow: none | h-shadow v-shadow blur spread color inset|initial|inherit
// numbers must be floats and color must be rgb object * * text-shadow: none | offset-x offset-y blur-radius color |initial|inherit
* * numbers must be floats and color must be rgb object
*
* @param {(number | string)[]} shadow an `Array` with shadow parameters
* @param {string} tweenProp the property name
* @returns {KUTE.shadowObject} the property tween object
*/
function processShadowArray(shadow, tweenProp) { function processShadowArray(shadow, tweenProp) {
let newShadow; let newShadow;
@ -45,12 +51,17 @@ function processShadowArray(shadow, tweenProp) {
newShadow = tweenProp === 'boxShadow' newShadow = tweenProp === 'boxShadow'
? newShadow ? newShadow
: newShadow.filter((x, i) => [0, 1, 2, 4].includes(i)); : newShadow.filter((_, i) => [0, 1, 2, 4].includes(i));
return newShadow; return newShadow;
} }
// Component Functions // Component Functions
/**
* Returns the current property computed style.
* @param {string} tweenProp the property name
* @returns {string} computed style for property
*/
export function getShadow(tweenProp/* , value */) { export function getShadow(tweenProp/* , value */) {
const cssShadow = getStyleForProperty(this.element, tweenProp); const cssShadow = getStyleForProperty(this.element, tweenProp);
// '0px 0px 0px 0px rgb(0,0,0)' // '0px 0px 0px 0px rgb(0,0,0)'
@ -59,6 +70,12 @@ export function getShadow(tweenProp/* , value */) {
: cssShadow; : cssShadow;
} }
/**
* Returns the property tween object.
* @param {string} tweenProp the property name
* @param {string} propValue the property value
* @returns {KUTE.shadowObject} the property tween object
*/
export function prepareShadow(tweenProp, propValue) { export function prepareShadow(tweenProp, propValue) {
// [horizontal, vertical, blur, spread, color: {r:0,g:0,b:0}, inset] // [horizontal, vertical, blur, spread, color: {r:0,g:0,b:0}, inset]
// parseProperty for boxShadow, builds basic structure with ready to tween values // parseProperty for boxShadow, builds basic structure with ready to tween values
@ -95,7 +112,7 @@ const shadowFunctions = {
}; };
// Component Full // Component Full
const shadowProperties = { const ShadowProperties = {
component: 'shadowProperties', component: 'shadowProperties',
properties: shadowProps, properties: shadowProps,
defaultValues: { defaultValues: {
@ -107,4 +124,4 @@ const shadowProperties = {
Util: { processShadowArray, trueColor }, Util: { processShadowArray, trueColor },
}; };
export default shadowProperties; export default ShadowProperties;

View file

@ -1,14 +1,18 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import colors from '../interpolation/colors.js'; import colors from '../interpolation/colors';
// Component Properties // Component Properties
const shadowProps = ['boxShadow', 'textShadow']; const shadowProps = ['boxShadow', 'textShadow'];
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartShadow(tweenProp) { export function onStartShadow(tweenProp) {
if (this.valuesEnd[tweenProp] && !KUTE[tweenProp]) { if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
// let's start with the numbers | set unit | also determine inset // let's start with the numbers | set unit | also determine inset
const params = []; const params = [];
const unit = 'px'; const unit = 'px';
@ -18,9 +22,11 @@ export function onStartShadow(tweenProp) {
const inset = (a[5] && a[5] !== 'none') || (b[5] && b[5] !== 'none') ? ' inset' : false; const inset = (a[5] && a[5] !== 'none') || (b[5] && b[5] !== 'none') ? ' inset' : false;
for (let i = 0; i < sl; i += 1) { for (let i = 0; i < sl; i += 1) {
/* eslint no-bitwise: ["error", { "allow": [">>"] }] */
params.push(((numbers(a[i], b[i], v) * 1000 >> 0) / 1000) + unit); params.push(((numbers(a[i], b[i], v) * 1000 >> 0) / 1000) + unit);
} }
// the final piece of the puzzle, the DOM update // the final piece of the puzzle, the DOM update
// eslint-disable-next-line no-param-reassign -- impossible to satisfy
elem.style[tweenProp] = inset elem.style[tweenProp] = inset
? colors(colA, colB, v) + params.join(' ') + inset ? colors(colA, colB, v) + params.join(' ') + inset
: colors(colA, colB, v) + params.join(' '); : colors(colA, colB, v) + params.join(' ');
@ -31,15 +37,10 @@ const shadowPropOnStart = {};
shadowProps.forEach((x) => { shadowPropOnStart[x] = onStartShadow; }); shadowProps.forEach((x) => { shadowPropOnStart[x] = onStartShadow; });
// Component Base // Component Base
const baseShadow = { const ShadowPropertiesBase = {
component: 'baseShadow', component: 'baseShadow',
// properties: shadowProps,
// defaultValues: {
// boxShadow :'0px 0px 0px 0px rgb(0,0,0)',
// textShadow: '0px 0px 0px 0px rgb(0,0,0)'
// },
Interpolate: { numbers, colors }, Interpolate: { numbers, colors },
functions: { onStart: shadowPropOnStart }, functions: { onStart: shadowPropOnStart },
}; };
export default baseShadow; export default ShadowPropertiesBase;

View file

@ -1,31 +1,31 @@
import parsePathString from 'svg-path-commander/src/process/parsePathString.js'; import parsePathString from 'svg-path-commander/src/parser/parsePathString';
import pathToAbsolute from 'svg-path-commander/src/convert/pathToAbsolute.js'; import pathToAbsolute from 'svg-path-commander/src/convert/pathToAbsolute';
import pathToCurve from 'svg-path-commander/src/convert/pathToCurve.js'; import pathToCurve from 'svg-path-commander/src/convert/pathToCurve';
import pathToString from 'svg-path-commander/src/convert/pathToString.js'; import pathToString from 'svg-path-commander/src/convert/pathToString';
import reverseCurve from 'svg-path-commander/src/process/reverseCurve.js'; import reverseCurve from 'svg-path-commander/src/process/reverseCurve';
import getDrawDirection from 'svg-path-commander/src/util/getDrawDirection.js'; import getDrawDirection from 'svg-path-commander/src/util/getDrawDirection';
import clonePath from 'svg-path-commander/src/process/clonePath.js'; import clonePath from 'svg-path-commander/src/process/clonePath';
import splitCubic from 'svg-path-commander/src/process/splitCubic.js'; import splitCubic from 'svg-path-commander/src/process/splitCubic';
import splitPath from 'svg-path-commander/src/process/splitPath.js'; import splitPath from 'svg-path-commander/src/process/splitPath';
import getSegCubicLength from 'svg-path-commander/src/util/getSegCubicLength.js'; import fixPath from 'svg-path-commander/src/process/fixPath';
import distanceSquareRoot from 'svg-path-commander/src/math/distanceSquareRoot.js'; import getSegCubicLength from 'svg-path-commander/src/util/getSegCubicLength';
import { onStartCubicMorph } from './svgCubicMorphBase.js'; import distanceSquareRoot from 'svg-path-commander/src/math/distanceSquareRoot';
import numbers from '../interpolation/numbers.js';
import selector from '../util/selector.js';
/* SVGMorph = { import { onStartCubicMorph } from './svgCubicMorphBase';
property: 'path', import numbers from '../interpolation/numbers';
defaultValue: [], import selector from '../util/selector';
interpolators: {numbers},
functions = { prepareStart, prepareProperty, onStart, crossCheck }
} */
// Component Util // Component Util
function getCurveArray(pathString) { /**
return pathToCurve(splitPath(pathToString(pathToAbsolute(pathString)))[0]) * Returns first `pathArray` from multi-paths path.
* @param {SVGPathCommander.pathArray | string} source the source `pathArray` or string
* @returns {KUTE.curveSpecs[]} an `Array` with a custom tuple for `equalizeSegments`
*/
function getCurveArray(source) {
return pathToCurve(splitPath(source)[0])
.map((segment, i, pathArray) => { .map((segment, i, pathArray) => {
const segmentData = i && pathArray[i - 1].slice(-2).concat(segment.slice(1)); const segmentData = i && [...pathArray[i - 1].slice(-2), ...segment.slice(1)];
const curveLength = i ? getSegCubicLength.apply(0, segmentData) : 0; const curveLength = i ? getSegCubicLength(...segmentData) : 0;
let subsegs; let subsegs;
if (i) { if (i) {
@ -43,6 +43,13 @@ function getCurveArray(pathString) {
}); });
} }
/**
* Returns two `curveArray` with same amount of segments.
* @param {SVGPathCommander.curveArray} path1 the first `curveArray`
* @param {SVGPathCommander.curveArray} path2 the second `curveArray`
* @param {number} TL the maximum `curveArray` length
* @returns {SVGPathCommander.curveArray[]} equalized segments
*/
function equalizeSegments(path1, path2, TL) { function equalizeSegments(path1, path2, TL) {
const c1 = getCurveArray(path1); const c1 = getCurveArray(path1);
const c2 = getCurveArray(path2); const c2 = getCurveArray(path2);
@ -70,23 +77,34 @@ function equalizeSegments(path1, path2, TL) {
: equalizeSegments(result[0], result[1], tl); : equalizeSegments(result[0], result[1], tl);
} }
/**
* Returns all possible path rotations for `curveArray`.
* @param {SVGPathCommander.curveArray} a the source `curveArray`
* @returns {SVGPathCommander.curveArray[]} all rotations for source
*/
function getRotations(a) { function getRotations(a) {
const segCount = a.length; const segCount = a.length;
const pointCount = segCount - 1; const pointCount = segCount - 1;
return a.map((f, idx) => a.map((p, i) => { return a.map((_, idx) => a.map((__, i) => {
let oldSegIdx = idx + i; let oldSegIdx = idx + i;
let seg; let seg;
if (i === 0 || (a[oldSegIdx] && a[oldSegIdx][0] === 'M')) { if (i === 0 || (a[oldSegIdx] && a[oldSegIdx][0] === 'M')) {
seg = a[oldSegIdx]; seg = a[oldSegIdx];
return ['M'].concat(seg.slice(-2)); return ['M', ...seg.slice(-2)];
} }
if (oldSegIdx >= segCount) oldSegIdx -= pointCount; if (oldSegIdx >= segCount) oldSegIdx -= pointCount;
return a[oldSegIdx]; return a[oldSegIdx];
})); }));
} }
/**
* Returns the `curveArray` rotation for the best morphing animation.
* @param {SVGPathCommander.curveArray} a the target `curveArray`
* @param {SVGPathCommander.curveArray} b the reference `curveArray`
* @returns {SVGPathCommander.curveArray} the best `a` rotation
*/
function getRotatedCurve(a, b) { function getRotatedCurve(a, b) {
const segCount = a.length - 1; const segCount = a.length - 1;
const lineLengths = []; const lineLengths = [];
@ -94,8 +112,8 @@ function getRotatedCurve(a, b) {
let sumLensSqrd = 0; let sumLensSqrd = 0;
const rotations = getRotations(a); const rotations = getRotations(a);
rotations.forEach((r, i) => { rotations.forEach((_, i) => {
a.slice(1).forEach((s, j) => { a.slice(1).forEach((__, j) => {
sumLensSqrd += distanceSquareRoot(a[(i + j) % segCount].slice(-2), b[j % segCount].slice(-2)); sumLensSqrd += distanceSquareRoot(a[(i + j) % segCount].slice(-2), b[j % segCount].slice(-2));
}); });
lineLengths[i] = sumLensSqrd; lineLengths[i] = sumLensSqrd;
@ -108,10 +126,23 @@ function getRotatedCurve(a, b) {
} }
// Component Functions // Component Functions
/**
* Returns the current `d` attribute value.
* @returns {string}
*/
function getCubicMorph(/* tweenProp, value */) { function getCubicMorph(/* tweenProp, value */) {
return this.element.getAttribute('d'); return this.element.getAttribute('d');
} }
function prepareCubicMorph(tweenProp, value) {
/**
* Returns the property tween object.
* @see KUTE.curveObject
*
* @param {string} _ is the `path` property name, not needed
* @param {string | KUTE.curveObject} value the `path` property value
* @returns {KUTE.curveObject}
*/
function prepareCubicMorph(/* tweenProp, */_, value) {
// get path d attribute or create a path from string value // get path d attribute or create a path from string value
const pathObject = {}; const pathObject = {};
// remove newlines, they break some JSON strings // remove newlines, they break some JSON strings
@ -135,7 +166,12 @@ function prepareCubicMorph(tweenProp, value) {
} }
return pathObject; return pathObject;
} }
function crossCheckCubicMorph(tweenProp) {
/**
* Enables the `to()` method by preparing the tween object in advance.
* @param {string} tweenProp is `path` tween property, but it's not needed
*/
function crossCheckCubicMorph(tweenProp/** , value */) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
const pathCurve1 = this.valuesStart[tweenProp].curve; const pathCurve1 = this.valuesStart[tweenProp].curve;
const pathCurve2 = this.valuesEnd[tweenProp].curve; const pathCurve2 = this.valuesEnd[tweenProp].curve;
@ -183,6 +219,8 @@ const svgCubicMorph = {
clonePath, clonePath,
getDrawDirection, getDrawDirection,
splitCubic, splitCubic,
splitPath,
fixPath,
getCurveArray, getCurveArray,
}, },
}; };

View file

@ -1,24 +1,23 @@
import pathToString from 'svg-path-commander/src/convert/pathToString.js'; import pathToString from 'svg-path-commander/src/convert/pathToString';
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
/* SVGMorph = {
property: 'path',
defaultValue: [],
interpolators: {numbers} },
functions = { prepareStart, prepareProperty, onStart, crossCheck }
} */
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the `path` property
*/
export function onStartCubicMorph(tweenProp) { export function onStartCubicMorph(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
KUTE[tweenProp] = function updateMorph(elem, a, b, v) { KEC[tweenProp] = function updateMorph(elem, a, b, v) {
const curve = []; const curve = [];
const path1 = a.curve; const path1 = a.curve;
const path2 = b.curve; const path2 = b.curve;
for (let i = 0, l = path2.length; i < l; i += 1) { // each path command for (let i = 0, l = path2.length; i < l; i += 1) { // each path command
curve.push([path1[i][0]]); curve.push([path1[i][0]]);
for (let j = 1, l2 = path1[i].length; j < l2; j += 1) { // each command coordinate for (let j = 1, l2 = path1[i].length; j < l2; j += 1) { // each command coordinate
/* eslint-disable-next-line no-bitwise -- impossible to satisfy */
curve[i].push((numbers(path1[i][j], path2[i][j], v) * 1000 >> 0) / 1000); curve[i].push((numbers(path1[i][j], path2[i][j], v) * 1000 >> 0) / 1000);
} }
} }

View file

@ -1,29 +1,36 @@
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { onStartDraw } from './svgDrawBase.js'; import { onStartDraw } from './svgDrawBase';
/* svgDraw = {
property: 'draw',
defaultValue,
Interpolate: {numbers} },
functions = { prepareStart, prepareProperty, onStart }
} */
// Component Util // Component Util
/**
* Convert a `<path>` length percent value to absolute.
* @param {string} v raw value
* @param {number} l length value
* @returns {number} the absolute value
*/
function percent(v, l) { function percent(v, l) {
return (parseFloat(v) / 100) * l; return (parseFloat(v) / 100) * l;
} }
// http://stackoverflow.com/a/30376660 /**
// returns the length of a Rect * Returns the `<rect>` length.
* It doesn't compute `rx` and / or `ry` of the element.
* @see http://stackoverflow.com/a/30376660
* @param {SVGRectElement} el target element
* @returns {number} the `<rect>` length
*/
function getRectLength(el) { function getRectLength(el) {
const w = el.getAttribute('width'); const w = el.getAttribute('width');
const h = el.getAttribute('height'); const h = el.getAttribute('height');
return (w * 2) + (h * 2); return (w * 2) + (h * 2);
} }
// getPolygonLength / getPolylineLength /**
// returns the length of the Polygon / Polyline * Returns the `<polyline>` / `<polygon>` length.
* @param {SVGPolylineElement | SVGPolygonElement} el target element
* @returns {number} the element length
*/
function getPolyLength(el) { function getPolyLength(el) {
const points = el.getAttribute('points').split(' '); const points = el.getAttribute('points').split(' ');
@ -54,7 +61,11 @@ function getPolyLength(el) {
return len; return len;
} }
// return the length of the line /**
* Returns the `<line>` length.
* @param {SVGLineElement} el target element
* @returns {number} the element length
*/
function getLineLength(el) { function getLineLength(el) {
const x1 = el.getAttribute('x1'); const x1 = el.getAttribute('x1');
const x2 = el.getAttribute('x2'); const x2 = el.getAttribute('x2');
@ -63,13 +74,22 @@ function getLineLength(el) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
} }
// return the length of the circle /**
* Returns the `<circle>` length.
* @param {SVGCircleElement} el target element
* @returns {number} the element length
*/
function getCircleLength(el) { function getCircleLength(el) {
const r = el.getAttribute('r'); const r = el.getAttribute('r');
return 2 * Math.PI * r; return 2 * Math.PI * r;
} }
// returns the length of an ellipse // returns the length of an ellipse
/**
* Returns the `<ellipse>` length.
* @param {SVGEllipseElement} el target element
* @returns {number} the element length
*/
function getEllipseLength(el) { function getEllipseLength(el) {
const rx = el.getAttribute('rx'); const rx = el.getAttribute('rx');
const ry = el.getAttribute('ry'); const ry = el.getAttribute('ry');
@ -78,7 +98,11 @@ function getEllipseLength(el) {
return ((Math.sqrt(0.5 * ((len * len) + (wid * wid)))) * (Math.PI * 2)) / 2; return ((Math.sqrt(0.5 * ((len * len) + (wid * wid)))) * (Math.PI * 2)) / 2;
} }
// returns the result of any of the below functions /**
* Returns the shape length.
* @param {SVGPathCommander.shapeTypes} el target element
* @returns {number} the element length
*/
function getTotalLength(el) { function getTotalLength(el) {
if (el.tagName === 'rect') { if (el.tagName === 'rect') {
return getRectLength(el); return getRectLength(el);
@ -95,6 +119,12 @@ function getTotalLength(el) {
return 0; return 0;
} }
/**
* Returns the property tween object.
* @param {SVGPathCommander.shapeTypes} element the target element
* @param {string | KUTE.drawObject} value the property value
* @returns {KUTE.drawObject} the property tween object
*/
function getDraw(element, value) { function getDraw(element, value) {
const length = /path|glyph/.test(element.tagName) const length = /path|glyph/.test(element.tagName)
? element.getTotalLength() ? element.getTotalLength()
@ -104,7 +134,7 @@ function getDraw(element, value) {
let dasharray; let dasharray;
let offset; let offset;
if (value instanceof Object) { if (value instanceof Object && Object.keys(value).every((v) => ['s', 'e', 'l'].includes(v))) {
return value; return value;
} if (typeof value === 'string') { } if (typeof value === 'string') {
const v = value.split(/,|\s/); const v = value.split(/,|\s/);
@ -120,17 +150,33 @@ function getDraw(element, value) {
return { s: start, e: end, l: length }; return { s: start, e: end, l: length };
} }
/**
* Reset CSS properties associated with the `draw` property.
* @param {SVGPathCommander.shapeTypes} element target
*/
function resetDraw(elem) { function resetDraw(elem) {
/* eslint-disable no-param-reassign -- impossible to satisfy */
elem.style.strokeDashoffset = ''; elem.style.strokeDashoffset = '';
elem.style.strokeDasharray = ''; elem.style.strokeDasharray = '';
/* eslint-disable no-param-reassign -- impossible to satisfy */
} }
// Component Functions // Component Functions
/**
* Returns the property tween object.
* @returns {KUTE.drawObject} the property tween object
*/
function getDrawValue(/* prop, value */) { function getDrawValue(/* prop, value */) {
return getDraw(this.element); return getDraw(this.element);
} }
function prepareDraw(a, o) { /**
return getDraw(this.element, o); * Returns the property tween object.
* @param {string} _ the property name
* @param {string | KUTE.drawObject} value the property value
* @returns {KUTE.drawObject} the property tween object
*/
function prepareDraw(_, value) {
return getDraw(this.element, value);
} }
// All Component Functions // All Component Functions
@ -141,7 +187,7 @@ const svgDrawFunctions = {
}; };
// Component Full // Component Full
const svgDraw = { const SvgDrawProperty = {
component: 'svgDraw', component: 'svgDraw',
property: 'draw', property: 'draw',
defaultValue: '0% 0%', defaultValue: '0% 0%',
@ -161,4 +207,4 @@ const svgDraw = {
}, },
}; };
export default svgDraw; export default SvgDrawProperty;

View file

@ -1,35 +1,35 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
/* svgDraw = {
property: 'draw',
defaultValue,
Interpolate: {numbers} },
functions = { prepareStart, prepareProperty, onStart }
} */
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartDraw(tweenProp) { export function onStartDraw(tweenProp) {
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { if (tweenProp in this.valuesEnd && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
/* eslint-disable no-bitwise -- impossible to satisfy */
const pathLength = (a.l * 100 >> 0) / 100; const pathLength = (a.l * 100 >> 0) / 100;
const start = (numbers(a.s, b.s, v) * 100 >> 0) / 100; const start = (numbers(a.s, b.s, v) * 100 >> 0) / 100;
const end = (numbers(a.e, b.e, v) * 100 >> 0) / 100; const end = (numbers(a.e, b.e, v) * 100 >> 0) / 100;
const offset = 0 - start; const offset = 0 - start;
const dashOne = end + offset; const dashOne = end + offset;
// eslint-disable-next-line no-param-reassign -- impossible to satisfy
elem.style.strokeDashoffset = `${offset}px`; elem.style.strokeDashoffset = `${offset}px`;
// eslint-disable-next-line no-param-reassign -- impossible to satisfy
elem.style.strokeDasharray = `${((dashOne < 1 ? 0 : dashOne) * 100 >> 0) / 100}px, ${pathLength}px`; elem.style.strokeDasharray = `${((dashOne < 1 ? 0 : dashOne) * 100 >> 0) / 100}px, ${pathLength}px`;
/* eslint-disable no-bitwise -- impossible to satisfy */
}; };
} }
} }
// Component Base // Component Base
const baseSVGDraw = { const SvgDrawBase = {
component: 'baseSVGDraw', component: 'baseSVGDraw',
property: 'draw', property: 'draw',
Interpolate: { numbers }, Interpolate: { numbers },
functions: { onStart: onStartDraw }, functions: { onStart: onStartDraw },
}; };
export default baseSVGDraw; export default SvgDrawBase;

View file

@ -1,46 +1,45 @@
import pathToCurve from 'svg-path-commander/src/convert/pathToCurve.js'; import pathToCurve from 'svg-path-commander/src/convert/pathToCurve';
import pathToString from 'svg-path-commander/src/convert/pathToString.js'; import pathToString from 'svg-path-commander/src/convert/pathToString';
import normalizePath from 'svg-path-commander/src/process/normalizePath.js'; import normalizePath from 'svg-path-commander/src/process/normalizePath';
import splitPath from 'svg-path-commander/src/process/splitPath.js'; import splitPath from 'svg-path-commander/src/process/splitPath';
import roundPath from 'svg-path-commander/src/process/roundPath.js'; import roundPath from 'svg-path-commander/src/process/roundPath';
import invalidPathValue from 'svg-path-commander/src/util/invalidPathValue.js'; import invalidPathValue from 'svg-path-commander/src/parser/invalidPathValue';
import getPathLength from 'svg-path-commander/src/util/getPathLength.js'; import getPathLength from 'svg-path-commander/src/util/getPathLength';
import getPointAtLength from 'svg-path-commander/src/util/getPointAtLength.js'; import getPointAtLength from 'svg-path-commander/src/util/getPointAtLength';
import getDrawDirection from 'svg-path-commander/src/util/getDrawDirection.js'; import getDrawDirection from 'svg-path-commander/src/util/getDrawDirection';
import epsilon from 'svg-path-commander/src/math/epsilon.js'; import epsilon from 'svg-path-commander/src/math/epsilon';
import midPoint from 'svg-path-commander/src/math/midPoint.js'; import midPoint from 'svg-path-commander/src/math/midPoint';
import distanceSquareRoot from 'svg-path-commander/src/math/distanceSquareRoot.js'; import distanceSquareRoot from 'svg-path-commander/src/math/distanceSquareRoot';
import { onStartSVGMorph } from './svgMorphBase.js'; import { onStartSVGMorph } from './svgMorphBase';
import coords from '../interpolation/coords.js'; import coords from '../interpolation/coords';
import defaultOptions from '../objects/defaultOptions.js'; import defaultOptions from '../objects/defaultOptions';
import selector from '../util/selector.js'; import selector from '../util/selector';
/* SVGMorph = {
property: 'path',
defaultValue: [],
interpolators: {numbers,coords},
functions = { prepareStart, prepareProperty, onStart, crossCheck }
} */
// Component Interpolation
// function function(array1, array2, length, progress)
// Component Util // Component Util
// original script flubber // original script flubber
// https://github.com/veltman/flubber // https://github.com/veltman/flubber
function polygonLength(ring) { /**
return ring.reduce((length, point, i) => (i * Returns polygon length.
? length + distanceSquareRoot(ring[i - 1], point) * @param {KUTE.polygonMorph} polygon target polygon
* @returns {number} length
*/
function polygonLength(polygon) {
return polygon.reduce((length, point, i) => (i
? length + distanceSquareRoot(polygon[i - 1], point)
: 0), 0); : 0), 0);
} }
/**
* Returns an existing polygin and its length or false if not polygon.
* @param {SVGPathCommander.pathArray} pathArray target polygon
* @returns {KUTE.exactRing} length
*/
function exactRing(pathArray) { function exactRing(pathArray) {
const ring = []; const polygon = [];
const pathlen = pathArray.length; const pathlen = pathArray.length;
let segment = []; let segment = [];
let pathCommand = ''; let pathCommand = '';
let pathLength = 0;
if (!pathArray.length || pathArray[0][0] !== 'M') { if (!pathArray.length || pathArray[0][0] !== 'M') {
return false; return false;
@ -52,54 +51,68 @@ function exactRing(pathArray) {
if ((pathCommand === 'M' && i) || pathCommand === 'Z') { if ((pathCommand === 'M' && i) || pathCommand === 'Z') {
break; // !! break; // !!
} else if ('ML'.indexOf(pathCommand) > -1) { } else if ('ML'.includes(pathCommand)) {
ring.push([segment[1], segment[2]]); polygon.push([segment[1], segment[2]]);
} else { } else {
return false; return false;
} }
} }
pathLength = polygonLength(ring); return pathlen ? { polygon } : false;
return pathlen ? { ring, pathLength } : false;
} }
function approximateRing(parsed, maxSegmentLength) { /**
* Returns polygon length.
* @param {SVGPathCommander.pathArray} parsed target polygon
* @param {number} maxLength the maximum segment length
* @returns {KUTE.exactRing} length
*/
function approximatePolygon(parsed, maxLength) {
const ringPath = splitPath(pathToString(parsed))[0]; const ringPath = splitPath(pathToString(parsed))[0];
const curvePath = pathToCurve(ringPath, 4); const curvePath = pathToCurve(ringPath);
const pathLength = getPathLength(curvePath); const pathLength = getPathLength(curvePath);
const ring = []; const polygon = [];
let numPoints = 3; let numPoints = 3;
let point; let point;
if (maxSegmentLength && !Number.isNaN(maxSegmentLength) && +maxSegmentLength > 0) { if (maxLength && !Number.isNaN(maxLength) && +maxLength > 0) {
numPoints = Math.max(numPoints, Math.ceil(pathLength / maxSegmentLength)); numPoints = Math.max(numPoints, Math.ceil(pathLength / maxLength));
} }
for (let i = 0; i < numPoints; i += 1) { for (let i = 0; i < numPoints; i += 1) {
point = getPointAtLength(curvePath, (pathLength * i) / numPoints); point = getPointAtLength(curvePath, (pathLength * i) / numPoints);
ring.push([point.x, point.y]); polygon.push([point.x, point.y]);
} }
// Make all rings clockwise // Make all rings clockwise
if (!getDrawDirection(curvePath)) { if (!getDrawDirection(curvePath)) {
ring.reverse(); polygon.reverse();
} }
return { return {
pathLength, polygon,
ring,
skipBisect: true, skipBisect: true,
}; };
} }
function pathStringToRing(str, maxSegmentLength) { /**
const parsed = normalizePath(str, 0); * Parses a path string and returns a polygon array.
return exactRing(parsed) || approximateRing(parsed, maxSegmentLength); * @param {string} str path string
* @param {number} maxLength maximum amount of points
* @returns {KUTE.exactRing} the polygon array we need
*/
function pathStringToPolygon(str, maxLength) {
const parsed = normalizePath(str);
return exactRing(parsed) || approximatePolygon(parsed, maxLength);
} }
function rotateRing(ring, vs) { /**
const len = ring.length; * Rotates a polygon to better match its pair.
* @param {KUTE.polygonMorph} polygon the target polygon
* @param {KUTE.polygonMorph} vs the reference polygon
*/
function rotatePolygon(polygon, vs) {
const len = polygon.length;
let min = Infinity; let min = Infinity;
let bestOffset; let bestOffset;
let sumOfSquares = 0; let sumOfSquares = 0;
@ -110,13 +123,9 @@ function rotateRing(ring, vs) {
for (let offset = 0; offset < len; offset += 1) { for (let offset = 0; offset < len; offset += 1) {
sumOfSquares = 0; sumOfSquares = 0;
// vs.forEach((p, i) => {
// const d = distanceSquareRoot(ring[(offset + i) % len], p);
// sumOfSquares += d * d;
// });
for (let i = 0; i < vs.length; i += 1) { for (let i = 0; i < vs.length; i += 1) {
p = vs[i]; p = vs[i];
d = distanceSquareRoot(ring[(offset + i) % len], p); d = distanceSquareRoot(polygon[(offset + i) % len], p);
sumOfSquares += d * d; sumOfSquares += d * d;
} }
@ -127,15 +136,19 @@ function rotateRing(ring, vs) {
} }
if (bestOffset) { if (bestOffset) {
spliced = ring.splice(0, bestOffset); spliced = polygon.splice(0, bestOffset);
ring.splice(ring.length, 0, ...spliced); polygon.splice(polygon.length, 0, ...spliced);
} }
} }
function addPoints(ring, numPoints) { /**
const desiredLength = ring.length + numPoints; * Sample additional points for a polygon to better match its pair.
// const step = ring.pathLength / numPoints; * @param {KUTE.polygonObject} polygon the target polygon
const step = polygonLength(ring) / numPoints; * @param {number} numPoints the amount of points needed
*/
function addPoints(polygon, numPoints) {
const desiredLength = polygon.length + numPoints;
const step = polygonLength(polygon) / numPoints;
let i = 0; let i = 0;
let cursor = 0; let cursor = 0;
@ -144,14 +157,14 @@ function addPoints(ring, numPoints) {
let b; let b;
let segment; let segment;
while (ring.length < desiredLength) { while (polygon.length < desiredLength) {
a = ring[i]; a = polygon[i];
b = ring[(i + 1) % ring.length]; b = polygon[(i + 1) % polygon.length];
segment = distanceSquareRoot(a, b); segment = distanceSquareRoot(a, b);
if (insertAt <= cursor + segment) { if (insertAt <= cursor + segment) {
ring.splice(i + 1, 0, segment polygon.splice(i + 1, 0, segment
? midPoint(a, b, (insertAt - cursor) / segment) ? midPoint(a, b, (insertAt - cursor) / segment)
: a.slice(0)); : a.slice(0));
insertAt += step; insertAt += step;
@ -162,48 +175,62 @@ function addPoints(ring, numPoints) {
} }
} }
function bisect(ring, maxSegmentLength = Infinity) { /**
* Split segments of a polygon until it reaches a certain
* amount of points.
* @param {number[][]} polygon the target polygon
* @param {number} maxSegmentLength the maximum amount of points
*/
function bisect(polygon, maxSegmentLength = Infinity) {
let a = []; let a = [];
let b = []; let b = [];
for (let i = 0; i < ring.length; i += 1) { for (let i = 0; i < polygon.length; i += 1) {
a = ring[i]; a = polygon[i];
b = i === ring.length - 1 ? ring[0] : ring[i + 1]; b = i === polygon.length - 1 ? polygon[0] : polygon[i + 1];
// Could splice the whole set for a segment instead, but a bit messy // Could splice the whole set for a segment instead, but a bit messy
while (distanceSquareRoot(a, b) > maxSegmentLength) { while (distanceSquareRoot(a, b) > maxSegmentLength) {
b = midPoint(a, b, 0.5); b = midPoint(a, b, 0.5);
ring.splice(i + 1, 0, b); polygon.splice(i + 1, 0, b);
} }
} }
} }
function validRing(ring) { /**
return Array.isArray(ring) * Checks the validity of a polygon.
&& ring.every((point) => Array.isArray(point) * @param {KUTE.polygonMorph} polygon the target polygon
* @returns {boolean} the result of the check
*/
function validPolygon(polygon) {
return Array.isArray(polygon)
&& polygon.every((point) => Array.isArray(point)
&& point.length === 2 && point.length === 2
&& !Number.isNaN(point[0]) && !Number.isNaN(point[0])
&& !Number.isNaN(point[1])); && !Number.isNaN(point[1]));
} }
function normalizeRing(input, maxSegmentLength) { /**
* Returns a new polygon and its length from string or another `Array`.
* @param {KUTE.polygonMorph | string} input the target polygon
* @param {number} maxSegmentLength the maximum amount of points
* @returns {KUTE.polygonMorph} normalized polygon
*/
function getPolygon(input, maxSegmentLength) {
let skipBisect; let skipBisect;
let pathLength; let polygon;
let ring = input;
if (typeof (ring) === 'string') { if (typeof (input) === 'string') {
const converted = pathStringToRing(ring, maxSegmentLength); const converted = pathStringToPolygon(input, maxSegmentLength);
ring = converted.ring; ({ polygon, skipBisect } = converted);
skipBisect = converted.skipBisect; } else if (!Array.isArray(input)) {
pathLength = converted.pathLength; throw Error(`${invalidPathValue}: ${input}`);
} else if (!Array.isArray(ring)) {
throw Error(`${invalidPathValue}: ${ring}`);
} }
const points = ring.slice(0); /** @type {KUTE.polygonMorph} */
points.pathLength = pathLength; const points = [...polygon];
if (!validRing(points)) { if (!validPolygon(points)) {
throw Error(`${invalidPathValue}: ${points}`); throw Error(`${invalidPathValue}: ${points}`);
} }
@ -221,39 +248,56 @@ function normalizeRing(input, maxSegmentLength) {
return points; return points;
} }
function getInterpolationPoints(pathArray1, pathArray2, precision) { /**
* Returns two new polygons ready to tween.
* @param {string} path1 the first path string
* @param {string} path2 the second path string
* @param {number} precision the morphPrecision option value
* @returns {KUTE.polygonMorph[]} the two polygons
*/
function getInterpolationPoints(path1, path2, precision) {
const morphPrecision = precision || defaultOptions.morphPrecision; const morphPrecision = precision || defaultOptions.morphPrecision;
const fromRing = normalizeRing(pathArray1, morphPrecision); const fromRing = getPolygon(path1, morphPrecision);
const toRing = normalizeRing(pathArray2, morphPrecision); const toRing = getPolygon(path2, morphPrecision);
const diff = fromRing.length - toRing.length; const diff = fromRing.length - toRing.length;
addPoints(fromRing, diff < 0 ? diff * -1 : 0); addPoints(fromRing, diff < 0 ? diff * -1 : 0);
addPoints(toRing, diff > 0 ? diff : 0); addPoints(toRing, diff > 0 ? diff : 0);
rotateRing(fromRing, toRing); rotatePolygon(fromRing, toRing);
return [roundPath(fromRing), roundPath(toRing)]; return [roundPath(fromRing), roundPath(toRing)];
} }
// Component functions // Component functions
/**
* Returns the current `d` attribute value.
* @returns {string} the `d` attribute value
*/
function getSVGMorph(/* tweenProp */) { function getSVGMorph(/* tweenProp */) {
return this.element.getAttribute('d'); return this.element.getAttribute('d');
} }
function prepareSVGMorph(tweenProp, value) { /**
* Returns the property tween object.
* @param {string} _ the property name
* @param {string | KUTE.polygonObject} value the property value
* @returns {KUTE.polygonObject} the property tween object
*/
function prepareSVGMorph(/* tweenProp */_, value) {
const pathObject = {}; const pathObject = {};
// remove newlines, they brake JSON strings sometimes // remove newlines, they brake JSON strings sometimes
const pathReg = new RegExp('\\n', 'ig'); const pathReg = new RegExp('\\n', 'ig');
let elem = null; let elem = null;
if (value instanceof SVGElement) { if (value instanceof SVGPathElement) {
elem = value; elem = value;
} else if (/^\.|^#/.test(value)) { } else if (/^\.|^#/.test(value)) {
elem = selector(value); elem = selector(value);
} }
// first make sure we return pre-processed values // first make sure we return pre-processed values
if (typeof (value) === 'object' && value.pathArray) { if (typeof (value) === 'object' && value.polygon) {
return value; return value;
} if (elem && ['path', 'glyph'].includes(elem.tagName)) { } if (elem && ['path', 'glyph'].includes(elem.tagName)) {
pathObject.original = elem.getAttribute('d').replace(pathReg, ''); pathObject.original = elem.getAttribute('d').replace(pathReg, '');
@ -264,10 +308,15 @@ function prepareSVGMorph(tweenProp, value) {
return pathObject; return pathObject;
} }
/**
* Enables the `to()` method by preparing the tween object in advance.
* @param {string} prop the `path` property name
*/
function crossCheckSVGMorph(prop) { function crossCheckSVGMorph(prop) {
if (this.valuesEnd[prop]) { if (this.valuesEnd[prop]) {
const pathArray1 = this.valuesStart[prop].pathArray; const pathArray1 = this.valuesStart[prop].polygon;
const pathArray2 = this.valuesEnd[prop].pathArray; const pathArray2 = this.valuesEnd[prop].polygon;
// skip already processed paths // skip already processed paths
// allow the component to work with pre-processed values // allow the component to work with pre-processed values
if (!pathArray1 || !pathArray2 if (!pathArray1 || !pathArray2
@ -280,8 +329,8 @@ function crossCheckSVGMorph(prop) {
: defaultOptions.morphPrecision; : defaultOptions.morphPrecision;
const [path1, path2] = getInterpolationPoints(p1, p2, morphPrecision); const [path1, path2] = getInterpolationPoints(p1, p2, morphPrecision);
this.valuesStart[prop].pathArray = path1; this.valuesStart[prop].polygon = path1;
this.valuesEnd[prop].pathArray = path2; this.valuesEnd[prop].polygon = path2;
} }
} }
} }
@ -295,27 +344,29 @@ const svgMorphFunctions = {
}; };
// Component Full // Component Full
const svgMorph = { const SVGMorph = {
component: 'svgMorph', component: 'svgMorph',
property: 'path', property: 'path',
defaultValue: [], defaultValue: [],
Interpolate: coords, Interpolate: coords,
defaultOptions: { morphPrecision: 10, morphIndex: 0 }, defaultOptions: { morphPrecision: 10 },
functions: svgMorphFunctions, functions: svgMorphFunctions,
// Export utils to global for faster execution // Export utils to global for faster execution
Util: { Util: {
// component
addPoints, addPoints,
bisect, bisect,
normalizeRing, getPolygon,
validRing, // component validPolygon,
getInterpolationPoints, getInterpolationPoints,
pathStringToRing, pathStringToPolygon,
distanceSquareRoot, distanceSquareRoot,
midPoint, midPoint,
approximateRing, approximatePolygon,
rotateRing, rotatePolygon,
// svg-path-commander
pathToString, pathToString,
pathToCurve, // svg-path-commander pathToCurve,
getPathLength, getPathLength,
getPointAtLength, getPointAtLength,
getDrawDirection, getDrawDirection,
@ -323,4 +374,4 @@ const svgMorph = {
}, },
}; };
export default svgMorph; export default SVGMorph;

View file

@ -1,5 +1,5 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import coords from '../interpolation/coords.js'; import coords from '../interpolation/coords';
/* SVGMorph = { /* SVGMorph = {
property: 'path', property: 'path',
@ -9,22 +9,26 @@ import coords from '../interpolation/coords.js';
} */ } */
// Component functions // Component functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartSVGMorph(tweenProp) { export function onStartSVGMorph(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
const path1 = a.pathArray; const path2 = b.pathArray; const const path1 = a.polygon; const path2 = b.polygon;
len = path2.length; const len = path2.length;
elem.setAttribute('d', (v === 1 ? b.original : `M${coords(path1, path2, len, v).join('L')}Z`)); elem.setAttribute('d', (v === 1 ? b.original : `M${coords(path1, path2, len, v).join('L')}Z`));
}; };
} }
} }
// Component Base // Component Base
const baseSVGMorph = { const SVGMorphBase = {
component: 'baseSVGMorph', component: 'baseSVGMorph',
property: 'path', property: 'path',
Interpolate: coords, Interpolate: coords,
functions: { onStart: onStartSVGMorph }, functions: { onStart: onStartSVGMorph },
}; };
export default baseSVGMorph; export default SVGMorphBase;

View file

@ -1,17 +1,16 @@
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { svgTransformOnStart } from './svgTransformBase.js'; import { svgTransformOnStart } from './svgTransformBase';
/* const svgTransform = {
property: 'svgTransform',
subProperties,
defaultValue,
Interpolate: {numbers},
functions
} */
// Component Util // Component Util
function parseStringOrigin(origin, { x, width }) { /**
* Returns a correct transform origin consistent with the shape bounding box.
* @param {string} origin transform origin string
* @param {SVGPathCommander.pathBBox} bbox path bounding box
* @returns {number}
*/
function parseStringOrigin(origin, bbox) {
let result; let result;
const { x, width } = bbox;
if (/[a-z]/i.test(origin) && !/px/.test(origin)) { if (/[a-z]/i.test(origin) && !/px/.test(origin)) {
result = origin.replace(/top|left/, 0) result = origin.replace(/top|left/, 0)
.replace(/right|bottom/, 100) .replace(/right|bottom/, 100)
@ -22,7 +21,11 @@ function parseStringOrigin(origin, { x, width }) {
return result; return result;
} }
// helper function that turns transform value from string to object /**
* Parse SVG transform string and return an object.
* @param {string} a transform string
* @returns {Object<string, (string | number)>}
*/
function parseTransformString(a) { function parseTransformString(a) {
const c = {}; const c = {};
const d = a && /\)/.test(a) const d = a && /\)/.test(a)
@ -38,7 +41,14 @@ function parseTransformString(a) {
return c; return c;
} }
function parseTransformSVG(p, v) { /**
* Returns the SVG transform tween object.
* @param {string} _ property name
* @param {Object<string, (string | number)>} v property value object
* @returns {KUTE.transformSVGObject} the SVG transform tween object
*/
function parseTransformSVG(/* prop */_, v) {
/** @type {KUTE.transformSVGObject} */
const svgTransformObject = {}; const svgTransformObject = {};
// by default the transformOrigin is "50% 50%" of the shape box // by default the transformOrigin is "50% 50%" of the shape box
@ -90,12 +100,23 @@ function parseTransformSVG(p, v) {
} }
// Component Functions // Component Functions
function prepareSvgTransform(p, v) { /**
return parseTransformSVG.call(this, p, v); * Returns the property tween object.
* @param {string} prop the property name
* @param {string} value the property value
* @returns {KUTE.transformSVGObject} the property tween object
*/
function prepareSvgTransform(prop, value) {
return parseTransformSVG.call(this, prop, value);
} }
// returns an obect with current transform attribute value /**
function getStartSvgTransform(tweenProp, value) { * Returns an object with the current transform attribute value.
* @param {string} _ the property name
* @param {string} value the property value
* @returns {string} current transform object
*/
function getStartSvgTransform(/* tweenProp */_, value) {
const transformObject = {}; const transformObject = {};
const currentTransform = parseTransformString(this.element.getAttribute('transform')); const currentTransform = parseTransformString(this.element.getAttribute('transform'));

View file

@ -1,18 +1,14 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
/* svgTransform = {
property: 'svgTransform',
subProperties,
defaultValue,
Interpolate: {numbers},
functions
} */
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function svgTransformOnStart(tweenProp) { export function svgTransformOnStart(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
KUTE[tweenProp] = (l, a, b, v) => { KEC[tweenProp] = (l, a, b, v) => {
let x = 0; let x = 0;
let y = 0; let y = 0;
const deg = Math.PI / 180; const deg = Math.PI / 180;
@ -43,6 +39,7 @@ export function svgTransformOnStart(tweenProp) {
x += complex ? b.origin[0] : 0; y += complex ? b.origin[1] : 0; x += complex ? b.origin[0] : 0; y += complex ? b.origin[1] : 0;
// finally we apply the transform attribute value // finally we apply the transform attribute value
/* eslint no-bitwise: ["error", { "allow": [">>"] }] */
l.setAttribute('transform', (x || y ? (`translate(${(x * 1000 >> 0) / 1000}${y ? (`,${(y * 1000 >> 0) / 1000}`) : ''})`) : '') l.setAttribute('transform', (x || y ? (`translate(${(x * 1000 >> 0) / 1000}${y ? (`,${(y * 1000 >> 0) / 1000}`) : ''})`) : '')
+ (rotate ? `rotate(${(rotate * 1000 >> 0) / 1000})` : '') + (rotate ? `rotate(${(rotate * 1000 >> 0) / 1000})` : '')
+ (skewX ? `skewX(${(skewX * 1000 >> 0) / 1000})` : '') + (skewX ? `skewX(${(skewX * 1000 >> 0) / 1000})` : '')

View file

@ -1,15 +1,8 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getStyleForProperty from '../process/getStyleForProperty.js'; import getStyleForProperty from '../process/getStyleForProperty';
import trueDimension from '../util/trueDimension.js'; import trueDimension from '../util/trueDimension';
import units from '../interpolation/units.js'; import units from '../interpolation/units';
import { textPropOnStart } from './textPropertiesBase.js'; import { textPropOnStart } from './textPropertiesBase';
/* textProperties = {
category: 'textProperties',
defaultValues: [],
interpolators: {units}
functions = { prepareStart, prepareProperty, onStart }
} */
// Component Properties // Component Properties
const textProps = ['fontSize', 'lineHeight', 'letterSpacing', 'wordSpacing']; const textProps = ['fontSize', 'lineHeight', 'letterSpacing', 'wordSpacing'];
@ -20,11 +13,22 @@ textProps.forEach((tweenProp) => {
textOnStart[tweenProp] = textPropOnStart; textOnStart[tweenProp] = textPropOnStart;
}); });
/**
* Returns the current property computed style.
* @param {string} prop the property name
* @returns {string} computed style for property
*/
export function getTextProp(prop/* , value */) { export function getTextProp(prop/* , value */) {
return getStyleForProperty(this.element, prop) || defaultValues[prop]; return getStyleForProperty(this.element, prop) || defaultValues[prop];
} }
export function prepareTextProp(prop, value) { /**
* Returns the property tween object.
* @param {string} _ the property name
* @param {string} value the property value
* @returns {number} the property tween object
*/
export function prepareTextProp(/* prop */_, value) {
return trueDimension(value); return trueDimension(value);
} }
@ -36,7 +40,7 @@ const textPropFunctions = {
}; };
// Component Full // Component Full
const textProperties = { const TextProperties = {
component: 'textProperties', component: 'textProperties',
category: 'textProperties', category: 'textProperties',
properties: textProps, properties: textProps,
@ -48,4 +52,4 @@ const textProperties = {
Util: { trueDimension }, Util: { trueDimension },
}; };
export default textProperties; export default TextProperties;

View file

@ -1,20 +1,18 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import units from '../interpolation/units.js'; import units from '../interpolation/units';
/* textProperties = {
category: 'textProperties',
defaultValues: [],
interpolators: {units},
functions = { prepareStart, prepareProperty, onStart:{}
} */
// Component Properties // Component Properties
const textProperties = ['fontSize', 'lineHeight', 'letterSpacing', 'wordSpacing']; const textProperties = ['fontSize', 'lineHeight', 'letterSpacing', 'wordSpacing'];
const textOnStart = {}; const textOnStart = {};
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function textPropOnStart(tweenProp) { export function textPropOnStart(tweenProp) {
if (this.valuesEnd[tweenProp] && !KUTE[tweenProp]) { if (this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { 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); elem.style[tweenProp] = units(a.v, b.v, b.u, v);
}; };
} }
@ -25,7 +23,7 @@ textProperties.forEach((tweenProp) => {
}); });
// Component Base // Component Base
const baseTextProperties = { const TextPropertiesBase = {
component: 'baseTextProperties', component: 'baseTextProperties',
category: 'textProps', category: 'textProps',
// properties: textProperties, // properties: textProperties,
@ -34,4 +32,4 @@ const baseTextProperties = {
functions: { onStart: textOnStart }, functions: { onStart: textOnStart },
}; };
export default baseTextProperties; export default TextPropertiesBase;

View file

@ -1,7 +1,7 @@
import connect from '../objects/connect.js'; import connect from '../objects/connect';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import { onStartWrite, charSet } from './textWriteBase.js'; import { onStartWrite, charSet } from './textWriteBase';
// Component Util // Component Util
// utility for multi-child targets // utility for multi-child targets
@ -20,8 +20,10 @@ function wrapContentsSpan(el, classNAME) {
textWriteWrapper = document.createElement('SPAN'); textWriteWrapper = document.createElement('SPAN');
textWriteWrapper.className = classNAME; textWriteWrapper.className = classNAME;
textWriteWrapper.innerHTML = elementInnerHTML; textWriteWrapper.innerHTML = elementInnerHTML;
/* eslint-disable no-param-reassign -- impossible to satisfy */
el.appendChild(textWriteWrapper); el.appendChild(textWriteWrapper);
el.innerHTML = textWriteWrapper.outerHTML; el.innerHTML = textWriteWrapper.outerHTML;
/* eslint-enable no-param-reassign -- impossible to satisfy */
} else if (el.children.length && el.children[0].className === classNAME) { } else if (el.children.length && el.children[0].className === classNAME) {
[textWriteWrapper] = el.children; [textWriteWrapper] = el.children;
} }
@ -72,9 +74,11 @@ function setSegments(target, newText) {
const oldTargetSegs = getTextPartsArray(target, 'text-part'); const oldTargetSegs = getTextPartsArray(target, 'text-part');
const newTargetSegs = getTextPartsArray(wrapContentsSpan(newText), 'text-part'); const newTargetSegs = getTextPartsArray(wrapContentsSpan(newText), 'text-part');
/* eslint-disable no-param-reassign */
target.innerHTML = ''; target.innerHTML = '';
target.innerHTML += oldTargetSegs.map((s) => { s.className += ' oldText'; return s.outerHTML; }).join(''); target.innerHTML += oldTargetSegs.map((s) => { s.className += ' oldText'; return s.outerHTML; }).join('');
target.innerHTML += newTargetSegs.map((s) => { s.className += ' newText'; return s.outerHTML.replace(s.innerHTML, ''); }).join(''); target.innerHTML += newTargetSegs.map((s) => { s.className += ' newText'; return s.outerHTML.replace(s.innerHTML, ''); }).join('');
/* eslint-enable no-param-reassign */
return [oldTargetSegs, newTargetSegs]; return [oldTargetSegs, newTargetSegs];
} }
@ -113,8 +117,10 @@ export function createTextTweens(target, newText, ops) {
})); }));
textTween = textTween.concat(newTargets.map((el, i) => { textTween = textTween.concat(newTargets.map((el, i) => {
function onComplete() { function onComplete() {
/* eslint-disable no-param-reassign */
target.innerHTML = newText; target.innerHTML = newText;
target.playing = false; target.playing = false;
/* eslint-enable no-param-reassign */
} }
options.duration = options.duration === 'auto' ? newTargetSegs[i].innerHTML.length * 75 : options.duration; options.duration = options.duration === 'auto' ? newTargetSegs[i].innerHTML.length * 75 : options.duration;
@ -128,6 +134,7 @@ export function createTextTweens(target, newText, ops) {
textTween.start = function startTweens() { textTween.start = function startTweens() {
if (!target.playing) { if (!target.playing) {
textTween.forEach((tw) => tw.start()); textTween.forEach((tw) => tw.start());
// eslint-disable-next-line no-param-reassign
target.playing = true; target.playing = true;
} }
}; };
@ -136,10 +143,20 @@ export function createTextTweens(target, newText, ops) {
} }
// Component Functions // Component Functions
/**
* Returns the current element `innerHTML`.
* @returns {string} computed style for property
*/
function getWrite(/* tweenProp, value */) { function getWrite(/* tweenProp, value */) {
return this.element.innerHTML; return this.element.innerHTML;
} }
/**
* Returns the property tween object.
* @param {string} tweenProp the property name
* @param {string} value the property value
* @returns {number | string} the property tween object
*/
function prepareText(tweenProp, value) { function prepareText(tweenProp, value) {
if (tweenProp === 'number') { if (tweenProp === 'number') {
return parseFloat(value); return parseFloat(value);
@ -156,7 +173,7 @@ export const textWriteFunctions = {
}; };
// Full Component // Full Component
export const textWrite = { export const TextWrite = {
component: 'textWriteProperties', component: 'textWriteProperties',
category: 'textWrite', category: 'textWrite',
properties: ['text', 'number'], properties: ['text', 'number'],
@ -168,4 +185,4 @@ export const textWrite = {
Util: { charSet, createTextTweens }, Util: { charSet, createTextTweens },
}; };
export default textWrite; export default TextWrite;

View file

@ -1,6 +1,6 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import defaultOptions from '../objects/defaultOptions.js'; import defaultOptions from '../objects/defaultOptions';
// Component Values // Component Values
const lowerCaseAlpha = String('abcdefghijklmnopqrstuvwxyz').split(''); // lowercase const lowerCaseAlpha = String('abcdefghijklmnopqrstuvwxyz').split(''); // lowercase
@ -23,8 +23,14 @@ export { charSet };
// Component Functions // Component Functions
export const onStartWrite = { export const onStartWrite = {
/**
* onStartWrite.text
*
* Sets the property update function.
* @param {string} tweenProp the property name
*/
text(tweenProp) { text(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
const chars = this._textChars; const chars = this._textChars;
let charsets = charSet[defaultOptions.textChars]; let charsets = charSet[defaultOptions.textChars];
@ -34,12 +40,13 @@ export const onStartWrite = {
charsets = chars; charsets = chars;
} }
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
let initialText = ''; let initialText = '';
let endText = ''; let endText = '';
const finalText = b === '' ? ' ' : b; const finalText = b === '' ? ' ' : b;
const firstLetterA = a.substring(0); const firstLetterA = a.substring(0);
const firstLetterB = b.substring(0); const firstLetterB = b.substring(0);
/* eslint-disable */
const pointer = charsets[(Math.random() * charsets.length) >> 0]; const pointer = charsets[(Math.random() * charsets.length) >> 0];
if (a === ' ') { if (a === ' ') {
@ -58,20 +65,29 @@ export const onStartWrite = {
.substring(0, Math.min(v * firstLetterB.length, firstLetterB.length) >> 0); .substring(0, Math.min(v * firstLetterB.length, firstLetterB.length) >> 0);
elem.innerHTML = v < 1 ? ((endText + pointer + initialText)) : finalText; elem.innerHTML = v < 1 ? ((endText + pointer + initialText)) : finalText;
} }
/* eslint-enable */
}; };
} }
}, },
/**
* onStartWrite.number
*
* Sets the property update function.
* @param {string} tweenProp the property name
*/
number(tweenProp) { number(tweenProp) {
if (tweenProp in this.valuesEnd && !KUTE[tweenProp]) { // numbers can be 0 if (tweenProp in this.valuesEnd && !KEC[tweenProp]) { // numbers can be 0
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
/* eslint-disable */
elem.innerHTML = numbers(a, b, v) >> 0; elem.innerHTML = numbers(a, b, v) >> 0;
/* eslint-enable */
}; };
} }
}, },
}; };
// Base Component // Base Component
export const baseTextWrite = { export const TextWriteBase = {
component: 'baseTextWrite', component: 'baseTextWrite',
category: 'textWrite', category: 'textWrite',
// properties: ['text','number'], // properties: ['text','number'],
@ -83,4 +99,4 @@ export const baseTextWrite = {
Util: { charSet }, Util: { charSet },
}; };
export default baseTextWrite; export default TextWriteBase;

View file

@ -1,31 +1,35 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getInlineStyle from '../process/getInlineStyle.js'; import getInlineStyle from '../process/getInlineStyle';
import perspective from '../interpolation/perspective.js'; import perspective from '../interpolation/perspective';
import translate3d from '../interpolation/translate3d.js'; import translate3d from '../interpolation/translate3d';
import rotate3d from '../interpolation/rotate3d.js'; import rotate3d from '../interpolation/rotate3d';
import translate from '../interpolation/translate.js'; import translate from '../interpolation/translate';
import rotate from '../interpolation/rotate.js'; import rotate from '../interpolation/rotate';
import scale from '../interpolation/scale.js'; import scale from '../interpolation/scale';
import skew from '../interpolation/skew.js'; import skew from '../interpolation/skew';
import { onStartTransform } from './transformFunctionsBase.js'; import { onStartTransform } from './transformFunctionsBase';
/* transformFunctions = {
property: 'transform',
subProperties,
defaultValues,
Interpolate: {translate,rotate,skew,scale},
functions } */
// same to svg transform, attr // same to svg transform, attr
// the component developed for modern browsers supporting non-prefixed transform // the component developed for modern browsers supporting non-prefixed transform
// Component Functions // Component Functions
function getTransform(tweenProperty/* , value */) { /**
* Returns the current property inline style.
* @param {string} tweenProp the property name
* @returns {string} inline style for property
*/
function getTransform(tweenProp/* , value */) {
const currentStyle = getInlineStyle(this.element); const currentStyle = getInlineStyle(this.element);
return currentStyle[tweenProperty] ? currentStyle[tweenProperty] : defaultValues[tweenProperty]; return currentStyle[tweenProp] ? currentStyle[tweenProp] : defaultValues[tweenProp];
} }
function prepareTransform(prop, obj) { /**
* Returns the property tween object.
* @param {string} _ the property name
* @param {Object<string, string | number | (string | number)[]>} obj the property value
* @returns {KUTE.transformFObject} the property tween object
*/
function prepareTransform(/* prop, */_, obj) {
const prepAxis = ['X', 'Y', 'Z']; // coordinates const prepAxis = ['X', 'Y', 'Z']; // coordinates
const transformObject = {}; const transformObject = {};
const translateArray = []; const rotateArray = []; const skewArray = []; const translateArray = []; const rotateArray = []; const skewArray = [];
@ -79,6 +83,10 @@ function prepareTransform(prop, obj) {
return transformObject; return transformObject;
} }
/**
* Prepare tween object in advance for `to()` method.
* @param {string} tweenProp the property name
*/
function crossCheckTransform(tweenProp) { function crossCheckTransform(tweenProp) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
@ -124,7 +132,7 @@ const defaultTransformValues = {
}; };
// Full Component // Full Component
const transformFunctionsComponent = { const TransformFunctions = {
component: 'transformFunctions', component: 'transformFunctions',
property: 'transform', property: 'transform',
subProperties: supportedTransformProperties, subProperties: supportedTransformProperties,
@ -141,4 +149,4 @@ const transformFunctionsComponent = {
}, },
}; };
export default transformFunctionsComponent; export default TransformFunctions;

View file

@ -1,25 +1,22 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import perspective from '../interpolation/perspective.js'; import perspective from '../interpolation/perspective';
import translate3d from '../interpolation/translate3d.js'; import translate3d from '../interpolation/translate3d';
import rotate3d from '../interpolation/rotate3d.js'; import rotate3d from '../interpolation/rotate3d';
import translate from '../interpolation/translate.js'; import translate from '../interpolation/translate';
import rotate from '../interpolation/rotate.js'; import rotate from '../interpolation/rotate';
import scale from '../interpolation/scale.js'; import scale from '../interpolation/scale';
import skew from '../interpolation/skew.js'; import skew from '../interpolation/skew';
/* transformFunctions = {
property: 'transform',
subProperties,
defaultValues,
Interpolate: {translate,rotate,skew,scale},
functions } */
// same to svg transform, attr
// Component Functions // Component Functions
/**
* Sets the property update function.
* * same to svgTransform, htmlAttributes
* @param {string} tweenProp the property name
*/
export function onStartTransform(tweenProp) { export function onStartTransform(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
// eslint-disable-next-line no-param-reassign
elem.style[tweenProp] = (a.perspective || b.perspective ? perspective(a.perspective, b.perspective, 'px', v) : '') // one side might be 0 elem.style[tweenProp] = (a.perspective || b.perspective ? perspective(a.perspective, b.perspective, 'px', v) : '') // one side might be 0
+ (a.translate3d ? translate3d(a.translate3d, b.translate3d, 'px', v) : '') // array [x,y,z] + (a.translate3d ? translate3d(a.translate3d, b.translate3d, 'px', v) : '') // array [x,y,z]
+ (a.rotate3d ? rotate3d(a.rotate3d, b.rotate3d, 'deg', v) : '') // array [x,y,z] + (a.rotate3d ? rotate3d(a.rotate3d, b.rotate3d, 'deg', v) : '') // array [x,y,z]
@ -30,7 +27,7 @@ export function onStartTransform(tweenProp) {
} }
// Base Component // Base Component
const BaseTransform = { const TransformFunctionsBase = {
component: 'baseTransform', component: 'baseTransform',
property: 'transform', property: 'transform',
functions: { onStart: onStartTransform }, functions: { onStart: onStartTransform },
@ -45,4 +42,4 @@ const BaseTransform = {
}, },
}; };
export default BaseTransform; export default TransformFunctionsBase;

View file

@ -1,35 +1,40 @@
import support3DTransform from 'shorter-js/src/boolean/support3DTransform.js'; import support3DTransform from 'shorter-js/src/boolean/support3DTransform';
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import getInlineStyleLegacy from '../process/getInlineStyleLegacy.js'; import getInlineStyleLegacy from '../process/getInlineStyleLegacy';
import perspective from '../interpolation/perspective.js'; import perspective from '../interpolation/perspective';
import translate3d from '../interpolation/translate3d.js'; import translate3d from '../interpolation/translate3d';
import rotate3d from '../interpolation/rotate3d.js'; import rotate3d from '../interpolation/rotate3d';
import translate from '../interpolation/translate.js'; import translate from '../interpolation/translate';
import rotate from '../interpolation/rotate.js'; import rotate from '../interpolation/rotate';
import scale from '../interpolation/scale.js'; import scale from '../interpolation/scale';
import skew from '../interpolation/skew.js'; import skew from '../interpolation/skew';
import { onStartLegacyTransform } from './transformLegacyBase.js'; import { onStartLegacyTransform } from './transformLegacyBase';
import transformProperty from '../util/transformProperty.js'; import transformProperty from '../util/transformProperty';
import supportTransform from '../util/supportLegacyTransform.js'; import supportTransform from '../util/supportLegacyTransform';
/* transformFunctions = {
property : 'transform',
subProperties,
defaultValues,
Interpolate: {translate,rotate,skew,scale},
functions } */
// same to svg transform, attr // same to svg transform, attr
// the component to handle all kinds of input values and process according to browser supported API, // the component to handle all kinds of input values and process according to browser supported API,
// the component that handles all browsers IE9+ // the component that handles all browsers IE9+
// Component Functions // Component Functions
/**
* Returns the current property inline style.
* @param {string} tweenProperty the property name
* @returns {string} inline style for property
*/
function getLegacyTransform(tweenProperty/* , value */) { function getLegacyTransform(tweenProperty/* , value */) {
const currentStyle = getInlineStyleLegacy(this.element); const currentStyle = getInlineStyleLegacy(this.element);
return currentStyle[tweenProperty] ? currentStyle[tweenProperty] : defaultValues[tweenProperty]; return currentStyle[tweenProperty] ? currentStyle[tweenProperty] : defaultValues[tweenProperty];
} }
function prepareLegacyTransform(prop, obj) {
/**
* Returns the property tween object.
* @param {string} _ the property name
* @param {Object<string, string | number | (string | number)[]>} obj the property value
* @returns {KUTE.transformFObject} the property tween object
*/
function prepareLegacyTransform(/* prop */_, obj) {
const prepAxis = ['X', 'Y', 'Z']; // coordinates const prepAxis = ['X', 'Y', 'Z']; // coordinates
const translateArray = []; const rotateArray = []; const skewArray = []; const translateArray = []; const rotateArray = []; const skewArray = [];
const transformObject = {}; const transformObject = {};
@ -97,6 +102,10 @@ function prepareLegacyTransform(prop, obj) {
return transformObject; return transformObject;
} }
/**
* Prepare tween object in advance for `to()` method.
* @param {string} tweenProp the property name
*/
function crossCheckLegacyTransform(tweenProp) { function crossCheckLegacyTransform(tweenProp) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
if (this.valuesEnd[tweenProp] && support3DTransform) { if (this.valuesEnd[tweenProp] && support3DTransform) {

View file

@ -1,31 +1,29 @@
import support3DTransform from 'shorter-js/src/boolean/support3DTransform.js'; import support3DTransform from 'shorter-js/src/boolean/support3DTransform';
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import perspective from '../interpolation/perspective.js'; import perspective from '../interpolation/perspective';
import translate3d from '../interpolation/translate3d.js'; import translate3d from '../interpolation/translate3d';
import rotate3d from '../interpolation/rotate3d.js'; import rotate3d from '../interpolation/rotate3d';
import translate from '../interpolation/translate.js'; import translate from '../interpolation/translate';
import rotate from '../interpolation/rotate.js'; import rotate from '../interpolation/rotate';
import scale from '../interpolation/scale.js'; import scale from '../interpolation/scale';
import skew from '../interpolation/skew.js'; import skew from '../interpolation/skew';
import supportTransform from '../util/supportLegacyTransform.js'; import supportTransform from '../util/supportLegacyTransform';
import transformProperty from '../util/transformProperty.js'; import transformProperty from '../util/transformProperty';
/* baseLegacyTransform = { // same as svgTransform, htmlAttributes
property: 'transform',
subProperties,
defaultValues,
Interpolate: {translate,rotate,skew,scale},
functions } */
// same to svg transform, attr
// the component that handles all browsers IE9+ // the component that handles all browsers IE9+
// Component Functions // Component Functions
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
export function onStartLegacyTransform(tweenProp) { export function onStartLegacyTransform(tweenProp) {
if (!KUTE[tweenProp] && this.valuesEnd[tweenProp]) { if (!KEC[tweenProp] && this.valuesEnd[tweenProp]) {
if (support3DTransform) { if (support3DTransform) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
// eslint-disable-next-line no-param-reassign
elem.style[transformProperty] = (a.perspective || b.perspective ? perspective(a.perspective, b.perspective, 'px', v) : '') // one side might be 0 elem.style[transformProperty] = (a.perspective || b.perspective ? perspective(a.perspective, b.perspective, 'px', v) : '') // one side might be 0
+ (a.translate3d ? translate3d(a.translate3d, b.translate3d, 'px', v) : '') // array [x,y,z] + (a.translate3d ? translate3d(a.translate3d, b.translate3d, 'px', v) : '') // array [x,y,z]
+ (a.rotate3d ? rotate3d(a.rotate3d, b.rotate3d, 'deg', v) : '') // array [x,y,z] + (a.rotate3d ? rotate3d(a.rotate3d, b.rotate3d, 'deg', v) : '') // array [x,y,z]
@ -33,7 +31,8 @@ export function onStartLegacyTransform(tweenProp) {
+ (a.scale || b.scale ? scale(a.scale, b.scale, v) : ''); // one side might be 0 + (a.scale || b.scale ? scale(a.scale, b.scale, v) : ''); // one side might be 0
}; };
} else if (supportTransform) { } else if (supportTransform) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
// eslint-disable-next-line no-param-reassign
elem.style[transformProperty] = (a.translate ? translate(a.translate, b.translate, 'px', v) : '') // array [x,y] elem.style[transformProperty] = (a.translate ? translate(a.translate, b.translate, 'px', v) : '') // array [x,y]
+ ((a.rotate || b.rotate) ? rotate(a.rotate, b.rotate, 'deg', v) : '') // one side might be 0 + ((a.rotate || b.rotate) ? rotate(a.rotate, b.rotate, 'deg', v) : '') // one side might be 0
+ (a.skew ? skew(a.skew, b.skew, 'deg', v) : '') // array [x,y] + (a.skew ? skew(a.skew, b.skew, 'deg', v) : '') // array [x,y]

View file

@ -1,20 +1,19 @@
import defaultValues from '../objects/defaultValues.js'; import defaultValues from '../objects/defaultValues';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import arrays from '../interpolation/arrays.js'; import arrays from '../interpolation/arrays';
import { onStartTransform } from './transformMatrixBase.js'; import { onStartTransform } from './transformMatrixBase';
/* transformMatrix = {
property : 'transform',
defaultValue: {},
interpolators: {}
functions = { prepareStart, prepareProperty, onStart, crossCheck }
} */
// Component name // Component name
const matrixComponent = 'transformMatrix'; const matrixComponent = 'transformMatrix';
// Component Functions // Component Functions
function getTransform(tweenProp, value) { /**
* Returns the current transform object.
* @param {string} _ the property name
* @param {string} value the property value
* @returns {KUTE.transformMObject} transform object
*/
function getTransform(/* tweenProp, */_, value) {
const transformObject = {}; const transformObject = {};
const currentValue = this.element[matrixComponent]; const currentValue = this.element[matrixComponent];
@ -30,7 +29,13 @@ function getTransform(tweenProp, value) {
return transformObject; return transformObject;
} }
function prepareTransform(tweenProp, value) { /**
* Returns the property tween object.
* @param {string} _ the property name
* @param {Object<string, string | number | (string | number)[]>} obj the property value
* @returns {KUTE.transformMObject} the property tween object
*/
function prepareTransform(/* tweenProp, */_, value) {
if (typeof (value) === 'object' && !value.length) { if (typeof (value) === 'object' && !value.length) {
let pv; let pv;
const transformObject = {}; const transformObject = {};
@ -89,14 +94,20 @@ function prepareTransform(tweenProp, value) {
throw Error(`KUTE.js - "${value}" is not valid/supported transform function`); throw Error(`KUTE.js - "${value}" is not valid/supported transform function`);
} }
/**
* Sets the end values for the next `to()` method call.
* @param {string} tweenProp the property name
*/
function onCompleteTransform(tweenProp) { function onCompleteTransform(tweenProp) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
this.element[matrixComponent] = {}; this.element[matrixComponent] = { ...this.valuesEnd[tweenProp] };
Object.keys(this.valuesEnd[tweenProp]).forEach((tf) => {
this.element[matrixComponent][tf] = this.valuesEnd[tweenProp][tf];
});
} }
} }
/**
* Prepare tween object in advance for `to()` method.
* @param {string} tweenProp the property name
*/
function crossCheckTransform(tweenProp) { function crossCheckTransform(tweenProp) {
if (this.valuesEnd[tweenProp]) { if (this.valuesEnd[tweenProp]) {
if (this.valuesEnd[tweenProp].perspective && !this.valuesStart[tweenProp].perspective) { if (this.valuesEnd[tweenProp].perspective && !this.valuesStart[tweenProp].perspective) {

View file

@ -1,13 +1,6 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import numbers from '../interpolation/numbers.js'; import numbers from '../interpolation/numbers';
import arrays from '../interpolation/arrays.js'; import arrays from '../interpolation/arrays';
/* transformMatrix = {
property : 'transform',
defaultValue: {},
interpolators: {},
functions = { prepareStart, prepareProperty, onStart, crossCheck }
} */
// Component name // Component name
const matrixComponent = 'transformMatrixBase'; const matrixComponent = 'transformMatrixBase';
@ -18,9 +11,13 @@ const CSS3Matrix = typeof (DOMMatrix) !== 'undefined' ? DOMMatrix : null;
// Component Functions // Component Functions
export const onStartTransform = { export const onStartTransform = {
/**
* Sets the property update function.
* @param {string} tweenProp the property name
*/
transform(tweenProp) { transform(tweenProp) {
if (CSS3Matrix && this.valuesEnd[tweenProp] && !KUTE[tweenProp]) { if (CSS3Matrix && this.valuesEnd[tweenProp] && !KEC[tweenProp]) {
KUTE[tweenProp] = (elem, a, b, v) => { KEC[tweenProp] = (elem, a, b, v) => {
let matrix = new CSS3Matrix(); let matrix = new CSS3Matrix();
const tObject = {}; const tObject = {};
@ -53,19 +50,26 @@ export const onStartTransform = {
: matrix; : matrix;
// set element style // set element style
// eslint-disable-next-line no-param-reassign
elem.style[tweenProp] = matrix.toString(); elem.style[tweenProp] = matrix.toString();
}; };
} }
}, },
/**
* onStartTransform.CSS3Matrix
*
* Sets the update function for the property.
* @param {string} prop the property name
*/
CSS3Matrix(prop) { CSS3Matrix(prop) {
if (CSS3Matrix && this.valuesEnd.transform) { if (CSS3Matrix && this.valuesEnd.transform) {
if (!KUTE[prop]) KUTE[prop] = CSS3Matrix; if (!KEC[prop]) KEC[prop] = CSS3Matrix;
} }
}, },
}; };
// Component Base Object // Component Base Object
export const baseMatrixTransform = { export const TransformMatrixBase = {
component: matrixComponent, component: matrixComponent,
property: 'transform', property: 'transform',
functions: { onStart: onStartTransform }, functions: { onStart: onStartTransform },
@ -78,4 +82,4 @@ export const baseMatrixTransform = {
}, },
}; };
export default baseMatrixTransform; export default TransformMatrixBase;

View file

@ -1,3 +1,10 @@
import Tweens from '../objects/tweens.js'; import Tweens from '../objects/tweens';
export default (tw) => Tweens.push(tw); /**
* KUTE.add(Tween)
*
* @param {KUTE.Tween} tw a new tween to add
*/
const add = (tw) => Tweens.push(tw);
export default add;

View file

@ -1,3 +1,10 @@
import Tweens from '../objects/tweens.js'; import Tweens from '../objects/tweens';
export default () => Tweens; /**
* KUTE.add(Tween)
*
* @return {KUTE.Tween[]} tw a new tween to add
*/
const getAll = () => Tweens;
export default getAll;

View file

@ -1,11 +1,11 @@
import add from './add.js'; import add from './add';
import remove from './remove.js'; import remove from './remove';
import getAll from './getAll.js'; import getAll from './getAll';
import removeAll from './removeAll.js'; import removeAll from './removeAll';
import { stop } from './render.js'; import { stop } from './render';
import linkInterpolation from './linkInterpolation.js'; import linkInterpolation from './linkInterpolation';
export default { const internals = {
add, add,
remove, remove,
getAll, getAll,
@ -13,3 +13,5 @@ export default {
stop, stop,
linkInterpolation, linkInterpolation,
}; };
export default internals;

View file

@ -1,7 +1,11 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import linkProperty from '../objects/linkProperty.js'; import linkProperty from '../objects/linkProperty';
import supportedProperties from '../objects/supportedProperties.js'; import supportedProperties from '../objects/supportedProperties';
/**
* linkInterpolation
* @this {KUTE.Tween}
*/
export default function linkInterpolation() { // DON'T change export default function linkInterpolation() { // DON'T change
Object.keys(linkProperty).forEach((component) => { Object.keys(linkProperty).forEach((component) => {
const componentLink = linkProperty[component]; const componentLink = linkProperty[component];
@ -11,18 +15,18 @@ export default function linkInterpolation() { // DON'T change
if (typeof (componentLink[fnObj]) === 'function' // ATTR, colors, scroll, boxModel, borderRadius if (typeof (componentLink[fnObj]) === 'function' // ATTR, colors, scroll, boxModel, borderRadius
&& Object.keys(this.valuesEnd).some((i) => (componentProps && componentProps.includes(i)) && Object.keys(this.valuesEnd).some((i) => (componentProps && componentProps.includes(i))
|| (i === 'attr' && Object.keys(this.valuesEnd[i]).some((j) => componentProps && componentProps.includes(j))))) { || (i === 'attr' && Object.keys(this.valuesEnd[i]).some((j) => componentProps && componentProps.includes(j))))) {
if (!KUTE[fnObj]) KUTE[fnObj] = componentLink[fnObj]; if (!KEC[fnObj]) KEC[fnObj] = componentLink[fnObj];
} else { } else {
Object.keys(this.valuesEnd).forEach((prop) => { Object.keys(this.valuesEnd).forEach((prop) => {
const propObject = this.valuesEnd[prop]; const propObject = this.valuesEnd[prop];
if (propObject instanceof Object) { if (propObject instanceof Object) {
Object.keys(propObject).forEach((i) => { Object.keys(propObject).forEach((i) => {
if (typeof (componentLink[i]) === 'function') { // transformCSS3 if (typeof (componentLink[i]) === 'function') { // transformCSS3
if (!KUTE[i]) KUTE[i] = componentLink[i]; if (!KEC[i]) KEC[i] = componentLink[i];
} else { } else {
Object.keys(componentLink[fnObj]).forEach((j) => { Object.keys(componentLink[fnObj]).forEach((j) => {
if (componentLink[i] && typeof (componentLink[i][j]) === 'function') { // transformMatrix if (componentLink[i] && typeof (componentLink[i][j]) === 'function') { // transformMatrix
if (!KUTE[j]) KUTE[j] = componentLink[i][j]; if (!KEC[j]) KEC[j] = componentLink[i][j];
} }
}); });
} }

View file

@ -1,5 +1,5 @@
import onStart from '../objects/onStart.js'; import onStart from '../objects/onStart';
import linkInterpolation from './linkInterpolation.js'; import linkInterpolation from './linkInterpolation';
export default function queueStart() { export default function queueStart() {
// fire onStart actions // fire onStart actions

View file

@ -1,6 +1,13 @@
import Tweens from '../objects/tweens.js'; import Tweens from '../objects/tweens';
export default (tw) => { /**
* KUTE.remove(Tween)
*
* @param {KUTE.Tween} tw a new tween to add
*/
const remove = (tw) => {
const i = Tweens.indexOf(tw); const i = Tweens.indexOf(tw);
if (i !== -1) Tweens.splice(i, 1); if (i !== -1) Tweens.splice(i, 1);
}; };
export default remove;

View file

@ -1,3 +1,8 @@
import Tweens from '../objects/tweens.js'; import Tweens from '../objects/tweens';
export default () => { Tweens.length = 0; }; /**
* KUTE.removeAll()
*/
const removeAll = () => { Tweens.length = 0; };
export default removeAll;

View file

@ -1,18 +1,21 @@
import KUTE from '../objects/kute.js'; import KEC from '../objects/kute';
import Tweens from '../objects/tweens.js'; import Tweens from '../objects/tweens';
import globalObject from '../objects/globalObject.js'; import globalObject from '../objects/globalObject';
import Interpolate from '../objects/interpolate.js'; import Interpolate from '../objects/interpolate';
import onStart from '../objects/onStart.js'; import onStart from '../objects/onStart';
import now from '../util/now.js'; import now from '../util/now';
const Time = {}; const Time = {};
Time.now = now; Time.now = now;
// const that = window.self || window || {};
// Time.now = that.performance.now.bind(that.performance);
// eslint-disable-next-line import/no-mutable-exports -- impossible to satisfy
let Tick = 0; let Tick = 0;
export { Tick }; export { Tick };
/**
*
* @param {number | Date} time
*/
const Ticker = (time) => { const Ticker = (time) => {
let i = 0; let i = 0;
while (i < Tweens.length) { while (i < Tweens.length) {
@ -34,31 +37,31 @@ export function stop() {
Tick = null; Tick = null;
Object.keys(onStart).forEach((obj) => { Object.keys(onStart).forEach((obj) => {
if (typeof (onStart[obj]) === 'function') { if (typeof (onStart[obj]) === 'function') {
if (KUTE[obj]) delete KUTE[obj]; if (KEC[obj]) delete KEC[obj];
} else { } else {
Object.keys(onStart[obj]).forEach((prop) => { Object.keys(onStart[obj]).forEach((prop) => {
if (KUTE[prop]) delete KUTE[prop]; if (KEC[prop]) delete KEC[prop];
}); });
} }
}); });
Object.keys(Interpolate).forEach((i) => { Object.keys(Interpolate).forEach((i) => {
if (KUTE[i]) delete KUTE[i]; if (KEC[i]) delete KEC[i];
}); });
} }
}, 64); }, 64);
} }
// KUTE.js render update functions // render update functions
// =============================== // =======================
const Render = { const Render = {
Tick, Ticker, Tweens, Time, Tick, Ticker, Tweens, Time,
}; };
Object.keys(Render).forEach((blob) => { Object.keys(Render).forEach((blob) => {
if (!KUTE[blob]) { if (!KEC[blob]) {
KUTE[blob] = blob === 'Time' ? Time.now : Render[blob]; KEC[blob] = blob === 'Time' ? Time.now : Render[blob];
} }
}); });
globalObject._KUTE = KUTE; globalObject._KUTE = KEC;
export default Render; export default Render;

View file

@ -1,28 +1,41 @@
import connect from '../objects/connect.js'; import connect from '../objects/connect';
// Select Robert Penner's Easing Functions // Select Robert Penner's Easing Functions
// updated for ESLint // updated for ESLint
const Easing = { const Easing = {
/** @type {KUTE.easingFunction} */
linear: (t) => t, linear: (t) => t,
/** @type {KUTE.easingFunction} */
easingQuadraticIn: (t) => t * t, easingQuadraticIn: (t) => t * t,
/** @type {KUTE.easingFunction} */
easingQuadraticOut: (t) => t * (2 - t), easingQuadraticOut: (t) => t * (2 - t),
/** @type {KUTE.easingFunction} */
easingQuadraticInOut: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t), easingQuadraticInOut: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
/** @type {KUTE.easingFunction} */
easingCubicIn: (t) => t * t * t, easingCubicIn: (t) => t * t * t,
/** @type {KUTE.easingFunction} */
easingCubicOut: (t0) => { const t = t0 - 1; return t * t * t + 1; }, easingCubicOut: (t0) => { const t = t0 - 1; return t * t * t + 1; },
/** @type {KUTE.easingFunction} */
easingCubicInOut: (t) => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1), easingCubicInOut: (t) => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1),
/** @type {KUTE.easingFunction} */
easingCircularIn: (t) => -(Math.sqrt(1 - (t * t)) - 1), easingCircularIn: (t) => -(Math.sqrt(1 - (t * t)) - 1),
/** @type {KUTE.easingFunction} */
easingCircularOut: (t0) => { const t = t0 - 1; return Math.sqrt(1 - t * t); }, easingCircularOut: (t0) => { const t = t0 - 1; return Math.sqrt(1 - t * t); },
/** @type {KUTE.easingFunction} */
easingCircularInOut: (t0) => { easingCircularInOut: (t0) => {
let t = t0 * 2; let t = t0 * 2;
if (t < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1); if (t < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1);
t -= 2; return 0.5 * (Math.sqrt(1 - t * t) + 1); t -= 2; return 0.5 * (Math.sqrt(1 - t * t) + 1);
}, },
/** @type {KUTE.easingFunction} */
easingBackIn: (t) => { const s = 1.70158; return t * t * ((s + 1) * t - s); }, easingBackIn: (t) => { const s = 1.70158; return t * t * ((s + 1) * t - s); },
/** @type {KUTE.easingFunction} */
easingBackOut: (t0) => { easingBackOut: (t0) => {
const s = 1.70158; const s = 1.70158;
const t = t0 - 1; const t = t0 - 1;
return t * t * ((s + 1) * t + s) + 1; return t * t * ((s + 1) * t + s) + 1;
}, },
/** @type {KUTE.easingFunction} */
easingBackInOut: (t0) => { easingBackInOut: (t0) => {
const s = 1.70158 * 1.525; const s = 1.70158 * 1.525;
let t = t0 * 2; let t = t0 * 2;
@ -31,6 +44,12 @@ const Easing = {
}, },
}; };
/**
* Returns a valid `easingFunction`.
*
* @param {KUTE.easingFunction | string} fn function name or constructor name
* @returns {KUTE.easingFunction} a valid easing function
*/
function processEasing(fn) { function processEasing(fn) {
if (typeof fn === 'function') { if (typeof fn === 'function') {
return fn; return fn;

View file

@ -1,5 +1,5 @@
import CubicBezier from 'cubic-bezier-easing'; import CubicBezier from 'cubic-bezier-easing';
import connect from '../objects/connect.js'; import connect from '../objects/connect';
const Easing = { const Easing = {
linear: new CubicBezier(0, 0, 1, 1, 'linear'), linear: new CubicBezier(0, 0, 1, 1, 'linear'),
@ -36,6 +36,12 @@ const Easing = {
easingBackInOut: new CubicBezier(0.68, -0.55, 0.265, 1.55, 'easingBackInOut'), easingBackInOut: new CubicBezier(0.68, -0.55, 0.265, 1.55, 'easingBackInOut'),
}; };
/**
* Returns a valid `easingFunction`.
*
* @param {KUTE.easingFunction | string} fn function name or constructor name
* @returns {KUTE.easingFunction} a valid easingfunction
*/
function processBezierEasing(fn) { function processBezierEasing(fn) {
if (typeof fn === 'function') { if (typeof fn === 'function') {
return fn; return fn;
@ -46,7 +52,7 @@ function processBezierEasing(fn) {
return new CubicBezier(bz[0] * 1, bz[1] * 1, bz[2] * 1, bz[3] * 1); // bezier easing return new CubicBezier(bz[0] * 1, bz[1] * 1, bz[2] * 1, bz[3] * 1); // bezier easing
} }
// if (/elastic|bounce/i.test(fn)) { // if (/elastic|bounce/i.test(fn)) {
// throw TypeError(`KUTE.js - CubicBezier doesn't support ${fn} easing.`); // throw TypeError(`KUTE - CubicBezier doesn't support ${fn} easing.`);
// } // }
return Easing.linear; return Easing.linear;
} }

View file

@ -1,58 +1,84 @@
import connect from '../objects/connect.js'; import connect from '../objects/connect';
// Robert Penner's Easing Functions // Robert Penner's Easing Functions
// updated for ESLint // updated for ESLint
const Easing = { const Easing = {
/** @type {KUTE.easingFunction} */
linear: (t) => t, linear: (t) => t,
/** @type {KUTE.easingFunction} */
easingSinusoidalIn: (t) => -Math.cos((t * Math.PI) / 2) + 1, easingSinusoidalIn: (t) => -Math.cos((t * Math.PI) / 2) + 1,
/** @type {KUTE.easingFunction} */
easingSinusoidalOut: (t) => Math.sin((t * Math.PI) / 2), easingSinusoidalOut: (t) => Math.sin((t * Math.PI) / 2),
/** @type {KUTE.easingFunction} */
easingSinusoidalInOut: (t) => -0.5 * (Math.cos(Math.PI * t) - 1), easingSinusoidalInOut: (t) => -0.5 * (Math.cos(Math.PI * t) - 1),
/** @type {KUTE.easingFunction} */
easingQuadraticIn: (t) => t * t, easingQuadraticIn: (t) => t * t,
/** @type {KUTE.easingFunction} */
easingQuadraticOut: (t) => t * (2 - t), easingQuadraticOut: (t) => t * (2 - t),
/** @type {KUTE.easingFunction} */
easingQuadraticInOut: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t), easingQuadraticInOut: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
/** @type {KUTE.easingFunction} */
easingCubicIn: (t) => t * t * t, easingCubicIn: (t) => t * t * t,
/** @type {KUTE.easingFunction} */
easingCubicOut: (t0) => { const t = t0 - 1; return t * t * t + 1; }, easingCubicOut: (t0) => { const t = t0 - 1; return t * t * t + 1; },
/** @type {KUTE.easingFunction} */
easingCubicInOut: (t) => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1), easingCubicInOut: (t) => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1),
/** @type {KUTE.easingFunction} */
easingQuarticIn: (t) => t * t * t * t, easingQuarticIn: (t) => t * t * t * t,
/** @type {KUTE.easingFunction} */
easingQuarticOut: (t0) => { const t = t0 - 1; return 1 - t * t * t * t; }, easingQuarticOut: (t0) => { const t = t0 - 1; return 1 - t * t * t * t; },
/** @type {KUTE.easingFunction} */
easingQuarticInOut: (t0) => { easingQuarticInOut: (t0) => {
let t = t0; let t = t0;
if (t < 0.5) return 8 * t * t * t * t; if (t < 0.5) return 8 * t * t * t * t;
t -= 1; return 1 - 8 * t * t * t * t; t -= 1; return 1 - 8 * t * t * t * t;
}, },
/** @type {KUTE.easingFunction} */
easingQuinticIn: (t) => t * t * t * t * t, easingQuinticIn: (t) => t * t * t * t * t,
/** @type {KUTE.easingFunction} */
easingQuinticOut: (t0) => { const t = t0 - 1; return 1 + t * t * t * t * t; }, easingQuinticOut: (t0) => { const t = t0 - 1; return 1 + t * t * t * t * t; },
/** @type {KUTE.easingFunction} */
easingQuinticInOut: (t0) => { easingQuinticInOut: (t0) => {
let t = t0; let t = t0;
if (t < 0.5) return 16 * t * t * t * t * t; if (t < 0.5) return 16 * t * t * t * t * t;
t -= 1; return 1 + 16 * t * t * t * t * t; t -= 1; return 1 + 16 * t * t * t * t * t;
}, },
/** @type {KUTE.easingFunction} */
easingCircularIn: (t) => -(Math.sqrt(1 - (t * t)) - 1), easingCircularIn: (t) => -(Math.sqrt(1 - (t * t)) - 1),
/** @type {KUTE.easingFunction} */
easingCircularOut: (t0) => { const t = t0 - 1; return Math.sqrt(1 - t * t); }, easingCircularOut: (t0) => { const t = t0 - 1; return Math.sqrt(1 - t * t); },
/** @type {KUTE.easingFunction} */
easingCircularInOut: (t0) => { easingCircularInOut: (t0) => {
let t = t0 * 2; let t = t0 * 2;
if (t < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1); if (t < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1);
t -= 2; return 0.5 * (Math.sqrt(1 - t * t) + 1); t -= 2; return 0.5 * (Math.sqrt(1 - t * t) + 1);
}, },
/** @type {KUTE.easingFunction} */
easingExponentialIn: (t) => 2 ** (10 * (t - 1)) - 0.001, easingExponentialIn: (t) => 2 ** (10 * (t - 1)) - 0.001,
/** @type {KUTE.easingFunction} */
easingExponentialOut: (t) => 1 - 2 ** (-10 * t), easingExponentialOut: (t) => 1 - 2 ** (-10 * t),
/** @type {KUTE.easingFunction} */
easingExponentialInOut: (t0) => { easingExponentialInOut: (t0) => {
const t = t0 * 2; const t = t0 * 2;
if (t < 1) return 0.5 * (2 ** (10 * (t - 1))); if (t < 1) return 0.5 * (2 ** (10 * (t - 1)));
return 0.5 * (2 - 2 ** (-10 * (t - 1))); return 0.5 * (2 - 2 ** (-10 * (t - 1)));
}, },
/** @type {KUTE.easingFunction} */
easingBackIn: (t) => { const s = 1.70158; return t * t * ((s + 1) * t - s); }, easingBackIn: (t) => { const s = 1.70158; return t * t * ((s + 1) * t - s); },
/** @type {KUTE.easingFunction} */
easingBackOut: (t0) => { easingBackOut: (t0) => {
const s = 1.70158; const s = 1.70158;
const t = t0 - 1; const t = t0 - 1;
return t * t * ((s + 1) * t + s) + 1; return t * t * ((s + 1) * t + s) + 1;
}, },
/** @type {KUTE.easingFunction} */
easingBackInOut: (t0) => { easingBackInOut: (t0) => {
const s = 1.70158 * 1.525; const s = 1.70158 * 1.525;
let t = t0 * 2; let t = t0 * 2;
if (t < 1) return 0.5 * (t * t * ((s + 1) * t - s)); if (t < 1) return 0.5 * (t * t * ((s + 1) * t - s));
t -= 2; return 0.5 * (t * t * ((s + 1) * t + s) + 2); t -= 2; return 0.5 * (t * t * ((s + 1) * t + s) + 2);
}, },
/** @type {KUTE.easingFunction} */
easingElasticIn: (t0) => { easingElasticIn: (t0) => {
let s; let s;
let k1 = 0.1; let k1 = 0.1;
@ -68,6 +94,7 @@ const Easing = {
t -= 1; t -= 1;
return -(k1 * (2 ** (10 * t)) * Math.sin(((t - s) * Math.PI * 2) / k2)); return -(k1 * (2 ** (10 * t)) * Math.sin(((t - s) * Math.PI * 2) / k2));
}, },
/** @type {KUTE.easingFunction} */
easingElasticOut: (t) => { easingElasticOut: (t) => {
let s; let s;
let k1 = 0.1; let k1 = 0.1;
@ -82,6 +109,7 @@ const Easing = {
} }
return k1 * (2 ** (-10 * t)) * Math.sin(((t - s) * Math.PI * 2) / k2) + 1; return k1 * (2 ** (-10 * t)) * Math.sin(((t - s) * Math.PI * 2) / k2) + 1;
}, },
/** @type {KUTE.easingFunction} */
easingElasticInOut: (t0) => { easingElasticInOut: (t0) => {
let t = t0; let t = t0;
let s; let s;
@ -97,12 +125,14 @@ const Easing = {
t *= 2; t *= 2;
if (t < 1) { if (t < 1) {
return -0.5 * (k1 * (2 ** (10 * (t - 1))) return -0.5 * (k1 * (2 ** (10 * (t - 1)))
* Math.sin(((t - 1 - s) * Math.PI * 2) / k2)); * Math.sin(((t - 1 - s) * Math.PI * 2) / k2));
} }
t -= 1; t -= 1;
return k1 * (2 ** (-10 * t)) * Math.sin(((t - s) * Math.PI * 2) / k2) * 0.5 + 1; return k1 * (2 ** (-10 * t)) * Math.sin(((t - s) * Math.PI * 2) / k2) * 0.5 + 1;
}, },
/** @type {KUTE.easingFunction} */
easingBounceIn: (t) => 1 - Easing.easingBounceOut(1 - t), easingBounceIn: (t) => 1 - Easing.easingBounceOut(1 - t),
/** @type {KUTE.easingFunction} */
easingBounceOut: (t0) => { easingBounceOut: (t0) => {
let t = t0; let t = t0;
if (t < (1 / 2.75)) { return 7.5625 * t * t; } if (t < (1 / 2.75)) { return 7.5625 * t * t; }
@ -111,12 +141,19 @@ const Easing = {
t -= (2.625 / 2.75); t -= (2.625 / 2.75);
return 7.5625 * t * t + 0.984375; return 7.5625 * t * t + 0.984375;
}, },
/** @type {KUTE.easingFunction} */
easingBounceInOut: (t) => { easingBounceInOut: (t) => {
if (t < 0.5) return Easing.easingBounceIn(t * 2) * 0.5; if (t < 0.5) return Easing.easingBounceIn(t * 2) * 0.5;
return Easing.easingBounceOut(t * 2 - 1) * 0.5 + 0.5; return Easing.easingBounceOut(t * 2 - 1) * 0.5 + 0.5;
}, },
}; };
/**
* Returns a valid `easingFunction`.
*
* @param {KUTE.easingFunction | string} fn function name or constructor
* @returns {KUTE.easingFunction} a valid easing function
*/
function processEasing(fn) { function processEasing(fn) {
if (typeof fn === 'function') { if (typeof fn === 'function') {
return fn; return fn;

View file

@ -1,22 +1,22 @@
import Render from './core/render.js'; import Render from './core/render';
import Interpolate from './objects/interpolate.js'; import Interpolate from './objects/interpolate';
import Objects from './objects/objectsBase.js'; import Objects from './objects/objectsBase';
import Util from './objects/util.js'; import Util from './objects/util';
import Easing from './easing/easing-base.js'; import Easing from './easing/easing-base';
import Internals from './core/internals.js'; import Internals from './core/internals';
import Selector from './util/selector.js'; import Selector from './util/selector';
// Animation // Animation
import Animation from './animation/animationBase.js'; import Animation from './animation/animationBase';
// Base Components // Base Components
import Components from './objects/componentsBase.js'; import Components from './objects/componentsBase';
// TweenConstructor // TweenConstructor
import Tween from './tween/tweenBase.js'; import Tween from './tween/tweenBase';
// Interface only fromTo // Interface only fromTo
import fromTo from './interface/fromTo.js'; import fromTo from './interface/fromTo';
import Version from './util/version.js'; import Version from './util/version';
export default { export default {
Animation, Animation,

View file

@ -1,30 +1,30 @@
import CubicBezier from 'cubic-bezier-easing'; import CubicBezier from 'cubic-bezier-easing';
import Render from './core/render.js'; import Render from './core/render';
import Interpolate from './objects/interpolate.js'; import Interpolate from './objects/interpolate';
import Objects from './objects/objects.js'; import Objects from './objects/objects';
import Util from './objects/util.js'; import Util from './objects/util';
import Internals from './core/internals.js'; import Internals from './core/internals';
import Process from './process/process.js'; import Process from './process/process';
import Easing from './easing/easing-bezier.js'; import Easing from './easing/easing-bezier';
import Selector from './util/selector.js'; import Selector from './util/selector';
// TweenConstructor // TweenConstructor
import Tween from './tween/tweenExtra.js'; import Tween from './tween/tweenExtra';
import TweenCollection from './tween/tweenCollection.js'; import TweenCollection from './tween/tweenCollection';
import ProgressBar from './util/progressBar.js'; import ProgressBar from './util/progressBar';
// interface // interface
import to from './interface/to.js'; import to from './interface/to';
import fromTo from './interface/fromTo.js'; import fromTo from './interface/fromTo';
import allTo from './interface/allTo.js'; import allTo from './interface/allTo';
import allFromTo from './interface/allFromTo.js'; import allFromTo from './interface/allFromTo';
// Animation // Animation
import Animation from './animation/animationDevelopment.js'; import Animation from './animation/animationDevelopment';
// Components Extra // Components Extra
import Components from './objects/componentsExtra.js'; import Components from './objects/componentsExtra';
import Version from './util/version.js'; import Version from './util/version';
export default { export default {
Animation, Animation,

View file

@ -1,40 +1,40 @@
import Render from './core/render.js'; import Render from './core/render';
import Interpolate from './objects/interpolate.js'; import Interpolate from './objects/interpolate';
import Objects from './objects/objects.js'; import Objects from './objects/objects';
import Util from './objects/util.js'; import Util from './objects/util';
import Internals from './core/internals.js'; import Internals from './core/internals';
import Process from './process/process.js'; import Process from './process/process';
import Easing from './easing/easing.js'; import Easing from './easing/easing';
import Selector from './util/selector.js'; import Selector from './util/selector';
// TweenConstructor // TweenConstructor
import Tween from './tween/tween.js'; import Tween from './tween/tween';
import TweenCollection from './tween/tweenCollection.js'; import TweenCollection from './tween/tweenCollection';
// interface // interface
import to from './interface/to.js'; import to from './interface/to';
import fromTo from './interface/fromTo.js'; import fromTo from './interface/fromTo';
import allTo from './interface/allTo.js'; import allTo from './interface/allTo';
import allFromTo from './interface/allFromTo.js'; import allFromTo from './interface/allFromTo';
import Animation from './animation/animation.js'; import Animation from './animation/animation';
// components // components
import BoxModel from './components/boxModelEssential.js'; import BoxModel from './components/boxModelEssential';
import ColorProperties from './components/colorProperties.js'; import ColorProperties from './components/colorProperties';
import HTMLAttributes from './components/htmlAttributes.js'; import HTMLAttributes from './components/htmlAttributes';
import OpacityProperty from './components/opacityProperty.js'; import OpacityProperty from './components/opacityProperty';
import TextWrite from './components/textWrite.js'; import TextWriteProp from './components/textWrite';
import TransformLegacy from './components/transformLegacy.js'; import TransformLegacy from './components/transformLegacy';
import SVGDraw from './components/svgDraw.js'; import SVGDraw from './components/svgDraw';
import SVGMorph from './components/svgMorph.js'; import SVGMorph from './components/svgMorph';
import Version from './util/version.js'; import Version from './util/version';
const Components = { const Components = {
BoxModel, BoxModel,
ColorProperties, ColorProperties,
HTMLAttributes, HTMLAttributes,
OpacityProperty, OpacityProperty,
TextWrite, TextWriteProp,
TransformLegacy, TransformLegacy,
SVGDraw, SVGDraw,
SVGMorph, SVGMorph,

View file

@ -1,29 +1,30 @@
// KUTE.js standard distribution version
import CubicBezier from 'cubic-bezier-easing'; import CubicBezier from 'cubic-bezier-easing';
import Render from './core/render.js'; import Render from './core/render';
import Interpolate from './objects/interpolate.js'; import Interpolate from './objects/interpolate';
import Objects from './objects/objects.js'; import Objects from './objects/objects';
import Util from './objects/util.js'; import Util from './objects/util';
import Internals from './core/internals.js'; import Internals from './core/internals';
import Process from './process/process.js'; import Process from './process/process';
import Easing from './easing/easing-bezier.js'; import Easing from './easing/easing-bezier';
import Selector from './util/selector.js'; import Selector from './util/selector';
// TweenConstructor // TweenConstructor
import Tween from './tween/tween.js'; import Tween from './tween/tween';
import TweenCollection from './tween/tweenCollection.js'; import TweenCollection from './tween/tweenCollection';
// interface // interface
import to from './interface/to.js'; import to from './interface/to';
import fromTo from './interface/fromTo.js'; import fromTo from './interface/fromTo';
import allTo from './interface/allTo.js'; import allTo from './interface/allTo';
import allFromTo from './interface/allFromTo.js'; import allFromTo from './interface/allFromTo';
// Animation // Animation
import Animation from './animation/animation.js'; import Animation from './animation/animation';
// Default Components // Default Components
import Components from './objects/componentsDefault.js'; import Components from './objects/componentsDefault';
import Version from './util/version.js'; import Version from './util/version';
const KUTE = { const KUTE = {
Animation, Animation,

View file

@ -1,6 +1,17 @@
import selector from '../util/selector.js'; import selector from '../util/selector';
import TweenCollection from '../tween/tweenCollection.js'; import TweenCollection from '../tween/tweenCollection';
/**
* The `KUTE.allFromTo()` static method creates a new Tween object
* for multiple `HTMLElement`s, `HTMLCollection` or `NodeListat`
* at a given state.
*
* @param {Element[] | HTMLCollection | NodeList} elements target elements
* @param {KUTE.tweenProps} startObject
* @param {KUTE.tweenProps} endObject
* @param {KUTE.tweenOptions} optionsObj tween options
* @returns {TweenCollection} the Tween object collection
*/
export default function allFromTo(elements, startObject, endObject, optionsObj) { export default function allFromTo(elements, startObject, endObject, optionsObj) {
const options = optionsObj || {}; const options = optionsObj || {};
return new TweenCollection(selector(elements, true), startObject, endObject, options); return new TweenCollection(selector(elements, true), startObject, endObject, options);

View file

@ -1,9 +1,18 @@
import selector from '../util/selector.js'; import selector from '../util/selector';
import TweenCollection from '../tween/tweenCollection.js'; import TweenCollection from '../tween/tweenCollection';
// multiple elements tween objects /**
* The `KUTE.allTo()` static method creates a new Tween object
* for multiple `HTMLElement`s, `HTMLCollection` or `NodeListat`
* at their current state.
*
* @param {Element[] | HTMLCollection | NodeList} elements target elements
* @param {KUTE.tweenProps} endObject
* @param {KUTE.tweenProps} optionsObj progress
* @returns {TweenCollection} the Tween object collection
*/
export default function allTo(elements, endObject, optionsObj) { export default function allTo(elements, endObject, optionsObj) {
const options = optionsObj || {}; const options = optionsObj || {};
optionsObj.resetStart = endObject; options.resetStart = endObject;
return new TweenCollection(selector(elements, true), endObject, endObject, options); return new TweenCollection(selector(elements, true), endObject, endObject, options);
} }

View file

@ -1,8 +1,19 @@
import selector from '../util/selector.js'; import selector from '../util/selector';
import connect from '../objects/connect.js'; import connect from '../objects/connect';
const { tween: TweenConstructor } = connect;
/**
* The `KUTE.fromTo()` static method returns a new Tween object
* for a single `HTMLElement` at a given state.
*
* @param {Element} element target element
* @param {KUTE.tweenProps} startObject
* @param {KUTE.tweenProps} endObject
* @param {KUTE.tweenOptions} optionsObj tween options
* @returns {KUTE.Tween} the resulting Tween object
*/
export default function fromTo(element, startObject, endObject, optionsObj) { export default function fromTo(element, startObject, endObject, optionsObj) {
const options = optionsObj || {}; const options = optionsObj || {};
const TweenConstructor = connect.tween;
return new TweenConstructor(selector(element), startObject, endObject, options); return new TweenConstructor(selector(element), startObject, endObject, options);
} }

View file

@ -1,9 +1,19 @@
import selector from '../util/selector.js'; import selector from '../util/selector';
import connect from '../objects/connect.js'; import connect from '../objects/connect';
const { tween: TweenConstructor } = connect;
/**
* The `KUTE.to()` static method returns a new Tween object
* for a single `HTMLElement` at its current state.
*
* @param {Element} element target element
* @param {KUTE.tweenProps} endObject
* @param {KUTE.tweenOptions} optionsObj tween options
* @returns {KUTE.Tween} the resulting Tween object
*/
export default function to(element, endObject, optionsObj) { export default function to(element, endObject, optionsObj) {
const options = optionsObj || {}; const options = optionsObj || {};
const TweenConstructor = connect.tween;
options.resetStart = endObject; options.resetStart = endObject;
return new TweenConstructor(selector(element), endObject, endObject, options); return new TweenConstructor(selector(element), endObject, endObject, options);
} }

View file

@ -1,6 +1,15 @@
/**
* Array Interpolation Function.
*
* @param {number[]} a start array
* @param {number[]} b end array
* @param {number} v progress
* @returns {number[]} the resulting array
*/
export default function arrays(a, b, v) { export default function arrays(a, b, v) {
const result = []; const result = []; const { length } = b;
for (let i = 0, l = b.length; i < l; i += 1) { for (let i = 0; i < length; i += 1) {
// eslint-disable-next-line no-bitwise
result[i] = ((a[i] + (b[i] - a[i]) * v) * 1000 >> 0) / 1000; result[i] = ((a[i] + (b[i] - a[i]) * v) * 1000 >> 0) / 1000;
} }
return result; return result;

View file

@ -1,5 +1,12 @@
import numbers from './numbers.js'; import numbers from './numbers';
/**
* Color Interpolation Function.
*
* @param {KUTE.colorObject} a start color
* @param {KUTE.colorObject} b end color
* @param {number} v progress
* @returns {string} the resulting color
*/
export default function colors(a, b, v) { export default function colors(a, b, v) {
const _c = {}; const _c = {};
const ep = ')'; const ep = ')';
@ -8,12 +15,10 @@ export default function colors(a, b, v) {
const rgba = 'rgba('; const rgba = 'rgba(';
Object.keys(b).forEach((c) => { Object.keys(b).forEach((c) => {
// _c[c] = c !== 'a' ? (numbers(a[c], b[c], v) >> 0 || 0) : (a[c] && b[c])
// ? (numbers(a[c], b[c], v) * 100 >> 0) / 100 : null;
if (c !== 'a') { if (c !== 'a') {
_c[c] = numbers(a[c], b[c], v) >> 0 || 0; _c[c] = numbers(a[c], b[c], v) >> 0 || 0; // eslint-disable-line no-bitwise
} else if (a[c] && b[c]) { } else if (a[c] && b[c]) {
_c[c] = (numbers(a[c], b[c], v) * 100 >> 0) / 100; _c[c] = (numbers(a[c], b[c], v) * 100 >> 0) / 100; // eslint-disable-line no-bitwise
} }
}); });

View file

@ -1,8 +1,18 @@
/**
* Coordinates Interpolation Function.
*
* @param {number[][]} a start coordinates
* @param {number[][]} b end coordinates
* @param {string} l amount of coordinates
* @param {number} v progress
* @returns {number[][]} the interpolated coordinates
*/
export default function coords(a, b, l, v) { export default function coords(a, b, l, v) {
const points = []; const points = [];
for (let i = 0; i < l; i += 1) { // for each point for (let i = 0; i < l; i += 1) { // for each point
points[i] = []; points[i] = [];
for (let j = 0; j < 2; j += 1) { // each point coordinate for (let j = 0; j < 2; j += 1) { // each point coordinate
// eslint-disable-next-line no-bitwise
points[i].push(((a[i][j] + (b[i][j] - a[i][j]) * v) * 1000 >> 0) / 1000); points[i].push(((a[i][j] + (b[i][j] - a[i][j]) * v) * 1000 >> 0) / 1000);
} }
} }

View file

@ -1,4 +1,12 @@
export default function numbers(a, b, v) { // number1, number2, progress /**
* Numbers Interpolation Function.
*
* @param {number} a start value
* @param {number} b end value
* @param {number} v progress
* @returns {number} the interpolated number
*/
export default function numbers(a, b, v) {
const A = +a; const A = +a;
const B = b - a; const B = b - a;
// a = +a; b -= a; // a = +a; b -= a;

View file

@ -1,3 +1,13 @@
/**
* Perspective Interpolation Function.
*
* @param {number} a start value
* @param {number} b end value
* @param {string} u unit
* @param {number} v progress
* @returns {string} the perspective function in string format
*/
export default function perspective(a, b, u, v) { export default function perspective(a, b, u, v) {
// eslint-disable-next-line no-bitwise
return `perspective(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`; return `perspective(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`;
} }

View file

@ -1,3 +1,13 @@
/**
* 2D Rotation Interpolation Function.
*
* @param {number} a start angle
* @param {number} b end angle
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated rotation
*/
export default function rotate(a, b, u, v) { export default function rotate(a, b, u, v) {
// eslint-disable-next-line no-bitwise
return `rotate(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`; return `rotate(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`;
} }

View file

@ -1,7 +1,19 @@
/**
* 3D Rotation Interpolation Function.
*
* @param {number} a start [x,y,z] angles
* @param {number} b end [x,y,z] angles
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated 3D rotation string
*/
export default function rotate3d(a, b, u, v) { export default function rotate3d(a, b, u, v) {
let rotateStr = ''; let rotateStr = '';
// eslint-disable-next-line no-bitwise
rotateStr += a[0] || b[0] ? `rotateX(${((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000}${u})` : ''; rotateStr += a[0] || b[0] ? `rotateX(${((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000}${u})` : '';
// eslint-disable-next-line no-bitwise
rotateStr += a[1] || b[1] ? `rotateY(${((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000}${u})` : ''; rotateStr += a[1] || b[1] ? `rotateY(${((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000}${u})` : '';
// eslint-disable-next-line no-bitwise
rotateStr += a[2] || b[2] ? `rotateZ(${((a[2] + (b[2] - a[2]) * v) * 1000 >> 0) / 1000}${u})` : ''; rotateStr += a[2] || b[2] ? `rotateZ(${((a[2] + (b[2] - a[2]) * v) * 1000 >> 0) / 1000}${u})` : '';
return rotateStr; return rotateStr;
} }

View file

@ -1,3 +1,12 @@
/**
* Scale Interpolation Function.
*
* @param {number} a start scale
* @param {number} b end scale
* @param {number} v progress
* @returns {string} the interpolated scale
*/
export default function scale(a, b, v) { export default function scale(a, b, v) {
// eslint-disable-next-line no-bitwise
return `scale(${((a + (b - a) * v) * 1000 >> 0) / 1000})`; return `scale(${((a + (b - a) * v) * 1000 >> 0) / 1000})`;
} }

View file

@ -1,6 +1,17 @@
/**
* Skew Interpolation Function.
*
* @param {number} a start {x,y} angles
* @param {number} b end {x,y} angles
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated string value of skew(s)
*/
export default function skew(a, b, u, v) { export default function skew(a, b, u, v) {
const skewArray = []; const skewArray = [];
// eslint-disable-next-line no-bitwise
skewArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u; skewArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u;
// eslint-disable-next-line no-bitwise
skewArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0'; skewArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0';
return `skew(${skewArray.join(',')})`; return `skew(${skewArray.join(',')})`;
} }

View file

@ -1,3 +1,13 @@
/**
* SkewX Interpolation Function.
*
* @param {number} a start angle
* @param {number} b end angle
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated skewX
*/
export default function skewX(a, b, u, v) { export default function skewX(a, b, u, v) {
// eslint-disable-next-line no-bitwise
return `skewX(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`; return `skewX(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`;
} }

View file

@ -1,3 +1,13 @@
/**
* SkewY Interpolation Function.
*
* @param {number} a start angle
* @param {number} b end angle
* @param {string} u unit, usually `deg` degrees
* @param {number} v progress
* @returns {string} the interpolated skewY
*/
export default function skewY(a, b, u, v) { export default function skewY(a, b, u, v) {
// eslint-disable-next-line no-bitwise
return `skewY(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`; return `skewY(${((a + (b - a) * v) * 1000 >> 0) / 1000}${u})`;
} }

View file

@ -1,6 +1,17 @@
/**
* Translate 2D Interpolation Function.
*
* @param {number[]} a start [x,y] position
* @param {number[]} b end [x,y] position
* @param {string} u unit, usually `px` degrees
* @param {number} v progress
* @returns {string} the interpolated 2D translation string
*/
export default function translate(a, b, u, v) { export default function translate(a, b, u, v) {
const translateArray = []; const translateArray = [];
// eslint-disable-next-line no-bitwise
translateArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u; translateArray[0] = (a[0] === b[0] ? b[0] : ((a[0] + (b[0] - a[0]) * v) * 1000 >> 0) / 1000) + u;
// eslint-disable-next-line no-bitwise
translateArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0'; translateArray[1] = a[1] || b[1] ? ((a[1] === b[1] ? b[1] : ((a[1] + (b[1] - a[1]) * v) * 1000 >> 0) / 1000) + u) : '0';
return `translate(${translateArray.join(',')})`; return `translate(${translateArray.join(',')})`;
} }

View file

@ -1,7 +1,17 @@
/**
* Translate 3D Interpolation Function.
*
* @param {number[]} a start [x,y,z] position
* @param {number[]} b end [x,y,z] position
* @param {string} u unit, usually `px` degrees
* @param {number} v progress
* @returns {string} the interpolated 3D translation string
*/
export default function translate3d(a, b, u, v) { export default function translate3d(a, b, u, v) {
const translateArray = []; const translateArray = [];
for (let ax = 0; ax < 3; ax += 1) { for (let ax = 0; ax < 3; ax += 1) {
translateArray[ax] = (a[ax] || b[ax] translateArray[ax] = (a[ax] || b[ax]
// eslint-disable-next-line no-bitwise
? ((a[ax] + (b[ax] - a[ax]) * v) * 1000 >> 0) / 1000 : 0) + u; ? ((a[ax] + (b[ax] - a[ax]) * v) * 1000 >> 0) / 1000 : 0) + u;
} }
return `translate3d(${translateArray.join(',')})`; return `translate3d(${translateArray.join(',')})`;

View file

@ -1,3 +1,12 @@
/**
* Units Interpolation Function.
*
* @param {number} a start value
* @param {number} b end value
* @param {string} u unit
* @param {number} v progress
* @returns {string} the interpolated value + unit string
*/
export default function units(a, b, u, v) { // number1, number2, unit, progress export default function units(a, b, u, v) { // number1, number2, unit, progress
const A = +a; const A = +a;
const B = b - a; const B = b - a;

View file

@ -1,11 +1,11 @@
import Animation from '../animation/animationBase.js'; import Animation from '../animation/animationBase';
// kute-base.js supported components // kute-base supported components
import baseTransform from '../components/transformFunctionsBase.js'; import baseTransform from '../components/transformFunctionsBase';
import baseBoxModel from '../components/boxModelBase.js'; import baseBoxModel from '../components/boxModelBase';
import baseOpacity from '../components/opacityPropertyBase.js'; import baseOpacity from '../components/opacityPropertyBase';
// import {baseCrossBrowserMove} from '../components/crossBrowserMove.js' // import {baseCrossBrowserMove} from '../components/crossBrowserMove'
// support for kute-base.js ends here // support for kute-base ends here
const Components = { const Components = {
Transform: new Animation(baseTransform), Transform: new Animation(baseTransform),

View file

@ -1,20 +1,20 @@
import Animation from '../animation/animation.js'; import Animation from '../animation/animation';
import EssentialBoxModel from '../components/boxModelEssential.js'; import EssentialBoxModel from '../components/boxModelEssential';
import ColorsProperties from '../components/colorProperties.js'; import ColorsProperties from '../components/colorProperties';
import HTMLAttributes from '../components/htmlAttributes.js'; import HTMLAttributes from '../components/htmlAttributes';
import OpacityProperty from '../components/opacityProperty.js'; import OpacityProperty from '../components/opacityProperty';
import TextWrite from '../components/textWrite.js'; import TextWriteProp from '../components/textWrite';
import TransformFunctions from '../components/transformFunctions.js'; import TransformFunctions from '../components/transformFunctions';
import SVGDraw from '../components/svgDraw.js'; import SVGDraw from '../components/svgDraw';
import SVGMorph from '../components/svgMorph.js'; import SVGMorph from '../components/svgMorph';
const Components = { const Components = {
EssentialBoxModel, EssentialBoxModel,
ColorsProperties, ColorsProperties,
HTMLAttributes, HTMLAttributes,
OpacityProperty, OpacityProperty,
TextWrite, TextWriteProp,
TransformFunctions, TransformFunctions,
SVGDraw, SVGDraw,
SVGMorph, SVGMorph,

View file

@ -1,21 +1,21 @@
import Animation from '../animation/animationDevelopment.js'; import Animation from '../animation/animationDevelopment';
import BackgroundPosition from '../components/backgroundPosition.js'; import BackgroundPosition from '../components/backgroundPosition';
import BorderRadius from '../components/borderRadius.js'; import BorderRadius from '../components/borderRadius';
import BoxModel from '../components/boxModel.js'; import BoxModel from '../components/boxModel';
import ClipProperty from '../components/clipProperty.js'; import ClipProperty from '../components/clipProperty';
import ColorProperties from '../components/colorProperties.js'; import ColorProperties from '../components/colorProperties';
import FilterEffects from '../components/filterEffects'; import FilterEffects from '../components/filterEffects';
import HTMLAttributes from '../components/htmlAttributes.js'; import HTMLAttributes from '../components/htmlAttributes';
import OpacityProperty from '../components/opacityProperty.js'; import OpacityProperty from '../components/opacityProperty';
import SVGDraw from '../components/svgDraw.js'; import SVGDraw from '../components/svgDraw';
import SVGCubicMorph from '../components/svgCubicMorph.js'; import SVGCubicMorph from '../components/svgCubicMorph';
import SVGTransform from '../components/svgTransform.js'; import SVGTransform from '../components/svgTransform';
import ScrollProperty from '../components/scrollProperty.js'; import ScrollProperty from '../components/scrollProperty';
import ShadowProperties from '../components/shadowProperties.js'; import ShadowProperties from '../components/shadowProperties';
import TextProperties from '../components/textProperties.js'; import TextProperties from '../components/textProperties';
import TextWriteProperties from '../components/textWrite.js'; import TextWriteProperties from '../components/textWrite';
import MatrixTransform from '../components/transformMatrix.js'; import MatrixTransform from '../components/transformMatrix';
const Components = { const Components = {
BackgroundPosition, BackgroundPosition,

View file

@ -1 +1,6 @@
export default {}; const connect = {};
/** @type {KUTE.TweenBase | KUTE.Tween | KUTE.TweenExtra} */
connect.tween = null;
connect.processEasing = null;
export default connect;

Some files were not shown because too many files have changed in this diff Show more