The 1.5 first commit, still testing, changelog in the comments

This commit is contained in:
thednp 2016-03-16 15:44:23 +02:00
parent 320cc59b05
commit dc820c5654
21 changed files with 3216 additions and 0 deletions

30
demo/assets/js/attr.js Normal file
View file

@ -0,0 +1,30 @@
// radius attribute
var radiusTween = KUTE.to('#circle', {attr: {r: 75} }, {repeat:1, yoyo: true, easing: 'easingCubicOut'});
// coordinates of the circle center
var coordinatesTween1 = KUTE.to('#circle', {attr: {cx:40,cy:40}}, { duration: 300, easing: 'easingCubicOut'});
var coordinatesTween2 = KUTE.to('#circle', {attr: {cx:110,cy:40}}, { duration: 400, easing: 'linear'});
var coordinatesTween3 = KUTE.to('#circle', {attr: {cx:75,cy:75}}, { easing: 'easingCubicOut'});
coordinatesTween1.chain(coordinatesTween2);
coordinatesTween2.chain(coordinatesTween3);
coordinatesTween3.chain(radiusTween);
var circleBtn = document.getElementById('circleBtn');
circleBtn.addEventListener('click', function(){
!coordinatesTween1.playing && !coordinatesTween2.playing && !coordinatesTween3.playing && !radiusTween.playing && coordinatesTween1.start();
});
// coordinatea of gradient
var gradBtn = document.getElementById('gradBtn');
var closingGradient = KUTE.to('#gradient',{attr: {x1:'49%', x2:'49%', y1:'49%', y2:'51%'}}, {easing: 'easingCubicInOut'});
var rotatingGradient1 = KUTE.to('#gradient',{attr: {x1:'49%', x2:'51%', y1:'51%', y2:'51%'}}, {easing: 'easingCubicInOut'});
var rotatingGradient2 = KUTE.to('#gradient',{attr: {x1:'0%', x2:'51%', y1:'100%', y2:'0%'}}, {easing: 'easingCubicInOut'});
var openingGradient = KUTE.to('#gradient',{attr: {x1:'0%', x2:'0%', y1:'0%', y2:'100%'}}, {duration: 1500, easing: 'easingCubicInOut'});
closingGradient.chain(rotatingGradient1);
rotatingGradient1.chain(rotatingGradient2);
rotatingGradient2.chain(openingGradient);
gradBtn.addEventListener('click', function(){
!closingGradient.playing && !rotatingGradient1.playing && !rotatingGradient2.playing && !openingGradient.playing && closingGradient.start();
});

164
demo/assets/js/css.js Normal file
View file

@ -0,0 +1,164 @@
// some regular checking
var isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false,
isIE8 = isIE === 8,
isIE9 = isIE === 9;
/* RADIUS EXAMPLES */
var radiusBtn = document.getElementById('radiusBtn');
var allRadius = KUTE.to('#allRadius',{borderRadius:80},{easing:'easingCubicOut', repeat: 1, yoyo: true});
var tlRadius = KUTE.to('#tlRadius',{borderTopLeftRadius:150},{easing:'easingCubicOut', repeat: 1, yoyo: true});
var trRadius = KUTE.to('#trRadius',{borderTopRightRadius:150},{easing:'easingCubicOut', repeat: 1, yoyo: true});
var blRadius = KUTE.to('#blRadius',{borderBottomLeftRadius:150},{easing:'easingCubicOut', repeat: 1, yoyo: true});
var brRadius = KUTE.to('#brRadius',{borderBottomRightRadius:150},{easing:'easingCubicOut', repeat: 1, yoyo: true});
radiusBtn.addEventListener('click',function(){
if (!allRadius.playing) { allRadius.start(); tlRadius.start(); trRadius.start(); blRadius.start(); brRadius.start(); }
}, false);
/* RADIUS EXAMPLES */
/* BOX MODEL EXAMPLE */
var boxModel = document.getElementById('boxModel'),
btb = boxModel.querySelector('.btn'),
box = boxModel.querySelector('.example-box-model');
// built the tween objects
var bm1 = KUTE.to(box,{marginTop:50},{ yoyo: true, repeat: 1, duration: 1500, update: onMarginTop});
var bm2 = KUTE.to(box,{marginBottom:50},{ yoyo: true, repeat: 1, duration: 1500, update: onMarginBottom});
var bm3 = KUTE.to(box,{padding:30},{ yoyo: true, repeat: 1, duration: 1500, update: onPadding});
var bm4 = KUTE.to(box,{marginTop:50,marginLeft:50,marginBottom:70},{ yoyo: true, repeat: 1, duration: 1500, update: onMargin, complete: onComplete});
// chain the bms
bm1.chain(bm2);
bm2.chain(bm3);
bm3.chain(bm4);
//callback functions
function onMarginTop() { var css = KUTE.gCS(box,'marginTop'); box.innerHTML = parseInt(css)+'px'+'<br>MARGIN'; }
function onMarginBottom() { var css = KUTE.gCS(box,'marginBottom'); box.innerHTML = 'MARGIN<br>'+parseInt(css)+'px'; }
function onPadding() { var css = KUTE.gCS(box,'paddingTop'); box.innerHTML = 'PADDING<br>'+parseInt(css)+'px'; }
function onMargin() { var css = KUTE.gCS(box,'marginTop'); box.innerHTML = 'MARGIN<br>'+parseInt(css)+'px'; }
function onComplete() { box.innerHTML = 'BOX<br>&nbsp;MODEL&nbsp;'; }
btb.addEventListener('click', function(e){
e.preventDefault();
!bm1.playing && !bm2.playing && !bm3.playing && !bm4.playing && bm1.start();
},false);
/* BOX MODEL EXAMPLE */
/* TEXT PROPERTIES EXAMPLE */
var textProperties = document.getElementById('textProperties'),
heading = textProperties.querySelector('h1'),
button = textProperties.querySelectorAll('.btn')[0],
tbt = textProperties.querySelectorAll('.btn')[1],
// let's split the heading text by character
chars = heading.innerHTML.split('');
// wrap the splits into spans and build an object with these spans
heading.innerHTML = '<span>' + chars.join('</span><span>') + '</span>';
var charsObject = heading.getElementsByTagName('SPAN'), l = charsObject.length;
// built the tween objects
var tp1 = KUTE.fromTo(
button,
{width: 150, opacity:0, height: 70, lineHeight:70, fontSize: 40},
{width: 100, opacity:1, height: 35, lineHeight:35, fontSize: 20}),
tps = [];
for (var i=0; i<l; i++){
var fn = i === l-1 ? startButtonAnimation : null,
delay = 250*i;
tps.push(KUTE.fromTo(charsObject[i],
{opacity:0, height: 50, fontSize:80, letterSpacing: 20},
{opacity:1, height: 35, fontSize:50, letterSpacing: 0},
{complete: fn, delay: delay, duration: 500, easing: 'easingCubicOut'}
))
}
function startButtonAnimation(){
tp1.start();
}
function runHeadingAnimation() {
for (var i=0; i<l; i++){
tps[i].start();
}
}
tbt.addEventListener('click', function(e){
e.preventDefault();
if (!tp1.playing && !tps[0].playing && !tps[l-1].playing) {
for (var i=0;i<l; i++) {
charsObject[i].style.opacity ="";
if (isIE8) charsObject[i].style.filter ="";
}
button.style.opacity = '';
if (isIE8) button.style.filter ="";
runHeadingAnimation();
}
},false);
/* TEXT PROPERTIES EXAMPLE */
/* COLORS EXAMPLE */
var colBox = document.getElementById('colBox'),
colBoxElement = colBox.querySelector('.example-box'),
colbtn = colBox.querySelector('.btn');
var colTween1 = KUTE.to(colBoxElement, {borderColor: '#069'}, {duration: 1000});
var colTween2 = KUTE.to(colBoxElement, {borderTopColor: '#9C27B0'}, {duration: 1000});
var colTween3 = KUTE.to(colBoxElement, {borderRightColor: '#9C27B0'}, {duration: 1000});
var colTween4 = KUTE.to(colBoxElement, {borderBottomColor: '#9C27B0'}, {duration: 1000});
var colTween5 = KUTE.to(colBoxElement, {borderLeftColor: '#9C27B0'}, {duration: 1000});
colTween1.chain(colTween2);
colTween2.chain(colTween3);
colTween3.chain(colTween4);
colTween4.chain(colTween5);
colbtn.addEventListener('click', function(e){
e.preventDefault();
!colTween1.playing && !colTween2.playing && !colTween3.playing && !colTween4.playing && !colTween5.playing && colTween1.start();
},false);
/* COLORS EXAMPLE */
/* CLIP EXAMPLE */
var clipExample = document.getElementById('clip'),
clipElement = clipExample.querySelector('.example-box'),
clpbtn = clipExample.querySelector('.btn');
var clp1 = KUTE.to(clipElement, {clip: [0,20,150,0]}, {duration:500, easing: 'easingCubicOut'});
var clp2 = KUTE.to(clipElement, {clip: [0,150,150,130]}, {duration:600, easing: 'easingCubicOut'});
var clp3 = KUTE.to(clipElement, {clip: [0,150,20,0]}, {duration:800, easing: 'easingCubicOut'});
var clp4 = KUTE.to(clipElement, {clip: [0,150,150,0]}, {duration:1200, easing: 'easingExponentialInOut'});
//chain some clps
clp1.chain(clp2);
clp2.chain(clp3);
clp3.chain(clp4);
clpbtn.addEventListener('click', function(e){
e.preventDefault();
!clp1.playing && !clp2.playing && !clp3.playing && !clp4.playing && clp1.start();
},false);
/* CLIP EXAMPLE */
/* BACKGROUND POSITION EXAMPLE */
var bgPos = document.getElementById('bgPos'),
bgBox = bgPos.querySelector('.example-box'),
bgb = bgPos.querySelector('.btn'),
bpTween1 = KUTE.to(bgBox, {backgroundPosition: ['0%','50%']}, { yoyo: true, repeat: 1, duration: 1500, easing: 'easingCubicOut'});
bgb.addEventListener('click', function(e){
e.preventDefault();
!bpTween1.playing && bpTween1.start();
},false);
/* BACKGROUND POSITION EXAMPLE */

27
demo/assets/js/extend.js Normal file
View file

@ -0,0 +1,27 @@
var boxShadow = document.getElementById('boxShadow'),
boxBtn = boxShadow.querySelector('.btn'),
boxElement = boxShadow.getElementsByTagName('div')[0];
// tween to a string value
var myBSTween1 = KUTE.to(boxElement, {boxShadow: '0px 0px 15px 10px #CDDC39'}, {duration:1000, easing: 'easingCubicInOut'});
// or a fromTo with string and array, hex and rgb
var myBSTween2 = KUTE.fromTo(boxElement, {boxShadow: [0, 0, 15, 10, '#CDDC39']}, {boxShadow: '0px 0px 25px 25px rgb(0,66,99)'}, { duration:2000, easing: 'easingCubicInOut'});
var myBSTween3 = KUTE.to(boxElement, {boxShadow: '15px 15px 0px 0px rgb(0,66,99)'}, {duration:2000, easing: 'easingCubicInOut'});
var myBSTween4 = KUTE.to(boxElement, {boxShadow: '-15px 15px 0px 10px #E91E63'}, {duration:2000, easing: 'easingCubicInOut'});
var myBSTween5 = KUTE.to(boxElement, {boxShadow: '0px 0px 0px 0px rgb(0,0,0)'}, {duration:2000, easing: 'easingCubicInOut'});
var myBSTween6 = KUTE.to(boxElement, {boxShadow: [5, 5, 5, '#99A52A', 'inset']}, {duration:2000, easing: 'easingCubicInOut', repeat: 1, yoyo: true, complete: removeInset});
myBSTween1.chain(myBSTween2);
myBSTween2.chain(myBSTween3);
myBSTween3.chain(myBSTween4);
myBSTween4.chain(myBSTween5);
myBSTween5.chain(myBSTween6);
function removeInset() {
boxElement.style.boxShadow = '0px 0px 0px 0px rgb(0,0,0)';
}
boxBtn.addEventListener('click', function(){
!myBSTween1.playing && !myBSTween2.playing && !myBSTween3.playing &&
!myBSTween4.playing && !myBSTween5.playing && !myBSTween6.playing && myBSTween1.start();
}, false);

116
demo/assets/js/kute-bs.js Normal file
View file

@ -0,0 +1,116 @@
/* KUTE.js - The Light Tweening Engine
* package - Box Shadow Plugin
* desc - adds support for boxShadow property with an array of values [h-shadow, v-shadow, blur, spread, color, inset]
* examples
* var bShadowTween1 = KUTE.to('selector', {boxShadow: '1px 1px 1px #069'}); // accepting string value
* var bShadowTween2 = KUTE.to('selector', {boxShadow: [1, 1, 1, '#069', 'inset'] }); // accepting array value
* by dnp_theme
* Licensed under MIT-License
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
var KUTE = require("./kute.js");
module.exports = factory(KUTE);
} else if ( typeof window.KUTE !== 'undefined' ) {
factory(KUTE);
} else {
throw new Error("Box Shadow Plugin require KUTE.js.");
}
}( function (KUTE) {
'use strict';
// filter unsupported browsers
if (!('boxShadow' in document.body.style)) {return;}
// add a reference to KUTE object
var K = window.KUTE;
// the preffixed boxShadow property, mostly for legacy browsers
// maybe the browser is supporting the property with its vendor preffix
// box-shadow: none|h-shadow v-shadow blur spread color |inset|initial|inherit;
var _boxShadow = K.property('boxShadow'); // note we're using the KUTE.property() autopreffix utility
var colRegEx = /(\s?(?:#(?:[\da-f]{3}){1,2}|rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\))\s?)/gi; // a full RegEx for color strings
// for the .to() method, you need to prepareStart the boxShadow property
// which means you need to read the current computed value
K.prS['boxShadow'] = function(element,property,value){
var cssBoxShadow = K.gCS(element,'boxShadow');
return /^none$|^initial$|^inherit$|^inset$/.test(cssBoxShadow) ? '0px 0px 0px 0px rgb(0,0,0)' : cssBoxShadow;
}
// the processProperty for boxShadow
// registers the K.dom['boxShadow'] function
// returns an array of 6 values with the following format
// [horizontal, vertical, blur, spread, color: {r:0,g:0,b:0}, inset]
K.pp['boxShadow'] = function(property,value,element){
if ( !('boxShadow' in K.dom) ) {
// the DOM update function for boxShadow registers here
// we only enqueue it if the boxShadow property is used to tween
K.dom['boxShadow'] = function(w,p,v) {
// let's start with the numbers | set unit | also determine inset
var numbers = [], unit = 'px', // the unit is always px
inset = w._vS[p][5] !== 'none' || w._vE[p][5] !== 'none' ? ' inset' : false;
for (var i=0; i<4; i++){
numbers.push( (w._vS[p][i] + (w._vE[p][i] - w._vS[p][i]) * v ) + unit);
}
// now we handle the color
var color, _color = {};
for (var c in w._vE[p][4]) {
_color[c] = parseInt(w._vS[p][4][c] + (w._vE[p][4][c] - w._vS[p][4][c]) * v )||0;
}
color = 'rgb(' + _color.r + ',' + _color.g + ',' + _color.b + ') ';
// the final piece of the puzzle, the DOM update
w._el.style[_boxShadow] = inset ? color + numbers.join(' ') + inset : color + numbers.join(' ');
};
}
// processProperty for boxShadow, builds basic structure with ready to tween values
if (typeof value === 'string'){
var color, inset = 'none';
// make sure to always have the inset last if possible
inset = /inset/.test(value) ? 'inset' : inset;
value = /inset/.test(value) ? value.replace(/(\s+inset|inset+\s)/g,'') : value;
// also getComputedStyle often returns color first "rgb(0, 0, 0) 15px 15px 6px 0px inset"
color = value.match(colRegEx);
value = value.replace(color[0],'').split(' ').concat([color[0].replace(/\s/g,'')],[inset]);
value = K.processBoxShadowArray(value);
} else if (value instanceof Array){
value = K.processBoxShadowArray(value);
}
return value;
}
// utility function to process values accordingly
// numbers must be integers and color must be rgb object
K.processBoxShadowArray = function(shadow){
var newShadow, i;
if (shadow.length === 3) { // [h-shadow, v-shadow, color]
newShadow = [shadow[0], shadow[1], 0, 0, shadow[2], 'none'];
} else if (shadow.length === 4) { // [h-shadow, v-shadow, color, inset] | [h-shadow, v-shadow, blur, color]
newShadow = /inset|none/.test(shadow[3]) ? [shadow[0], shadow[1], 0, 0, shadow[2], shadow[3]] : [shadow[0], shadow[1], shadow[2], 0, shadow[3], 'none'];
} else if (shadow.length === 5) { // [h-shadow, v-shadow, blur, color, inset] | [h-shadow, v-shadow, blur, spread, color]
newShadow = /inset|none/.test(shadow[4]) ? [shadow[0], shadow[1], shadow[2], 0, shadow[3], shadow[4]] : [shadow[0], shadow[1], shadow[2], shadow[3], shadow[4], 'none'];
} else if (shadow.length === 6) { // ideal [h-shadow, v-shadow, blur, spread, color, inset]
newShadow = shadow;
}
// make sure the values are ready to tween
for (i=0;i<4;i++){
newShadow[i] = parseFloat(newShadow[i]);
}
// also the color must be a rgb object
newShadow[4] = K.truC(newShadow[4]);
return newShadow;
}
return this;
}));

108
demo/assets/js/svg.js Normal file
View file

@ -0,0 +1,108 @@
// basic morph
var morphTween = KUTE.to('#rectangle', { path: '#star' }, {
duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'
});
var morphBtn = document.getElementById('morphBtn');
morphBtn.addEventListener('click', function(){
!morphTween.playing && morphTween.start();
}, false);
var morphTween1 = KUTE.to('#rectangle1', { path: '#star1' }, {
showMorphInfo: true, morphIndex: 79,
duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'
});
var morphBtn1 = document.getElementById('morphBtn1');
morphBtn1.addEventListener('click', function(){
!morphTween1.playing && morphTween1.start();
}, false);
// simple multi morph
var multiMorphBtn = document.getElementById('multiMorphBtn');
var multiMorph1 = KUTE.to('#w11', { path: '#w24', fill: "#56C5FF" }, { morphPrecision: 10, morphIndex: 17, reverseSecondPath: true, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
var multiMorph2 = KUTE.to('#w13', { path: '#w21', fill: "#56C5FF" }, { morphPrecision: 10, morphIndex: 13, reverseSecondPath: true, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
var multiMorph3 = KUTE.to('#w14', { path: '#w22', fill: "#56C5FF" }, { morphPrecision: 10, morphIndex: 76, reverseSecondPath: true, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
var multiMorph4 = KUTE.to('#w12', { path: '#w23', fill: "#56C5FF" }, { morphPrecision: 10, morphIndex: 35, reverseSecondPath: true, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
multiMorphBtn.addEventListener('click', function(){
!multiMorph1.playing && multiMorph1.start();
!multiMorph2.playing && multiMorph2.start();
!multiMorph3.playing && multiMorph3.start();
!multiMorph4.playing && multiMorph4.start();
}, false);
// complex multi morph
var compliMorphBtn = document.getElementById('compliMorphBtn');
var compliMorph1 = KUTE.to('#rectangle-container', { path: '#circle-container', fill: "#FF5722" }, { morphPrecision: 10, morphIndex: 161, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
var compliMorph2 = KUTE.to('#symbol-left', { path: '#eye-left', fill: "#fff" }, { morphPrecision: 10, morphIndex: 20, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
var compliMorph3 = KUTE.to('#symbol-left-clone', { path: '#mouth', fill: "#fff" }, { morphPrecision: 10, morphIndex: 8, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
var compliMorph4 = KUTE.to('#symbol-right', { path: '#eye-right', fill: "#fff" }, { morphPrecision: 10, morphIndex: 55, duration: 2000, repeat: 1, yoyo: true, easing: 'easingCubicOut'});
compliMorphBtn.addEventListener('click', function(){
!compliMorph1.playing && compliMorph1.start();
!compliMorph2.playing && compliMorph2.start();
!compliMorph3.playing && compliMorph3.start();
!compliMorph4.playing && compliMorph4.start();
}, false);
// draw example
var drawBtn = document.getElementById('drawBtn');
var draw1 = KUTE.fromTo('#drawSVG',{draw:'0% 0%'}, {draw:'0% 10%'}, {duration: 1500, easing: "easingCubicIn"});
var draw2 = KUTE.fromTo('#drawSVG',{draw:'0% 10%'}, {draw:'90% 100%'}, {duration: 2500, easing: "easingCubicOut"});
var draw3 = KUTE.fromTo('#drawSVG',{draw:'90% 100%'}, {draw:'100% 100%'}, {duration: 1500, easing: "easingCubicIn"});
var draw4 = KUTE.fromTo('#drawSVG',{draw:'0% 0%'}, {draw:'0% 100%'}, {duration: 3500, easing: "easingBounceOut"});
var draw5 = KUTE.fromTo('#drawSVG',{draw:'0% 100%'}, {draw:'50% 50%'}, {duration: 2500, easing: "easingExponentialInOut"});
// var draw1 = KUTE.to('#drawSVG', {draw:'0% 10%'}, {duration: 1500, easing: "easingCubicIn"});
// var draw2 = KUTE.to('#drawSVG', {draw:'90% 100%'}, {duration: 2500, easing: "easingCubicOut"});
// var draw3 = KUTE.to('#drawSVG', {draw:'100% 100%'}, {duration: 1500, easing: "easingCubicIn"});
// var draw4 = KUTE.to('#drawSVG', {draw:'0% 100%'}, {duration: 3500, easing: "easingBounceOut"});
// var draw5 = KUTE.to('#drawSVG', {draw:'50% 50%'}, {duration: 2500, easing: "easingExponentialInOut"});
draw1.chain(draw2); draw2.chain(draw3); draw3.chain(draw4); draw4.chain(draw5);
drawBtn.addEventListener('click', function(){
!draw1.playing && !draw2.playing && !draw3.playing && !draw4.playing && !draw5.playing && draw1.start();
}, false);
// fill HEX/RGBa
var tween1 = KUTE.to('#fillSVG', {fill: '#069'}, {duration: 1500, yoyo:true, repeat: 1});
// stroke HEX/RGBa
var tween2 = KUTE.to('#fillSVG',{stroke: '#069'}, {delay: 200, yoyo:true, repeat: 1});
// strokeOpacity Number 0-1
var tween3 = KUTE.to('#fillSVG',{strokeOpacity: 0.6}, {duration: 1500, yoyo:true, repeat: 1});
// fillOpacity Number 0-1
var tween4 = KUTE.to('#fillSVG',{fillOpacity: 0.2}, {yoyo:true, repeat: 1});
// strokeWidth Number
var tween5 = KUTE.to('#fillSVG',{strokeWidth: 0}, {duration: 1500, yoyo:true, repeat: 1});
tween1.chain(tween4);
tween2.chain(tween3,tween5);
var cssBtn = document.getElementById('cssBtn');
cssBtn.addEventListener('click',function(){
!tween1.playing && !tween3.playing && !tween4.playing && !tween5.playing && tween1.start();
!tween2.playing && !tween3.playing && !tween4.playing && !tween5.playing && tween2.start();
}, false);
// stopColor HEX/RGBa
var tween6 = KUTE.to('#stopCSVG',{stopColor: 'rgb(00,66,99)'}, {duration: 1500, yoyo:true, repeat: 1});
// stopOpacity Number 0-1
var tween7 = KUTE.to('#stopOSVG',{stopOpacity: 0}, {duration: 1500, yoyo:true, repeat: 1});
tween6.chain(tween7)
var gradBtn = document.getElementById('gradBtn');
gradBtn.addEventListener('click', function(){
!tween6.playing && !tween7.playing && tween6.start();
});

165
demo/attr.html Normal file
View file

@ -0,0 +1,165 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if gte IE 10 | !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="The Attributes Plugin for KUTE.js enables animation for any numeric presentation attribute.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>KUTE.js Attributes Plugin | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Synthax highlighter -->
<link href="./assets/css/prism.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group active">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li><a href="css.html">CSS Plugin </a></li>
<li><a href="svg.html">SVG Plugin </a></li>
<li class="active"><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li><a href="easing.html">Easing Functions</a></li>
<li><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>Attributes Plugin</h2>
<p>The KUTE.js Attributes Plugin extends the core engine and enables animation for any numeric presentation attribute, with or without a measurement unit or what we know as suffix. The plugin can be a great asset for creating complex animations in combination with the <a href="svg.html">SVG Plugin</a> as we'll see in the following examples. As a quick refference, the basic synthax goes like this:</p>
<pre><code class="language-javascript">// basic synthax for unitless properties
var myAttrTween = KUTE.to('selector', {attr: {attributeName: 75}});
// OR for attributes that are ALWAYS suffixed / have a measurement unit
var mySufAttrTween = KUTE.to('selector', {attr:{attributeName: '15%'}});
</code></pre>
<p>Currently the Attributes Plugin does not support color properties such as <code>fill</code> or <code>stroke</code> as well as properties with multiple values like <code>stroke-dasharray</code>, <code>viewBox</code> or <code>transform</code> for simplicity reasons. Still, you have access to just about any SVGElement/Element presentation attribute available.</p>
<h3>Unitless Properties</h3>
<p>In the first example, let's play with the attributes of a <code>&lt;circle&gt;</code> element: radius and center coordinates.</p>
<pre><code class="language-javascript">// radius attribute
var radiusTween = KUTE.to('#circle', {attr: {r: 75}});
// coordinates of the circle center
var coordinatesTween = KUTE.to('#circle', {attr:{cx:0,cy:0}});
</code></pre>
<p>A quick demo with the above:<p>
<div class="featurettes">
<svg class="example-box-model example-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<circle class="bg-orange" id="circle" cx="75" cy="75" r="40" />
</svg>
<div class="example-buttons">
<a id="circleBtn" class="btn btn-orange" href="javascript:void(0)">Start</a>
</div>
</div>
<h3>Suffixed Properties</h3>
<p>Similar to the example on gradients with <a href="svg.html">SVG Plugin</a>, we can also animate the gradient positions, but make sure to always include the <code>%</code> suffix:</p>
<pre><code class="language-javascript">// gradient positions to middle
var closingGradient = KUTE.to('#gradient', {attr: {x1:'49%', x2:'49%', y1:'49%', y2:'49%'}});
// gradient positions rotated
var rotatingGradient = KUTE.to('#gradient', {attr: {x1:'49%', x2:'51%', y1:'51%', y2:'51%'}});
</code></pre>
<div class="featurettes">
<svg class="example-box-model example-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 615 615">
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color: #e91b1f; stop-opacity:1"></stop>
<stop offset="100%" style="stop-color: #2196F3; stop-opacity:1"></stop>
</linearGradient>
</defs>
<path fill="url(#gradient)" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531
c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
</svg>
<div class="example-buttons">
<a id="gradBtn" class="btn btn-pink" href="javascript:void(0)">Start</a>
</div>
</div>
<p>This plugin is quite handy and a great addition to the <a href="svg.html">SVG Plugin</a>.</p>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- highlighter -->
<script src="./assets/js/prism.js" type="text/javascript"></script>
<!--<script src="http://cdn.jsdelivr.net/kute.js/1.5.0/kute.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- KUTE.js core -->
<script src="./src/kute-attr.js"></script> <!-- KUTE.js Attributes Plugin -->
<script src="./assets/js/scripts.js"></script> <!-- global scripts stuff -->
<script src="./assets/js/attr.js"></script> <!-- css plugin examples -->
</body>
</html>

225
demo/css.html Normal file
View file

@ -0,0 +1,225 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if gte IE 10 | !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="The CSS Plugin for KUTE.js extends the core engine with additional box model, color, border-radius and other properties.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>KUTE.js CSS Plugin | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Synthax highlighter -->
<link href="./assets/css/prism.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group active">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li class="active"><a href="css.html">CSS Plugin </a></li>
<li><a href="svg.html">SVG Plugin </a></li>
<li><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li><a href="easing.html">Easing Functions</a></li>
<li><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>CSS Plugin</h2>
<p>The CSS Plugin extends the KUTE.js core engine and enables animation for additional CSS properties as mentioned in the <a href="examples.html">examples page</a>. The focus is on box model properties like <code>padding</code>, <code>margin</code> or <code>borderWidth</code>, as well as other types of properties like <code>borderRadius</code>, <code>borderColor</code>, <code>backgroundPosition</code>, <code>borderColor</code> or <code>clip</code>.</p>
<h3>Border Radius</h3>
<p>In the example below we are doing some animation on the <code>border-radius</code> property. The first box animates all corners, while the other boxes animate each corner at a time. A quick reminder, for radius properties KUTE.js supports <code>px</code>, <code>%</code> and text properties' units such as <code>em</code> or <code>rem</code>.</p>
<pre><code class="language-javascript">KUTE.to('selector1',{borderRadius:'100%'}).start();
KUTE.to('selector2',{borderTopLeftRadius:'100%'}).start();
KUTE.to('selector3',{borderTopRightRadius:'100%'}).start();
KUTE.to('selector4',{borderBottomLeftRadius:'100%'}).start();
KUTE.to('selector5',{borderBottomRightRadius:'100%'}).start();
</code></pre>
<p>And here is how it looks like:</p>
<div class="featurettes">
<div id="allRadius" class="example-item example-box bg-red">ALL</div>
<div id="tlRadius" class="example-item example-box bg-pink">TL</div>
<div id="trRadius" class="example-item example-box bg-olive">TR</div>
<div id="blRadius" class="example-item example-box bg-indigo">BL</div>
<div id="brRadius" class="example-item example-box bg-blue">BR</div>
<div class="example-buttons">
<a id="radiusBtn" class="btn btn-green" href="javascript:void(0)">Start</a>
</div>
</div>
<p>A quick important reminder here is that KUTE.js does not support shorthands for radius properties. Also early implementations by Mozilla's Firefox browser like <code>-moz-border-radius-topleft</code> are not supported because they were depracated with later versions. Download this example <a href='http://codepen.io/thednp/share/zip/VvpypW/'>here</a>.</p>
<h3>Box Model Properties</h3>
<p>The CSS Plugin allows KUTE.js to support almost all the box model properties, but for our example here we will focus mostly on margin and padding, as other properties such as <code>outlineWidth</code>, <code>minWidth</code> or <code>maxHeight</code> require a more complex context and we won't insist on them.</p>
<pre><code class="language-javascript">var tween1 = KUTE.to('selector1',{marginTop:200});
var tween2 = KUTE.to('selector1',{marginBottom:50});
var tween3 = KUTE.to('selector1',{padding:30});
var tween4 = KUTE.to('selector1',{margin:'5%'});
</code></pre>
<p>We're gonna chain these tweens and start the animation. You can download this example <a href='http://codepen.io/thednp/share/zip/xwqYbX/'>here</a>.</p>
<div id="boxModel" class="featurettes">
<div class="example-item example-box-model bg-lime" style="padding: 15px; font-size:26px">BOX<br>&nbsp;MODEL&nbsp;</div>
<div class="example-buttons">
<a class="btn btn-orange" href="#">Start</a>
</div>
</div>
<p>TIP: the <code>width</code> and <code>height</code> properties used together can be great for <code>scale</code> animation fallback on images for legacy browsers.</p>
<h3>Text Properties</h3>
<p>OK here we're gonna do a cool example for text properties. Basically the below code would work:</p>
<pre><code class="language-javascript">var tween1 = KUTE.to('selector1',{fontSize:'200%'});
var tween2 = KUTE.to('selector1',{lineHeight:24});
var tween3 = KUTE.to('selector1',{letterSpacing:50});
var tween3 = KUTE.to('selector1',{wordSpacing:50});
</code></pre>
<p>But our example will feature some more than just that. We're gonna animate each character of a given string, with a small delay. The heading will animate <code>fontSize</code> and <code>letterSpacing</code> properties for each character while the button will animate <code>fontSize</code> and <code>lineHeight</code> properties. Watch this:</p>
<div id="textProperties" class="featurettes" style="height: 152px">
<h1 class="example-item">Howdy!</h1>
<a href="javascript:void(0)" class="example-item btn btn-red">Button</a>
<div class="example-buttons">
<a class="btn btn-pink" href="javascript:void(0)">Start</a>
</div>
</div>
<p>TIP: this should also work in IE8 as a fallback for scale animation for text. It's not perfect, can be improved for sure, but if it's a must, this would do. Download this example <a href='http://codepen.io/thednp/share/zip/bVqLpb/'>here</a>.</p>
<h3>Color Properties</h3>
<p>The next example is about animating all border color properties, since the core engine already supports text <code>color</code> and <code>backgroundColor</code> properties. So check these lines for reference.</p>
<pre><code class="language-javascript">KUTE.to('selector1',{borderColor:'rgb(25,25,25)'}).start();
KUTE.to('selector1',{borderTopColor:'#069'}).start();
KUTE.to('selector1',{borderRightColor:'rgba(25,25,25,0.25)'}).start();
KUTE.to('selector1',{borderBottomColor:'#069'}).start();
KUTE.to('selector1',{borderLeftColor:'#069'}).start();
KUTE.to('selector1',{outlineColor:'#069'}).start();
</code></pre>
<p>Let's get some animation going. Download the example <a href='http://codepen.io/thednp/share/zip/OypvNR/'>here</a>.</p>
<div id="colBox" class="featurettes">
<div class="example-item example-box bg-olive" style="outline: #222 solid 5px; width: 135px; height: 135px; border:15px solid #9C27B0; line-height: 105px; font-size:30px">Colors</div>
<div class="example-buttons">
<a class="btn btn-blue" href="#">Start</a>
</div>
</div>
<p>A quick reminder: you can also use <code>RGB</code> or <code>RGBA</code>, but the last one is not supported on IE8 and it will fallback to <code>RGB</code>.</p>
<h3>Clip Property</h3>
<p>This property allows you to animate the rectangular shape of an element that is set to <code>position:absolute</code>. In CSS this property works like this <code>clip: rect(top,right,bottom,left)</code> forming a rectangular shape that masks an element making parts of it invisible.</p>
<pre><code class="language-javascript">KUTE.to('selector',{clip:[0,150,100,0]}).start();</code></pre>
<p>A quick example here could look like this:</p>
<div id="clip" class="featurettes" style="min-height: 190px">
<div class="example-item example-box bg-red" style="position: absolute; background: url('http://img.dummy-image-generator.com/people/dummy-250x250-Eye.jpg') center center no-repeat;"></div>
<div class="example-buttons">
<a class="btn btn-olive" href="#">Start</a>
</div>
</div>
<p><strong>Note</strong> that this would produce no effect for elements that have <code>overflow:visible</code> style rule. Download this example <a href='http://codepen.io/thednp/pen/NGpYmM/'>here</a>.</p>
<h3>Background Position</h3>
<p>Another property we can animate with KUTE.js is <code>backgroundPosition</code>. Quick example:</p>
<pre><code class="language-javascript">KUTE.to('selector1',{backgroundPosition:[0,50]}).start();</code></pre>
<p>A working example would look like this:</p>
<div id="bgPos" class="featurettes">
<div class="example-item example-box" style="background: url('http://img.dummy-image-generator.com/abstract/dummy-400x300-Rope.jpg') center center no-repeat;"></div>
<div class="example-buttons">
<a class="btn btn-lime" href="#">Start</a>
</div>
</div>
<p>Download this example <a href='http://codepen.io/thednp/share/zip/EVWEwJ/'>here</a>.</p>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- highlighter -->
<script src="./assets/js/prism.js" type="text/javascript"></script>
<!--<script src="http://cdn.jsdelivr.net/kute.js/0.9.2/kute.full.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- KUTE.js core -->
<script src="./src/kute-css.js"></script> <!-- KUTE.js CSS Plugin -->
<script src="./assets/js/scripts.js"></script> <!-- global scripts stuff -->
<script src="./assets/js/css.js"></script> <!-- css plugin examples -->
</body>
</html>

211
demo/easing.html Normal file
View file

@ -0,0 +1,211 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="A detailed API documentation on KUTE.js main methods, options and easing functions.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>KUTE.js Developer API | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Synthax highlighter -->
<link href="./assets/css/prism.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li><a href="css.html">CSS Plugin </a></li>
<li><a href="svg.html">SVG Plugin </a></li>
<li><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group active">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li class="active"><a href="easing.html">Easing Functions</a></li>
<li><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>Easing Functions</h2>
<p>The easing functions generally make animations closer to reality and completely eliminate the boring factor for a given context. The most simple example to understand what they do, think of gravity. Dropping an object from a given height, will start moving to the ground with accelerated speed. If the object has some sort of bounciness like a ball, it will jump back up and up again, till the gravity will eventually stick the object to the ground.</p>
<p>What scientists observed and put in theory houndreads of years ago, later the pioneers of scripting started to implement the laws of physics into digital animation and came up with this notion of easing to describe the progression of movement. If you care to dig into the concept, <a href="http://upshots.org/actionscript/jsas-understanding-easing" targt="_blank">here's an excellent resource</a> some developers recommend. I would also recommend <a href="https://medium.com/@sureshvselvaraj/animation-principles-in-ui-design-understanding-easing-bea05243fe3" target="_blank">this one</a> too.</p>
<h3>Core Functions</h3>
<p>Modern browsers that support <code>transition</code> can also make use of some generic easing functions via the CSS3 <code>transition-timing-function:ease-out</code> property, but in Javascript animation, we need some special functions. The popular <a href="robertpenner.com/easing/" target="_blank">Robert Penner's easing functions</a> set is the default set included with KUTE.js because it's the fastest set I know in terms of performance. Some functions may lack a bit of accuracy but they cover the most animation needs. Generally the easing functions' names are built with keywords that describe the type of easing, like <em>circular</em> or <em>exponential</em>, and also the type of progression <em>in</em> and/or <em>out</em>.</p>
<p>To use them, simply set a tween option like so <code>easing: KUTE.Easing.easingSinusoidalInOut</code> or simply <code>easing: 'easingSinusoidalInOut'</code>.</p>
<p><kbd>linear</kbd> is the default easing function and just as it sounds, it means that the animation has no acceleration or deceleration over time. While this one is basically boring, it's the fastest in all, and it's very useful when animating opacity or colors because we cannot really distinguish changes in speed for such cases, but mostly for movement.</p>
<p><kbd>curve</kbd> based functions are the next set of easings we are going to talk about. They are basically the same, the only difference is the number of multipliers applied (better think of it like the more weight an object has, the more acceleration):</p>
<ul>
<li><strong>Sinusoidal</strong> - multiplier of 1 (super light object, like a feather)</li>
<li><strong>Quadratic</strong> - multiplier of 2</li>
<li><strong>Cubic</strong> - multiplier of 3</li>
<li><strong>Quartic</strong> - multiplier of 4</li>
<li><strong>Quintic</strong> - multiplier of 5</li>
<li><strong>Circular</strong> - multiplier of 6</li>
<li><strong>Exponential</strong> - multiplier of 10 (super heavy object, like a truck)</li>
</ul>
<p>The In / Out explained:</p>
<ul>
<li><strong>In</strong> - means that the animation starts with very very low speed and gains acceleration over time, but when it reaches the maximum speed, animation stops. These functions are: <kbd>easingSinusoidalIn</kbd>, <kbd>easingQuadraticIn</kbd>,<kbd>easingCubicIn</kbd>, <kbd>easingQuarticIn</kbd>, <kbd>easingQuinticIn</kbd>, <kbd>easingCircularIn</kbd> and <kbd>easingExponentialIn</kbd>.</li>
<li><strong>Out</strong> - means that the animation starts with maximum speed and constantly decelerates over time until the animation stops. These functions are: <kbd>easingSinusoidalOut</kbd>, <kbd>easingQuadraticOut</kbd>, <kbd>easingCubicOut</kbd>, <kbd>easingQuarticOut</kbd>, <kbd>easingQuinticOut</kbd>, <kbd>easingCircularOut</kbd> and <kbd>easingExponentialOut</kbd>.</li>
<li><strong>InOut</strong> - means that the animation accelerates halfway until it reaches the maximum speed, then begins to decelerate until it stops. These functions are: <kbd>easingSinusoidalInOut</kbd>, <kbd>easingQuadraticInOut</kbd>, <kbd>easingCubicInOut</kbd>, <kbd>easingQuarticInOut</kbd>, <kbd>easingQuinticInOut</kbd>, <kbd>easingCircularInOut</kbd> and <kbd>easingExponentialInOut</kbd>.</li>
</ul>
<p><kbd>back</kbd> easing functions describe more complex animations (I would call them <em>reverse gravity</em> easings). They also come with <em>in</em> and/or <em>out</em> types of progression. </p>
<ul>
<li><kbd>easingBackIn</kbd> would be best described when you throw an object into the air with a small amount of physical power, it will move up decelerating until it stops, then will move to the ground with acceleration.</li>
<li><kbd>easingBackOut</kbd> would be best described as the previous function, but viewed in reverse mode.</li>
<li><kbd>easingBackInOut</kbd> is a combination of the other two.</li>
</ul>
<p><kbd>elasticity</kbd> easing functions describe the kind of animation where the object is elastic. With <em>in</em> and/or <em>out</em> as well. </p>
<ul>
<li><kbd>easingElasticOut</kbd> would be best described by the movement of a guitar string after being pinched, moving up and down, with decreasing frequency, until it stops.</li>
<li><kbd>easingElasticIn</kbd> would be best described as the above function but viewed in reverse mode.</li>
<li><kbd>easingElasticInOut</kbd> is simply a combination of the other two.</li>
</ul>
<p><kbd>gravity</kbd> based easing functions describe the kind of animation where the object has a certain degree of bounciness, like a ball. With <em>in</em> and/or <em>out</em> as well.</p>
<ul>
<li><kbd>easingBounceOut</kbd> looks just like a ball falling on the ground and start boucing up and down with decreasing frequency untill it stops.</li>
<li><kbd>easingBounceIn</kbd> looks like the previous viewed in reverse mode</li>
<li><kbd>easingBounceInOut</kbd> is a combination of the other two.</li>
</ul>
<h3>Cubic Bezier Functions</h3>
<p>While modern browsers support CSS3 <code>transition</code> with <code>transition-timing-function: cubic-bezier(0.1,0.5,0.8,0.5)</code>, in Javascript animation we need some specific functions to cover that kind of functionality. As mentioned in the <a href="features.html">features page</a>, we are using a modified version of the <a href="https://github.com/gre/bezier-easing" target="_blank">cubic-bezier</a> by Gaëtan Renaudeau. I believe this must be most accurate easing functions set.</p>
<p>You can use them either with <code>easing: KUTE.Ease.bezier(mX1, mY1, mX2, mY2)</code> or <code>easing: 'bezier(mX1, mY1, mX2, mY2)'</code>, where mX1, mY1, mX2, mY2 are <em>Float</em> values from 0 to 1. You can find the right values you need <a href="http://cubic-bezier.com/" target="_blank">right here</a>.</p>
<p>There is also a pack of presets, and the keywords look very similar if you have used jQuery.Easing plugin before:</p>
<ul>
<li>Equivalents of the browser's <strong>generic</strong> timing functions: <kbd>easeIn</kbd>, <kbd>easeOut</kbd> and <kbd>easeInOut</kbd></li>
<li><strong>Sinusoidal</strong> timing functions: <kbd>easeInSine</kbd>, <kbd>easeOutSine</kbd> and <kbd>easeInOutSine</kbd></li>
<li><strong>Quadratic</strong> timing functions: <kbd>easeInQuad</kbd>, <kbd>easeOutQuad</kbd> and <kbd>easeInOutQuad</kbd></li>
<li><strong>Cubic</strong> timing functions: <kbd>easeInCubic</kbd>, <kbd>easeOutCubic</kbd> and <kbd>easeInOutCubic</kbd></li>
<li><strong>Quartic</strong> timing functions: <kbd>easeInQuart</kbd>, <kbd>easeInQuart</kbd> and <kbd>easeInOutQuart</kbd></li>
<li><strong>Quintic</strong> timing functions: <kbd>easeInQuint</kbd>, <kbd>easeOutQuint</kbd> and <kbd>easeInOutQuint</kbd></li>
<li><strong>Exponential</strong> timing functions: <kbd>easeInExpo</kbd>, <kbd>easeOutExpo</kbd> and <kbd>easeInOutExpo</kbd></li>
<li><strong>Back</strong> timing functions: <kbd>easeInBack</kbd>, <kbd>easeOutBack</kbd> and <kbd>easeInOutBack</kbd></li>
<li><strong>Special slow motion</strong> timing functions look <a href="http://cubic-bezier.com/#0,.58,1,.3" target="_blank">like this</a>: <kbd>slowMo</kbd>, <kbd>slowMo1</kbd> and <kbd>slowMo2</kbd></li>
</ul>
<h3>Physics Based Functions</h3>
<p>KUTE.js also packs the <a href="http://dynamicsjs.com/" target="_blank">dynamics physics</a> easing functions by Michael Villar and I have to say these functions are amazing in terms of flexibility, control and performance. They allow you to control the friction, bounciness, frequency, elasticity, or multiple bezier points for your animations.</p>
<p>You can use them either with regular Javascript invocation as shown below and configure / visualize them on the <a href="http://dynamicsjs.com/" target="_blank">author's website</a>, while you can also use the pack of presets featuring mostly <kbd>bezier</kbd> based functions. Ok now, let's get to it:</p>
<ul>
<li><strong>spring</strong> function is basically an <strong>elastic</strong> type of easing that allows you to set <code>frequency:1-1000</code>, <code>friction:1-1000</code>, <code>anticipationSize:0-1000</code> (a kind of delay in miliseconds) and <code>anticipationStrength:0-1000</code> (a kind of a new curve to add to the function while waiting the anticipationSize). Usage: <code>easing: KUTE.Physics.spring({friction:100,frequency:600})</code>.</li>
<li><strong>bounce</strong> function is also an <strong>elastic</strong> easing function, but it works different than Robert Penner's version that's basically a <kbd>gravity</kbd> based function. This one here will always come back to the starting values. This function allows you to set <code>frequency:0-1000</code> and <code>friction:0-1000</code>. Usage: <code>easing: KUTE.Physics.bounce({friction:100,frequency:600})</code>.</li>
<li><strong>gravity</strong> function does what a ball dropped on the ground does, bounces until it stops. It allows you to set: <code>elasticity:1-1000</code> and <code>bounciness:0-1000</code>. Usage: <code>easing: KUTE.Physics.gravity({elasticity:100,bounciness:600})</code>.</li>
<li><strong>forceWithGravity</strong> function acts just like <code>gravity</code> except that the ball instead of being dropped it's thrown into the air. This allows you to set same options: <code>elasticity:1-1000</code> and <code>bounciness:0-1000</code>. Usage: <code>easing: KUTE.Physics.forceWithGravity({elasticity:100,bounciness:600})</code>.</li>
<li><strong>bezier</strong> easing function is a bit more complicated as it allows you to set multiple points of bezier curves. Usage: <code>easing: KUTE.Physics.bezier({points:POINTS_ARRAY_COMES HERE})</code>, again use the author's website, edit the bezier curve as you wish and copy paste the points array into this function. Here's how a basic <em>easeIn</em> looks like:
<pre><code class="language-javascript">// sample bezier based easing
easing: KUTE.Physics.bezier({points: [{"x":0,"y":0,"cp":[{"x":0.483,"y":0.445}]},{"x":1,"y":1,"cp":[{"x":0.009,"y":0.997}]}] });
</code></pre>
In other cases, the bezier can handle multiple points as well, basically unlimited:
<pre><code class="language-javascript">// multi point bezier easing
easing: KUTE.Physics.bezier({points: [{"x":0,"y":0,"cp":[{"x":0.387,"y":0.007}]},{"x":0.509,"y":0.48,"cp":[{"x":0.069,"y":0.874},{"x":0.928,"y":0.139}]},{"x":1,"y":1,"cp":[{"x":0.639,"y":0.988}]}] });
</code></pre>
</li>
</ul>
<p>The presets can be used both as a string <code>easing:'physicsIn'</code> or <code>easing:KUTE.Physics.physicsIn(friction:200)</code>. The list is:</p>
<ul>
<li><strong>curves</strong>: <kbd>physicsIn</kbd>, <kbd>physicsOut</kbd>, <kbd>physicsInOut</kbd> can do all multipliers (from sinusoidal to exponential) via the <code>friction</code> option;</li>
<li><strong>back</strong>: <kbd>physicsBackIn</kbd>, <kbd>physicsBackOut</kbd>, <kbd>physicsBackInOut</kbd> also benefit from the <code>friction</code> option.</li>
</ul>
</div>
<div class="content-wrap">
<ul id="share" class="nav">
<li>Share </li>
<li class="hidden-xs"><a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Facebook"><span class="ion-social-facebook-outline icon"></span></a></li>
<li class="hidden-xs"><a target="_blank" href="https://twitter.com/home?status=Spread the word about @kute.js animation engine by @thednp and download here http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Twitter"><span class="icon ion-social-twitter-outline"></span></a></a></li>
<li class="hidden-xs"><a target="_blank" href="https://plus.google.com/share?url=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Google+"><span class="icon ion-social-googleplus-outline"></span></a></li>
</ul>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- highlighter -->
<script src="./assets/js/prism.js" type="text/javascript"></script>
<!--<script src="http://cdn.jsdelivr.net/kute.js/1.0.0/kute.full.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- KUTE.js core -->
<script src="./assets/js/scripts.js"></script> <!-- some stuff -->
</body>
</html>

339
demo/extend.html Normal file
View file

@ -0,0 +1,339 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="A quick start guide for KUTE.js, CDN sources, NPM.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>Extending KUTE.js | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Synthax highlighter -->
<link href="./assets/css/prism.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li><a href="css.html">CSS Plugin </a></li>
<li><a href="svg.html">SVG Plugin </a></li>
<li><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group active">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li><a href="easing.html">Easing Functions</a></li>
<li class="active"><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>Extend Guide</h2>
<p>KUTE.js is a very flexible animation engine that allows you to extend beyond measure. In this tutorial we'll dig into what's best to do to extend/customize the functionality of KUTE.js core, plugins and features.</p>
<h3>Basic Plugin Template</h3>
<p>The best way to extend, no matter what you would like to achieve is to use a specific closure, here's an example:</p>
<pre><code class="language-javascript">/* KUTE.js - The Light Tweening Engine
* package - pluginName
* desc - what your plugin does
* by yourNickname aka YOUR NAME
* Licensed under MIT-License
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
var KUTE = require("./kute.js");
module.exports = factory(KUTE);
} else if ( typeof window.KUTE !== 'undefined' ) {
factory(KUTE);
} else {
throw new Error("pluginName require KUTE.js.");
}
}( function (KUTE) {
// your code goes here
// in this function body
// the plugin returns this
return this;
}));
</code></pre>
<p>As suggested in the above template, your function body could be written with one or more of the examples below.</p>
<h3>Extend Tween Control</h3>
<p>In some cases, you may want to extend with additional tween control methods, so before you do that, make sure to check <code>KUTE.Tween</code> function to get the internal references notation:</p>
<pre><code class="language-javascript">//add a reference to KUTE object
var K = window.KUTE;
// let's add a timescale method
K.Tween.prototype.timescale = function(factor){
this._dr *= factor; // this._dr is the internal tween duration
return this;
}
// or let's add a reverse method
K.Tween.prototype.reverse = function(){
for (var p in this._vE) {
var tmp = this._vSR[p]; // we cache this object first
this._vSR[p] = this._vE[p]; // this._vSR is the internal valuesStartRepeat object
this._vE[p] = tmp; // this._vE is the internal valuesEnd object
this._vS[p] = this._vSR[p]; // this._vSR is the internal valuesStart object
}
return this;
}
// go back in time
K.Tween.prototype.seek = function (time) {
this._sT -= time; // this._sT is the startTime
return this;
};
// how about a restart method
K.Tween.prototype.restart = function(){
if (this.playing) {
this.stop();
this.start();
}
return this;
}
</code></pre>
<p>For some reasons these methods aren't included into the core/plugins by default, but let you decide what you need and how to customize the animation engine for your very secific need.</p>
<h3>Support For Additional CSS Properties</h3>
<p>KUTE.js core engine and plugins cover what I consider to be most essential for animation, but you may have a different opinion. In case you may want to know how to animate properties that are not currently supported, stick to this guide and you'll master it real quick, it's very easy.</p>
<p>We need basically 3 functions:</p>
<ul>
<li><code>KUTE.prS['propertyName']</code> a <strong>prepareStart</strong> function to get the current value of the property required for the <code>.to()</code> method;</li>
<li><code>KUTE.pp['propertyName']</code> a <strong>processProperty</strong> function to process the user value / current value to have it ready to tween;</li>
<li><code>KUTE.dom['propertyName']</code> a <strong>domUpdate</strong> function that will update the property value into the DOM;</li>
<li><strong>optional</strong> a function that will work as an utility for your value processing.</li>
</ul>
<p>So let's add support for <kbd class="bg-olive">boxShadow</kbd>! It should be a medium difficulty guide most developers can follow and the purpose of this guide is to showcase how easy it actually is to extend KUTE.js. So grab the above template and let's break it down to pieces:</p>
<pre><code class="language-javascript">// add a reference to KUTE object
var K = window.KUTE;
// filter unsupported browsers
if (!('boxShadow' in document.body.style)) {return;}
// the preffixed boxShadow property, mostly for legacy browsers
// maybe the browser is supporting the property with its vendor preffix
// box-shadow: none|h-shadow v-shadow blur spread color |inset|initial|inherit;
var _boxShadow = K.property('boxShadow'); // note we're using the KUTE.property() autopreffix utility
var colRegEx = /(\s?(?:#(?:[\da-f]{3}){1,2}|rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\))\s?)/gi; // a full RegEx for color strings
</code></pre>
<p>Now we have access to the KUTE object, prototypes and it's utility functions, let's write a <code>prepareStart</code> function that will read the current <code>boxShadow</code> value:</p>
<pre><code class="language-javascript">// for the .to() method, you need to prepareStart the boxShadow property
// which means you need to read the current computed value
K.prS['boxShadow'] = function(element,property,value){
var cssBoxShadow = K.gCS(element,'boxShadow'); // where K.gCS() is an accurate getComputedStyle() core method
return /^none$|^initial$|^inherit$|^inset$/.test(cssBoxShadow) ? '0px 0px 0px 0px rgb(0,0,0)' : cssBoxShadow;
}
// note that in some cases the window.getComputedStyle(element,null) can be more accurate
// we are using a hybrid function that's trying to get proper colors and other stuff that
// some legacy browsers lack in this matter
// also to read the current value of an attribute, replace first line of the above function body with this
// var attrValue = element.getAttribute(property);
// and return the value or a default value, mostly rgb(0,0,0) for colors or 0 for other types
</code></pre>
<p>Next we'll need to write a <code>processProperty</code> function that will prepare the property value and build an Object or Array of values ready to tween. This function also registers the <code>K.dom['boxShadow']</code> function into the KUTE object, and this way we avoid filling the main object with unnecessary functions, just to keep performance tight.</p>
<pre><code class="language-javascript">// the processProperty for boxShadow
// registers the K.dom['boxShadow'] function
// returns an array of 6 values in the following format
// [horizontal, vertical, blur, spread, color: {r:0,g:0,b:0}, inset]
K.pp['boxShadow'] = function(property,value,element){
// the DOM update function for boxShadow registers here
// we only enqueue it if the boxShadow property is used to tween
if ( !('boxShadow' in K.dom) ) {
K.dom['boxShadow'] = function(w,p,v) {
// let's start with the numbers | set unit | also determine inset
var numbers = [], unit = 'px', // the unit is always px
inset = w._vS[p][5] !== 'none' || w._vE[p][5] !== 'none' ? ' inset' : false;
for (var i=0; i&lt;4; i++){
numbers.push( (w._vS[p][i] + (w._vE[p][i] - w._vS[p][i]) * v ) + unit);
}
// now we handle the color
var color, _color = {};
for (var c in w._vE[p][4]) {
_color[c] = parseInt(w._vS[p][4][c] + (w._vE[p][4][c] - w._vS[p][4][c]) * v )||0;
}
color = 'rgb(' + _color.r + ',' + _color.g + ',' + _color.b + ') ';
// last piece of the puzzle, the DOM update
w._el.style[_boxShadow] = inset ? color + numbers.join(' ') + inset : color + numbers.join(' ');
};
}
// processProperty for boxShadow, builds basic structure with ready to tween values
if (typeof value === 'string'){
var color, inset = false;
// make sure to always have the inset last if possible
inset = /inset/.test(value) ? 'inset' : inset;
value = /inset/.test(value) ? value.replace(/(\s+inset|inset+\s)/g,'') : value;
// also getComputedStyle often returns color first "rgb(0, 0, 0) 15px 15px 6px 0px inset"
color = value.match(colRegEx);
value = value.replace(color[0],'').split(' ').concat([color[0].replace(/\s/g,'')],[inset]);
value = K.processBoxShadowArray(value);
} else if (value instanceof Array){
value = K.processBoxShadowArray(value);
}
return value;
}
</code></pre>
<p>Notice we've used an utility function that fixes the Array values and makes sure the structure is right.</p>
<pre><code class="language-javascript">// utility function to process values accordingly
// numbers must be floats/integers and color must be rgb object
K.processBoxShadowArray = function(shadow){
var newShadow, i;
// properly process the shadow based on amount of values
if (shadow.length === 3) { // [h-shadow, v-shadow, color]
newShadow = [shadow[0], shadow[1], 0, 0, shadow[2], 'none'];
} else if (shadow.length === 4) { // [h-shadow, v-shadow, color, inset] | [h-shadow, v-shadow, blur, color]
newShadow = /inset|none/.test(shadow[3]) ? [shadow[0], shadow[1], 0, 0, shadow[2], shadow[3]] : [shadow[0], shadow[1], shadow[2], 0, shadow[3], 'none'];
} else if (shadow.length === 5) { // [h-shadow, v-shadow, blur, color, inset] | [h-shadow, v-shadow, blur, spread, color]
newShadow = /inset|none/.test(shadow[4]) ? [shadow[0], shadow[1], shadow[2], 0, shadow[3], shadow[4]] : [shadow[0], shadow[1], shadow[2], shadow[3], shadow[4], 'none'];
} else if (shadow.length === 6) { // ideal [h-shadow, v-shadow, blur, spread, color, inset]
newShadow = shadow;
}
// make sure the numbers are ready to tween
for (i=0;i&lt;4;i++){
newShadow[i] = parseFloat(newShadow[i]);
}
// make sure color is an rgb object
newShadow[4] = K.truC(newShadow[4]); // where K.truC() is a core method to return the true color in rgb object format
return newShadow;
}
</code></pre>
<p>And now, we are ready to tween both <code>.to()</code> and <code>.fromTo()</code> methods:</p>
<pre><code class="language-javascript">// tween to a string value
var myBSTween1 = KUTE.to('selector', {boxShadow: '15px 25px #069'}).start();
// or a fromTo with string and array, hex and rgb
var myBSTween2 = KUTE.fromTo('selector', {boxShadow: [15, 25, 0, '#069']}, {boxShadow: '0px 0px rgb(0,0,0)'}).start();
// maybe you want to animate an inset boxShadow?
var myBSTween3 = KUTE.fromTo('selector', {boxShadow: [5, 5, 0, '#069', 'inset']}, {boxShadow: '0px 0px rgb(0,0,0)'}).start();
</code></pre>
<p>You are now ready to demo!</p>
<div id="boxShadow" class="featurettes">
<div class="example-item example-box bg-lime"></div>
<div class="example-buttons">
<a class="btn btn-pink" href="javascript:void(0)">Start</a>
</div>
</div>
<p>This plugin should be compatible with IE9+ and anything that supports <code>boxShadow</code> CSS property. As you can see it can handle pretty much anything you throw at it, but it requires at least 3 values: h-shadow, v-shadow, and color because Safari doesn't work without a color. Also this plugin won't be able to handle multiple instances of <code>boxShadow</code> for same element, because the lack of support on legacy browsers, also the color cannot be RGBA, but hey, it supports both outline and inset shadows and you can fork it anyway to your liking.</p>
<p>If you liked this tutorial, feel free to write your own, a great idea would be for <code>textShadow</code>, it's very similar to the above example plugin.</p>
<h3>Utility Methods</h3>
<ul>
<li><kbd class="bg-lime">KUTE.selector(selector,multi)</kbd> is the selector utility that uses <code>getElementById</code> or <code>querySelector</code> when <code>multi</code> argument is <strong>null</strong> or <strong>false</strong>, BUT when <strong>true</strong>, <code>querySelectorAll</code> is used and returns a HTMLCollection object.</li>
<li><kbd class="bg-lime">KUTE.property(propertyName)</kbd> is the <strong>autoPrefix</strong> function that returns the property with the right vendor prefix, but only if required; on legacy browsers that don't support the property, the function returns <strong>undefinedPropertyName</strong> and that would be an easy way to detect support for that property on most legacy browsers: <pre><code class="language-javascript">if (/undefined/.test(KUTE.property('propertyName')) ) { /* legacy browsers */ } else { /* modern browsers */ }</code></pre></li>
<li><kbd class="bg-lime">KUTE.getPrefix()</kbd> returns a vendor preffix even if the browser supports a specific preffixed property or not.</li>
<li><kbd class="bg-lime">KUTE.gCS(element,property)</kbd> a hybrid <code>getComputedStyle</code> function to get the current value of the property required for the <code>.to()</code> method; it actually checks in <code>element.style</code>, <code>element.currentStyle</code> and <code>window.getComputedStyle(element,null)</code> to make sure it won't miss the property value;</li>
<li><kbd class="bg-lime">KUTE.gIS()</kbd> a <code>getInlineStyle</code> function to read the current inline style, very useful for transform, because decomposing a computed <strong>matrix</strong> would require a ton lot more code;</li>
<li><kbd class="bg-lime">KUTE.truD(value)</kbd> a function that accepts String and Number and returns a <code>{v: 150, u: 'px'}</code> object for any box model or a single numeric value based property and make it ready to tween.</li>
<li><kbd class="bg-lime">KUTE.truC(color)</kbd> a function that returns an <code>{r: 150, g: 150, b: 0}</code> color object ready to tween; if the color value is a <a href="http://www.w3schools.com/colors/colors_names.asp" target="_blank">web safe color</a>, the IE9+ browsers will be able to return the rgb object we need.</li>
<li><kbd class="bg-lime">KUTE.htr(hex)</kbd> a function that accepts HEX formatted colors and returns an <code>{r: 150, g: 150, b: 0}</code> color object;</li>
<li><kbd class="bg-lime">KUTE.rth(rgb)</kbd> a function that accepts RGBa formatted colors and returns a <code>#006699</code> color string;</li>
</ul>
<ul id="share" class="nav">
<li>Share </li>
<li class="hidden-xs"><a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Facebook"><span class="ion-social-facebook-outline icon"></span></a></li>
<li class="hidden-xs"><a target="_blank" href="https://twitter.com/home?status=Spread the word about @kute.js animation engine by @thednp and download here http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Twitter"><span class="icon ion-social-twitter-outline"></span></a></a></li>
<li class="hidden-xs"><a target="_blank" href="https://plus.google.com/share?url=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Google+"><span class="icon ion-social-googleplus-outline"></span></a></li>
</ul>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- highlighter -->
<script src="./assets/js/prism.js" type="text/javascript"></script>
<!--<script src="http://cdn.jsdelivr.net/kute.js/1.0.0/kute.full.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- KUTE.js core -->
<script src="./assets/js/scripts.js"></script> <!-- some stuff -->
<script src="./assets/js/kute-bs.js"></script> <!-- the boxShadow plugin -->
<script src="./assets/js/extend.js"></script> <!-- examples with boxShadow plugin -->
</body>
</html>

224
demo/properties.html Normal file
View file

@ -0,0 +1,224 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="The complete list of supported CSS properties, presentation attributes and other DOM animations for KUTE.js.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>KUTE.js Supported Properties | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group active"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li class="active"><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li><a href="css.html">CSS Plugin </a></li>
<li><a href="svg.html">SVG Plugin </a></li>
<li><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li><a href="easing.html">Easing Functions</a></li>
<li><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>Supported Properties</h2>
<p>KUTE.js covers all animation needs by itself for <code>transform</code> properties, <code>scroll</code> for window or a given element, colors. Note: not all browsers support <a href="http://caniuse.com/#feat=transforms2d" target="_blank">2D transforms</a> or <a href="http://caniuse.com/#feat=transforms3d" target="_blank">3D transforms</a>. With the help of some plugins it also covers SVG specific properties, presentation attributes, or other CSS properties like <code>border-radius</code>, <code>clip</code>, <code>backgroundPosition</code> and more box model properties.</p>
<p>Starting with KUTE.js version 1.5.0 the supported properties are split among some plugins to have a lighter core engine that gives more power to the developer. Due to it's modular coding, KUTE.js makes it easy to add support for additional properties, so check out the guide on <a href="extend.html">how to extend</a>.</p>
<p>All common measurement units are supported: <code>px</code> and <code>%</code> for translations and box-model properties, or <code>deg</code> and <code>rad</code> for rotations and skews, while <code>clip</code> only supports <code>px</code>. Other properties such as <code>opacity</code>, <code>scale</code> or <code>scroll</code> are unitless, and <code>background-position</code> always uses <code>%</code> as measurement unit. As for the text properties you can use <code>px</code>, <code>em</code>, <code>rem</code>, <code>vh</code> and <code>vw</code>. Be sure to <a href="http://caniuse.com/#feat=viewport-units" target="_blank">check</a> what your browsers support in terms of measurement unit.</p>
<h3>Opacity</h3>
<p>In most cases, the best animation possible is the <code class="bg-blue">opacity</code>, for performance, aesthetics and maybe more other reasons such as avoiding unwanted layout changes. KUTE.js also covers IE8 here with the help of proprietary synthax <code>filter: alpha(opacity=0)</code>. Also, opacity can be used for instance on legacy browsers that don't support <code>RGBA</code> colors. Eg. <code>opacity:0.5</code> will make an element semitransparent.</p>
<h3>2D Transform Properties</h3>
<p>The core engine supports all 2D transform properties except <code>matrix</code>.</p>
<ul>
<li><kbd class="bg-blue">translate</kbd> property can be used for horizontal and / or vertical movement. EG. <code>translate:150</code> to translate an element 150px to the right or <code>translate:[-150,200]</code> to move the element to the left by 150px and to bottom by 200px. Supported on IE9.</li>
<li><kbd class="bg-blue">rotate</kbd> is a property used to rotate an element on the Z axis or the plain document. Eg. <code>rotate:250</code> will rotate an element clockwise by 250 degrees. Supported on IE9.</li>
<li><kbd class="bg-blue">skewX</kbd> is a property used to apply a skew transformation on the X axis. Eg. <code>skewX:25</code> will skew an element by 25 degrees. Supported on IE9.</li>
<li><kbd class="bg-blue">skewY</kbd> is a property used to apply a skew transformation on the Y axis. Eg. <code>skewY:25</code> will skew an element by 25 degrees. Supported on IE9.</li>
<li><kbd class="bg-blue">scale</kbd> is a property used to apply a size transformation. Eg. <code>scale:2</code> will enlarge an element by a degree of 2. Supported on IE9.</li>
<li><kbd class="bg-red">matrix</kbd> property is not supported.</li>
</ul>
<h3>3D Transform Properties</h3>
<p>The core engine supports all 3D transform properties except <code>matrix3d</code> and <code>rotate3d</code>.</p>
<ul>
<li><kbd class="bg-blue">translateX</kbd> property is for horizontal movement. EG. <code>translateX:150</code> to translate an element 150px to the right. Modern browsers only.</li>
<li><kbd class="bg-blue">translateY</kbd> property is for vertical movement. EG. <code>translateY:-250</code> to translate an element 250px towards the top. Modern browsers only.</li>
<li><kbd class="bg-blue">translateZ</kbd> property is for movement on the Z axis in a given 3D field. EG. <code>translateZ:-250</code> to translate an element 250px to it's back, making it smaller. Modern browsers only and requires a <code>perspective</code> tween option to be used; the smaller perspective value, the deeper translation.</li>
<li><kbd class="bg-blue">translate3d</kbd> property is for movement on all the axis in a given 3D field. EG. <code>translate3d:[-150,200,150]</code> to translate an element 150px to the left, 200px to the bottom and 150px closer to the viewer, making it larger. Modern browsers only and also requires using a <code>perspective</code> tween option.</li>
<li><kbd class="bg-blue">rotateX</kbd> property rotates an element on the X axis in a given 3D field. Eg. <code>rotateX:250</code> will rotate an element clockwise by 250 degrees. Modern browsers only and requires perspective.</li>
<li><kbd class="bg-blue">rotateY</kbd> property rotates an element on the Y axis in a given 3D field. Eg. <code>rotateY:-150</code> will rotate an element counter-clockwise by 150 degrees. Modern browsers only and also requires perspective.</li>
<li><kbd class="bg-blue">rotateZ</kbd> property rotates an element on the Z axis and is the equivalent of the 2D rotation. Eg. <code>rotateZ:-150</code> will rotate an element counter-clockwise by 150 degrees. Modern browsers only and doesn't require perspective.</li>
<li><kbd class="bg-red">rotate3d</kbd> and <kbd class="bg-red">matrix3d</kbd> properties are not supported.</li>
</ul>
<h3>Box Model Properties</h3>
<p>The core engine supports <code>width</code>, <code>height</code>, <code>left</code> and <code>top</code> while the <a href="css.html">CSS Plugin</a> adds support for all other box-model properties.</p>
<ul>
<li><kbd class="bg-blue">left</kbd>, <kbd class="bg-blue">top</kbd>, <kbd class="bg-olive">right</kbd> and <kbd class="bg-olive">bottom</kbd> are <code>position</code> based properties for movement on vertical and / or horizontal axis. These properties require that the element to animate uses <code>position: absolute/relative</code> styling as well as it's parent element requires <code>position:relative</code>. These properties can be used as fallback for browsers with no support for <code>translate</code> properties such as IE8.</li>
<li><kbd class="bg-blue">width</kbd>, <kbd class="bg-blue">height</kbd>, <kbd class="bg-olive">minWidth</kbd>, <kbd class="bg-olive">minHeight</kbd>, <kbd class="bg-olive">maxWidth</kbd>, <kbd class="bg-olive">maxHeight</kbd> are properties that allow you to animate the size of an element on horizontal and / or vertical axis. These properties can be used on images as fallback for <code>scale</code> on IE8 again, as well as for other purposes.</li>
<li><kbd class="bg-olive">padding</kbd>, <kbd class="bg-olive">margin</kbd>, <kbd class="bg-olive">paddingTop</kbd>, <kbd class="bg-olive">paddingBottom</kbd>, <kbd class="bg-olive">paddingLeft</kbd>, <kbd class="bg-olive">paddingRight</kbd>, <kbd class="bg-olive">marginTop</kbd>, <kbd class="bg-olive">marginBottom</kbd>, <kbd class="bg-olive">marginLeft</kbd> and <kbd class="bg-olive">marginRight</kbd> are properties that allow you to animate the spacing of an element inside (via padding) and outside (via margin). Shorthand notations such as <code>margin: "20px 50px"</code> or any other type are not supported.</li>
<li><kbd class="bg-olive">borderWidth</kbd>, <kbd class="bg-olive">borderTopWidth</kbd>, <kbd class="bg-olive">borderRightWidth</kbd>, <kbd class="bg-olive">borderBottomWidth</kbd> are <kbd class="bg-olive">borderLeftWidth</kbd> are properties that allow you to animate the border of an element either on all sides at once or each side separatelly. Shorthand notations are not supported.</li>
<li><kbd class="bg-olive">outlineWidth</kbd> property allows you to animate the <code>outline-width</code> of an element.</li>
</ul>
<p><strong>Remember</strong>: these properties are <strong>layout modifiers</strong> that may force repaint of the entire DOM, drastically affecting performance on lower end and mobile devices. They also trigger <code>resize</code> event that may cause crashes on old browsers such as IE8 when using handlers bound on <code>resize</code>, so use with caution.</p>
<h3>Border Radius</h3>
<p>The <a href="css.html">CSS Plugin</a> covers all the radius properties while making sure to use the proper vendor prefix if a slightly older browser version is detected.</p>
<ul>
<li><kbd class="bg-olive">borderRadius</kbd> allows you to animate the <code>border-radius</code> on all corners for a given element.</li>
<li><kbd class="bg-olive">borderTopLeftRadius</kbd> allows you to animate the <code>border-top-left-radius</code> for a given element.</li>
<li><kbd class="bg-olive">borderTopRightRadius</kbd> allows you to animate the <code>border-top-right-radius</code> for a given element.</li>
<li><kbd class="bg-olive">borderBottomLeftRadius</kbd> allows you to animate the <code>border-bottom-left-radius</code>for a given element.</li>
<li><kbd class="bg-olive">borderBottomRightRadius</kbd> allows you to animate the <code>border-bottom-right-radius</code>for a given element.</li>
</ul>
<p>For all radius properties above <code>borderRadius:20</code> or <code>borderTopLeftRadius:'25%'</code> will do. In the first case <code>px</code> is the default measurement unit used, while in the second we require using <code>%</code> unit which is relative to the element's size.</p>
<p><strong>Remember</strong>: shorthands for <code>border-radius</code> are not supported. Also KUTE.js does not cover early implementations by Mozilla Firefox (Eg. <code>-moz-border-radius-topleft</code>) as they were deprecated with later versions.</p>
<h3>Color Properties</h3>
<p>The core engine only supports <code>color</code> and <code>backgroundColor</code>, but the <a href="css.html">CSS Plugin</a> covers all the others. KUTE.js currently supports values such as <code>HEX</code>, <code>RGB</code> and <code>RGBA</code> for all color properties, but IE8 does not support <code>RGBA</code> and always uses <code>RGB</code> when detected, otherwise will produce no effect. There is also a tween option <code>keepHex:true</code> to convert the color format. Eg. <code>color: '#ff0000'</code> or <code>backgroundColor: 'rgb(202,150,20)'</code> or <code>borderColor: 'rgba(250,100,20,0.5)'</code>. The IE9+ browsers should also work with <a href="http://www.w3schools.com/colors/colors_names.asp" target="_blank">web safe colors</a>, eg. <code>color: 'red'</code>. </p>
<ul>
<li><kbd class="bg-blue">color</kbd> allows you to animate the color for a given text element.</li>
<li><kbd class="bg-blue">backgroundColor</kbd> allows you to animate the <code>background-color</code> for a given element.</li>
<li><kbd class="bg-olive">outlineColor</kbd> allows you to animate the <code>outline-color</code> for a given element.</li>
<li><kbd class="bg-olive">borderColor</kbd> allows you to animate the <code>border-color</code> on all sides for a given element.</li>
<li><kbd class="bg-olive">borderTopColor</kbd>, <kbd class="bg-olive">borderRightColor</kbd>, <kbd class="bg-olive">borderBottomColor</kbd> and <kbd class="bg-olive">borderLeftColor</kbd> properties allow you to animate the color of the border on each side of a given element.</li>
</ul>
<p><strong>Remember</strong>: shorthands for <code>borderColor</code> property are not supported.</p>
<h3>SVG Properties</h3>
<p>The <a href="svg.html">SVG Plugin</a> can animate the <code>d</code> attribute of a given <code>&lt;path&gt;</code> or <code>&lt;glyph&gt;</code> element with the tween property called <kbd class="bg-olive">path</kbd>. The animation effect is widelly known as morph SVG and implemented in various scripts, but the KUTE.js implementation is similar to <a href="http://bl.ocks.org/mbostock/3081153" target="_blank">the D3.js examples</a> for wider usability.</p>
<p>Further more, the SVG Plugin can animate the stroke in a way that you probably know as <code>drawSVG</code>. KUTE.js implements it as <kbd class="bg-olive">draw</kbd> tween property that deals with the well known CSS properties: <kbd>strokeDasharray</kbd> and <kbd>strokeDashoffset</kbd>.
<p>The SVG Plugin also manages animation for most useful CSS properties that are specific to SVG elements, since SMIL animations tend to go extinct, this plugin can get quite useful.</p>
<ul>
<li><kbd class="bg-olive">strokeWidth</kbd> allows you to animate the <code>stroke-width</code> for a given SVG element.</li>
<li><kbd class="bg-olive">strokeOpacity</kbd> allows you to animate the <code>stroke-opacity</code> for a given SVG element.</li>
<li><kbd class="bg-olive">fillOpacity</kbd> allows you to animate the <code>fill-opacity</code> for a given SVG element.</li>
<li><kbd class="bg-olive">stopOpacity</kbd> allows you to animate the <code>stop-opacity</code> for a given gradient SVG element.</li>
<li><kbd class="bg-olive">fill</kbd> allows you to animate the <code>fill</code> color property for a given SVG element.</li>
<li><kbd class="bg-olive">stroke</kbd> allows you to animate the <code>stroke</code> color for a given SVG element.</li>
<li><kbd class="bg-olive">stopColor</kbd> allows you to animate the <code>stop-color</code> for a given gradient SVG element.</li>
</ul>
<h3>Presentation Attributes</h3>
<p>The <a href="attr.html">Attributes Plugin</a> can animate any numerical presentation attribute such as <kbd class="bg-olive">width</kbd>, <kbd class="bg-olive">cx</kbd> or <kbd class="bg-olive">stop-opacity</kbd>, but the values can be also suffixed: <code>150px</code> or <code>50%</code>, and for that you must always provide a string value that include the measurement unit, and that, of course, depends on the attribute. This plugin can be a great addition to the above SVG Plugin for specific gradient attributes or specific geometric shapes' attributes.</p>
<p>The synthax is slightly different to make sure we don't mess up with CSS properties that have the same name because the presentation attribute may be a unitless attribute while the CSS property might require a suffix (%,px,etc). For instance <code>KUTE.to('selector', {attr:{width:150}})</code> is clearly different from <code>KUTE.to('selector', {width:150})</code> which is the the CSS property with the same name.</p>
<h3>Text Properties</h3>
<p>The <a href="css.html">CSS Plugin</a> also cover the text properties, and these can be combinated with each other when applied to text elements (paragraphs, headings) as animation fallback for <code>scale</code> on browsers that don't support <code>transform</code> at all. Yes, IE8 and other legacy browsers.</p>
<ul>
<li><kbd class="bg-olive">fontSize</kbd> allows you to animate the <code>font-size</code> for a given element.</li>
<li><kbd class="bg-olive">lineHeight</kbd> allows you to animate the <code>line-height</code> for a given element.</li>
<li><kbd class="bg-olive">letterSpacing</kbd> allows you to animate the <code>letter-spacing</code> for a given element.</li>
<li><kbd class="bg-olive">wordSpacing</kbd> allows you to animate the <code>word-spacing</code> for a given element.</li>
</ul>
<p><strong>Remember</strong>: these properties are also <strong>layout modifiers</strong>.</p>
<h3>Scroll Animation</h3>
<p>KUTE.js core engine currently supports only vertical <kbd class="bg-blue">scroll</kbd> for both the window and a given element that's scrollable (when <code>scrollHeight</code> is higher than <code>offsetHeight</code>). Both <code>scroll: 150</code> or <code>scrollTop: 150</code> notations will do. When animating scroll, KUTE.js will disable all scroll and swipe handlers to prevent animation bubbles as well as scroll bottlenecks.</p>
<h3>Other properties</h3>
<ul>
<li><kbd class="bg-olive">clip</kbd> allows you to animate the <code>clip</code> property for a given element. Only rect is supported. Eg. <code>clip:[250,200,300,0]</code>. See <a href="http://www.w3.org/TR/CSS2/visufx.html#propdef-clip" target="_blank">spec</a> for details.</li>
<li><kbd class="bg-olive">backgroundPosition</kbd> allows you to animate the <code>background-position</code> for a given element that uses a background image. It only uses % as measurement unit. Eg. <code>backgroundPosition:[50,20]</code></li>
</ul>
<h3>Legend</h3>
<ul>
<li><kbd class="bg-blue">core</kbd> - the property/properties are supported by core animation engine.</li>
<li><kbd class="bg-olive">plugin</kbd> - the property/properties are supported by plugins.</li>
<li><kbd class="bg-red">unsupported</kbd> - the property/properties are NOT supported by core and/or plugins.</li>
</ul>
<h3>Did We Miss Any Important Property?</h3>
<p>Make sure you go to <a href="https://github.com/thednp/kute.js/issues" target="_blank">the issues tracker</a> and report the missing property ASAP.</p>
</div>
<div class="content-wrap">
<ul id="share" class="nav">
<li>Share </li>
<li class="hidden-xs"><a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Facebook"><span class="ion-social-facebook-outline icon"></span></a></li>
<li class="hidden-xs"><a target="_blank" href="https://twitter.com/home?status=Spread the word about @kute.js animation engine by @thednp and download here http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Twitter"><span class="icon ion-social-twitter-outline"></span></a></a></li>
<li class="hidden-xs"><a target="_blank" href="https://plus.google.com/share?url=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Google+"><span class="icon ion-social-googleplus-outline"></span></a></li>
</ul>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!--<script src="http://cdn.jsdelivr.net/kute.js/0.9.2/kute.full.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- some stuff -->
<script src="./assets/js/scripts.js"></script> <!-- some stuff -->
</body>
</html>

75
demo/src/kute-attr.js Normal file
View file

@ -0,0 +1,75 @@
/* KUTE.js - The Light Tweening Engine
* package - Attributes Plugin
* desc - enables animation for any numeric presentation attribute
* by dnp_theme
* Licensed under MIT-License
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
// We assume, that require() is sync.
var KUTE = require("./kute.js");
// Export the modified one. Not really required, but convenient.
module.exports = factory(KUTE);
} else if ( typeof window.KUTE !== 'undefined' ) {
// Browser globals
factory(KUTE);
} else {
throw new Error("Attributes Plugin require KUTE.js.");
}
}( function (KUTE) {
'use strict';
var K = window.KUTE;
// get current attribute value
K.gCA = function(e,a){
return e.getAttribute(a);
}
K.prS['attr'] = function(el,p,v){
var f = {};
for (var a in v){
f[a.replace(/_+[a-z]+/,'')] = K.gCA(el,a.replace(/_+[a-z]+/,''));
}
return f;
};
// register the render attributes object
if (!('attr' in K.dom)) {
K.dom.attr = function(w,p,v){
for ( var o in w._vE[p] ){
K.dom.attr.prototype[o](w,o,v);
}
};
}
var ra = K.dom.attr.prototype;
// process attributes object K.pp.attr(t[x])
// and also register their render functions
K.pp['attr'] = function(a,o){
var ats = {}, p;
for ( p in o ) {
if ( /%|px/.test(o[p]) ) {
var u = K.truD(o[p]).u, s = /%/.test(u) ? '_percent' : '_'+u;
if (!(p+s in ra)) {
ra[p+s] = function(w,p,v){
w._el.setAttribute(p.replace(s,''), (w._vS.attr[p].v + (w._vE.attr[p].v - w._vS.attr[p].v) * v) + w._vE.attr[p].u);
}
}
ats[p+s] = K.truD(o[p]);
} else {
if (!(p in ra)) {
ra[p] = function(w,p,v){
w._el.setAttribute(p, w._vS.attr[p] + (w._vE.attr[p]- w._vS.attr[p]) * v);
}
}
ats[p] = o[p] * 1;
}
}
return ats;
}
}));

176
demo/src/kute-css.js Normal file
View file

@ -0,0 +1,176 @@
/* KUTE.js - The Light Tweening Engine
* package CSS Plugin
* by dnp_theme
* Licensed under MIT-License
*/
(function(factory){
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
var KUTE = require("./kute.js");
// Export the modified one. Not really required, but convenient.
module.exports = factory(KUTE);
} else if(typeof window.KUTE != "undefined") {
factory(KUTE);
} else {
throw new Error("CSS Plugin require KUTE.js.")
}
})(function(KUTE){
var K = window.KUTE, p,
_br = K.property('borderRadius'), _brtl = K.property('borderTopLeftRadius'), _brtr = K.property('borderTopRightRadius'),
_brbl = K.property('borderBottomLeftRadius'), _brbr = K.property('borderBottomRightRadius'), // all radius props prefixed
_cls = ['borderColor', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'outlineColor'], // colors 'hex', 'rgb', 'rgba' -- #fff / rgb(0,0,0) / rgba(0,0,0,0)
_rd = ['borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'], // border radius px/any
_bm = ['right', 'bottom', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
'padding', 'margin', 'paddingTop','paddingBottom', 'paddingLeft', 'paddingRight', 'marginTop','marginBottom', 'marginLeft', 'marginRight',
'borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'outlineWidth'], // dimensions / box model
_tp = ['fontSize','lineHeight','letterSpacing','wordSpacing'], // text properties
_clp = ['clip'], _bg = ['backgroundPosition'], // clip | background position
_mg = _rd.concat(_bm,_tp), // a merge of all properties with px|%|em|rem|etc unit
_all = _cls.concat(_clp, _rd, _bm, _tp, _bg), al = _all.length,
_d = _d || {}; //all properties default values
//populate default values object
for ( var i=0; i< al; i++ ){
p = _all[i];
if (_cls.indexOf(p) !== -1){
_d[p] = 'rgba(0,0,0,0)'; // _d[p] = {r:0,g:0,b:0,a:1};
} else if ( _mg.indexOf(p) !== -1 ) {
_d[p] = 0;
} else if ( _bg.indexOf(p) !== -1 ){
_d[p] = [50,50];
} else if ( p === 'clip' ){
_d[p] = [0,0,0,0];
}
}
// create prepare/render functions for additional colors properties
for (var i = 0, l = _cls.length; i<l; i++) {
p = _cls[i];
K.pp[p] = function(p,v) {
if ( (!(p in K.dom)) ) {
K.dom[p] = function(w,p,v) {
var _c = {};
for (var c in w._vE[p].value) {
if ( c !== 'a' ){
_c[c] = parseInt(w._vS[p].value[c] + (w._vE[p].value[c] - w._vS[p].value[c]) * v )||0;
} else {
_c[c] = (w._vS[p].value[c] && w._vE[p].value[c]) ? parseFloat(w._vS[p].value[c] + (w._vE[p].value[c] - w._vS[p].value[c]) * v) : null;
}
}
if ( w._hex ) {
w._el.style[p] = K.rth( _c.r, _c.g, _c.b );
} else {
w._el.style[p] = !_c.a || _isIE8 ? 'rgb(' + _c.r + ',' + _c.g + ',' + _c.b + ')' : 'rgba(' + _c.r + ',' + _c.g + ',' + _c.b + ',' + _c.a + ')';
}
};
}
return K.pp.cls(p,v);
};
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || _d[p];
};
}
// create prepare/render functions for additional box model properties
for (var i = 0, l = _mg.length; i<l; i++) {
p = _mg[i];
K.pp[p] = function(p,v){
if ( (!(p in K.dom)) ) {
K.dom[p] = function(w,p,v) {
w._el.style[p] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
}
return K.pp.box(p,v);
};
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || _d[p];
};
}
//create prepare/render functions for radius properties
for (var i = 0, l = _rd.length; i<l; i++) {
p = _rd[i];
K.pp[p] = function(p,v){
if ( (!(p in K.dom)) ) {
if (p === 'borderRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_br] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderTopLeftRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brtl] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderTopRightRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brtr] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderBottomLeftRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brbl] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderBottomRightRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brbr] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
}
}
return K.pp.box(p,v);
};
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || _d[p];
};
}
// clip
K.pp['clip'] = function(p,v){
if ( !(p in K.dom) ) {
K.dom[p] = function(w,p,v) {
var h = 0, cl = [];
for (h;h<4;h++){
var c1 = w._vS[p][h].v, c2 = w._vE[p][h].v, cu = w._vE[p][h].u || 'px';
cl[h] = ((c1 + ( c2 - c1 ) * v)) + cu;
}
w._el.style[p] = 'rect('+cl+')';
};
}
if ( v instanceof Array ){
return [ K.truD(v[0]), K.truD(v[1]), K.truD(v[2]), K.truD(v[3]) ];
} else {
var ci = v.replace(/rect|\(|\)/g,'');
ci = /\,/g.test(ci) ? ci.split(/\,/g) : ci.split(/\s/g);
return [ K.truD(ci[0]), K.truD(ci[1]), K.truD(ci[2]), K.truD(ci[3]) ];
}
};
K.prS['clip'] = function(el,p,v){
var c = K.gCS(el,p), w = K.gCS(el,'width'), h = K.gCS(el,'height');
return !/rect/.test(c) ? [0, w, h, 0] : c;
};
// background position
K.pp['backgroundPosition'] = function(p,v) {
if ( !(p in K.dom) ) {
K.dom[p] = function(w,p,v) {
var px1 = w._vS[p].x.v, px2 = w._vE[p].x.v, py1 = w._vS[p].y.v, py2 = w._vE[p].y.v,
px = (px1 + ( px2 - px1 ) * v), pxu = '%', py = (py1 + ( py2 - py1 ) * v), pyu = '%';
w._el.style[p] = px + pxu + ' ' + py + pyu;
};
}
if ( v instanceof Array ){
return { x: K.truD(v[0])||{ v: 50, u: '%' }, y: K.truD(v[1])||{ v: 50, u: '%' } };
} else {
var posxy = v.replace(/top|left/g,0).replace(/right|bottom/g,100).replace(/center|middle/g,50), xp, yp;
posxy = /\,/g.test(posxy) ? posxy.split(/\,/g) : posxy.split(/\s/g); posxy = posxy.length === 2 ? posxy : [posxy[0],50];
xp = K.truD(posxy[0]); yp = K.truD(posxy[1]);
return { x: xp, y: yp };
}
}
K.prS['backgroundPosition'] = function(el,p,v){
return K.gCS(el,p) || _d[p];
}
return this;
});

292
demo/src/kute-svg.js Normal file
View file

@ -0,0 +1,292 @@
/* KUTE.js - The Light Tweening Engine
* package - SVG Plugin
* desc - draw strokes, morph paths and SVG color props
* by dnp_theme
* Licensed under MIT-License
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
// We assume, that require() is sync.
var KUTE = require("./kute.js");
// Export the modified one. Not really required, but convenient.
module.exports = factory(KUTE);
} else if ( typeof window.KUTE !== 'undefined' ) {
// Browser globals
window.KUTE.svg = window.KUTE.svg || factory(KUTE);
} else {
throw new Error("SVG Plugin require KUTE.js.");
}
}( function (KUTE) {
'use strict';
var K = window.KUTE, S = S || {}, p,
_svg = document.getElementsByTagName('path')[0],
_ns = _svg && _svg.ownerSVGElement && _svg.ownerSVGElement.namespaceURI || 'http://www.w3.org/2000/svg',
_nm = ['strokeWidth', 'strokeOpacity', 'fillOpacity', 'stopOpacity'], // numeric SVG CSS props
_cls = ['fill', 'stroke', 'stopColor'], // colors 'hex', 'rgb', 'rgba' -- #fff / rgb(0,0,0) / rgba(0,0,0,0)
trm = function(s){ if (!String.prototype.trim) { return s.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); } else { return s.trim(); }};
if (_svg && !_svg.ownerSVGElement) {return;} // if SVG API is not supported, return
// SVG MORPH
// get path d attribute or create a path with string value
S.getPath = function(e){
var p = {}, el = typeof e === 'object' ? e : /^\.|^\#/.test(e) ? document.querySelector(e) : null;
if ( el && /path|glyph/.test(el.tagName) ) {
p.e = S.forcePath(el);
p.o = el.getAttribute('d');
} else if (!el && /[a-z][^a-z]*/ig.test(e)) { // maybe it's a string path already
var np = S.createPath(trm(e));
p.e = np;
p.o = e;
}
return p;
}
S.pathCross = function(w){
// path tween options
this._mpr = w.morphPrecision || 25;
this._midx = w.morphIndex;
this._smi = w.showMorphInfo;
this._rv1 = w.reverseFirstPath;
this._rv2 = w.reverseSecondPath;
var p1 = S.getOnePath(w._vS.path.o), p2 = S.getOnePath(w._vE.path.o), arr;
arr = S._pathCross(p1,p2);
w._vS.path.d = arr[0];
w._vE.path.d = arr[1];
}
S._pathCross = function(s,e){
s = S.createPath(s); e = S.createPath(e);
var arr = S.getSegments(s,e,this._mpr), s1 = arr[0], e1 = arr[1], arL = e1.length, idx;
// reverse arrays
if (this._rv1) { s1.reverse(); }
if (this._rv2) { e1.reverse(); }
// determine index for best/minimum distance between points
if (this._smi) { idx = S.getBestIndex(s1,e1); }
// shift second array to for smallest tween distance
if (this._midx) {
var e11 = e1.splice(this._midx,arL-this._midx);
e1 = e11.concat(e1);
}
// the console.log helper utility
if (this._smi) {
console.log( 'KUTE.js Path Morph Log\nThe morph used ' + arL + ' points to draw both paths based on '+this._mpr+' morphPrecision value.\n'
+ (this._midx ? 'You\'ve configured the morphIndex to ' + this._midx + ' while the recommended is ' + idx+ '.\n' : 'You may also consider a morphIndex for the second path. Currently the best index seems to be ' + idx + '.\n')
+ (
!this._rv1 && !this._rv2 ? 'If the current animation is not satisfactory, consider reversing one of the paths. Maybe the paths do not intersect or they really have different draw directions.' :
'You\'ve chosen that the first path to have ' + ( this._rv1 ? 'REVERSED draw direction, ' : 'UNCHANGED draw direction, ') + 'while second path is to be ' + (this._rv2 ? 'REVERSED.\n' : 'UNCHANGED.\n')
)
);
}
s = e = null;
return [s1,e1]
}
S.getSegments = function(s,e,r){
var s1 = [], e1 = [], le1 = s.getTotalLength(), le2 = e.getTotalLength(), ml = Math.max(le1,le2),
d = r, ar = ml / r, j = 0, sl = ar*r; // sl = sample length
// populate the points arrays based on morphPrecision as sample size
while ( (j += r) < sl ) {
s1.push( [s.getPointAtLength(j).x, s.getPointAtLength(j).y]);
e1.push( [e.getPointAtLength(j).x, e.getPointAtLength(j).y]);
}
return [s1,e1];
}
S.getBestIndex = function(s,e){
var s1 = S.clone(s), e1 = S.clone(e), d = [], i, r = [], l = s1.length, t, ax, ay;
for (i=0; i<l; i++){
t = e1.splice(i,l-i); e1 = t.concat(e1);
ax = Math.abs(s1[i][0] - e1[i][0]);
ay = Math.abs(s1[i][1] - e1[i][1]);
d.push( Math.sqrt( ax * ax + ay * ay ) );
r.push( e1 );
e1 = []; e1 = S.clone(e); t = null;
}
return d.indexOf(Math.min.apply(null,d));
}
S.getOnePath = function(p){
var a = p.split(/z/i);
if (a.length > 2) {
return trm(a[0]) + 'z';
} else { return trm(p); }
}
S.createPath = function (p){
var c = document.createElementNS(_ns,'path'), d = typeof p === 'object' ? p.getAttribute('d') : p;
c.setAttribute('d',d); return c;
}
S.forcePath = function(p){
if (p.tagName === 'glyph') { // perhaps we can also change other SVG tags in the future
var c = S.createPath(p); p.parentNode.appendChild(c); return c;
}
return p;
}
S.clone = function(obj) {
var copy;
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = S.clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) {
copy[attr] = S.clone(obj[attr]);
}
}
return copy;
}
return obj;
}
// register the render SVG path object
// process path object and also register the render function
K.pp['path'] = function(a,o,l) {
if (!('path' in K.dom)) {
K.dom['path'] = function(w,p,v){
var curve =[], i, l;
for(i=0,l=w._vE.path.d.length;i<l;i++) { // for each point
curve[i] = [];
for(var j=0;j<2;j++) { // each point coordinate
curve[i].push(w._vS.path.d[i][j]+(w._vE.path.d[i][j]-w._vS.path.d[i][j])*v);
}
}
w._el.setAttribute("d", v === 1 ? w._vE.path.o : 'M' + curve.join('L') + 'Z' );
}
}
return S.getPath(o);
};
K.prS['path'] = function(el,p,v){
return el.getAttribute('d');
};
// SVG DRAW
S.getDraw = function(e,v){
var l = e.getTotalLength(), start, end, d, o;
if ( v instanceof Object ) {
return v;
} else if (typeof v === 'string') {
v = v.split(/\,|\s/);
start = /%/.test(v[0]) ? S.percent(trm(v[0]),l) : parseFloat(v[0]);
end = /%/.test(v[1]) ? S.percent(trm(v[1]),l) : parseFloat(v[1]);
} else if (typeof v === 'undefined') {
o = parseFloat(K.gCS(e,'strokeDashoffset'));
d = K.gCS(e,'strokeDasharray').split(/\,/);
start = 0-o;
end = parseFloat(d[0]) + start || l;
}
return { s: start, e: end, l: l }
};
S.percent = function(v,l){
return parseFloat(v) / 100 * l;
};
// register the draw
K.pp['draw'] = function(a,o,l){
if (!('draw' in K.dom)) {
K.dom['draw'] = function(w,p,v){
var l, s, e, o;
l = w._vS.draw.l;
s = w._vS.draw.s+(w._vE.draw.s-w._vS.draw.s)*v;
e = w._vS.draw.e+(w._vE.draw.e-w._vS.draw.e)*v;
o = 0 - s;
w._el.style.strokeDashoffset = o +'px';
w._el.style.strokeDasharray = e+o<1 ? '0px, ' + l + 'px' : (e+o) + 'px, ' + l + 'px';
}
}
return S.getDraw(l,o);
}
K.prS['draw'] = function(el,p,v){
return S.getDraw(el)
}
// SVG CSS Properties
for ( var i = 0, l = _cls.length; i< l; i++) {
p = _cls[i];
K.pp[p] = function(p,v){
if (!(p in K.dom)) {
K.dom[p] = function(w,p,v){
var _c = {};
for (var c in w._vE[p]) {
if ( c !== 'a' ){
_c[c] = parseInt(w._vS[p][c] + (w._vE[p][c] - w._vS[p][c]) * v )||0;
} else {
_c[c] = (w._vS[p][c] && w._vE[p][c]) ? parseFloat(w._vS[p][c] + (w._vE[p][c] - w._vS[p][c]) * v) : null;
}
}
if ( w._hex ) {
w._el.style[p] = K.rth( _c.r, _c.g, _c.b );
} else {
w._el.style[p] = !_c.a ? 'rgb(' + _c.r + ',' + _c.g + ',' + _c.b + ')' : 'rgba(' + _c.r + ',' + _c.g + ',' + _c.b + ',' + _c.a + ')';
}
}
}
return K.truC(v);
}
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || 'rgba(0,0,0,0)';
}
}
for ( var i = 0, l = _nm.length; i< l; i++) { // for numeric CSS props SVG related
p = _nm[i];
if (p === 'strokeWidth'){
K.pp[p] = function(p,v){
if (!(p in K.dom)) {
K.dom[p] = function(w,p,v) {
w._el.style[p] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v) + w._vS[p].unit;
}
}
return K.pp.box(p,v);
}
} else {
K.pp[p] = function(p,v){
if (!(p in K.dom)) {
K.dom[p] = function(w,p,v) {
w._el.style[p] = w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v;
}
}
return K.pp.unl(p,v);
}
}
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || 0;
}
}
return S;
}));

145
demo/start.html Normal file
View file

@ -0,0 +1,145 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="A quick start guide for KUTE.js, CDN sources, NPM.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>Getting Started with KUTE.js | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Synthax highlighter -->
<link href="./assets/css/prism.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li><a href="css.html">CSS Plugin </a></li>
<li><a href="svg.html">SVG Plugin </a></li>
<li><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group active">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li class="active"><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li><a href="easing.html">Easing Functions</a></li>
<li><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>Getting Started</h2>
<p>Welcome to KUTE.js API documentation, here we're going to talk about how to download, install, use, control and set up cross browser animations, in great detail. KUTE.js can be found on <a href="http://www.jsdelivr.com/#!kute.js" target="_blank">CDN</a> and also npm and Bower repositories with all it's features and tools.</p>
<h3>Bower and NPM</h3>
<p>You can install KUTE.js package by using either Bower or NPM.</p>
<pre><code class="language-clike">$ npm install --save kute.js
# Or
$ bower install --save kute.js
</code></pre>
<h3>Websites</h3>
<p>In your website add the following code, the best would be to put it at the end of your <code>body</code> tag:</p>
<pre><code class="language-markup">&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute.min.js">&lt;/script> &lt;!-- core KUTE.js --></code></pre>
<p>Also you can include the tools that you need for your project:</p>
<pre><code class="language-markup">&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute-jquery.min.js">&lt;/script> &lt;!-- jQuery Plugin -->
&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute-easing.min.js">&lt;/script> &lt;!-- Bezier Easing Functions -->
&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute-physics.min.js">&lt;/script> &lt;!-- Physics Easing Functions -->
&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute-css.min.js">&lt;/script> &lt;!-- CSS Plugin -->
&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute-svg.min.js">&lt;/script> &lt;!-- SVG Plugin -->
&lt;script src="https://cdn.jsdelivr.net/kute.js/1.5.0/kute-attr.min.js">&lt;/script> &lt;!-- Attributes Plugin -->
</code></pre>
<p>Your awesome animation coding would follow after these script links.</p>
<h3>Targeting Legacy Browsers</h3>
<p>You need to know when users' browser is a legacy one in order to use KUTE.js only for what browsers actually support. A quick note here: IE8 doesn't support any <code>transform</code> property or <code>RGBA</code> colors while IE9 can only do 2D transformations. Check the <a href="http://caniuse.com/#feat=transforms2d" target="_blank">2D transforms</a> and the <a href="http://caniuse.com/#feat=transforms3d" target="_blank">3D transforms</a> browser support list for more information.</p>
<p>Don't use <a href="https://modernizr.com/" target="_blank">Modernizr</a>, the best thing you can actually do is to use the Microsoft's synthax for it's own legacy browsers, and <a target="_blank" href="http://www.paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/">here is the full refference</a> on that. For other legacy browsers there is a ton of ways to target them, quite efficiently I would say: <a href="http://browserhacks.com/" target="_blank">there you go</a>.</p>
<ul id="share" class="nav">
<li>Share </li>
<li class="hidden-xs"><a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Facebook"><span class="ion-social-facebook-outline icon"></span></a></li>
<li class="hidden-xs"><a target="_blank" href="https://twitter.com/home?status=Spread the word about @kute.js animation engine by @thednp and download here http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Twitter"><span class="icon ion-social-twitter-outline"></span></a></a></li>
<li class="hidden-xs"><a target="_blank" href="https://plus.google.com/share?url=http://thednp.github.io/kute.js/index.html" title="Share KUTE.js on Google+"><span class="icon ion-social-googleplus-outline"></span></a></li>
</ul>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- highlighter -->
<script src="./assets/js/prism.js" type="text/javascript"></script>
<!--<script src="http://cdn.jsdelivr.net/kute.js/1.0.0/kute.full.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- some stuff -->
<script src="./assets/js/scripts.js"></script> <!-- some stuff -->
</body>
</html>

370
demo/svg.html Normal file
View file

@ -0,0 +1,370 @@
<!DOCTYPE html>
<!--[if IE 7]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8]><html class="ie ie8" lang="en"><![endif]-->
<!--[if IE 9]><html class="ie ie9" lang="en"><![endif]-->
<!--[if gte IE 10 | !IE ]><!--> <html lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="The SVG Plugin for KUTE.js enables animation for path morphing, drawing stroke, as well as some SVG specific CSS properties.">
<meta name="keywords" content="kute,kute.js,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
<title>KUTE.js SVG Plugin | Javascript Animation Engine</title>
<!-- RESET CSS -->
<link type="text/css" href="./assets/css/reset.css" rel="stylesheet">
<!-- DEMO KUTE CSS -->
<link type="text/css" href="./assets/css/kute.css" rel="stylesheet">
<!-- Ion Icons -->
<link type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
<!-- Synthax highlighter -->
<link href="./assets/css/prism.css" rel="stylesheet">
<!-- Polyfill -->
<script src="./assets/js/minifill.js"> </script>
<!-- legacy browsers support via polyfill
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
<!--[if IE]>
<script src="https://cdn.jsdelivr.net/minifill/0.0.2/minifill.min.js"> </script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="fill overlay"></div>
<div class="site-wrapper">
<div class="navbar-wrapper">
<div class="content-wrap">
<a href="index.html"><h1>KUTE.<span>js</span></h1></a>
<ul class="nav">
<li class="btn-group"><a href="#" data-function="toggle">Features <span class="caret"></span></a>
<ul class="subnav">
<li><a href="features.html">Feature Overview</a></li>
<li><a href="properties.html">Supported Properties</a></li>
</ul>
</li>
<li class="btn-group active">
<a href="#" data-function="toggle">Examples <span class="caret"></span></a>
<ul class="subnav">
<li><a href="examples.html">Core Engine</a></li>
<li><a href="css.html">CSS Plugin </a></li>
<li class="active"><a href="svg.html">SVG Plugin </a></li>
<li><a href="attr.html">Attributes Plugin </a></li>
</ul>
</li>
<li class="btn-group">
<a href="#" data-function="toggle">API <span class="caret"></span></a>
<ul class="subnav">
<li><a href="start.html">Getting Started</a></li>
<li><a href="api.html">Public Methods</a></li>
<li><a href="easing.html">Easing Functions</a></li>
<li><a href="extend.html">Extend Guide</a></li>
</ul>
</li>
<li><a href="about.html">About</a></li>
</ul>
</div>
</div>
<div class="content-wrap">
<h2>SVG Plugin</h2>
<p>The SVG Plugin for KUTE.js extends the core engine and enables animation for various CSS properties specific to SVG elements as well as morphing path shapes. We'll dig into this in great detail as well as provide valuable tips on how to configure your animation for best performance and visual aesthetics. The SVG Plugin is very light, maybe one of the lightest out there, still, you will find it to be very powerful and flexible.</p>
<p>Keep in mind that older browsers like Internet Explorer 8 and below as well as stock browser from Android 4.3 and below <a href="http://caniuse.com/#search=svg" target="_blank">do not support inline SVG</a>.</p>
<h3>Shape Morphing</h3>
<p>One of the most important parts of the plugin is the shape morphing capability. It only applies to inline <code>&lt;path></code> and <code>&lt;glyph></code> SVG elements, with closed shapes (their <code>d</code> attribute ends with <code>z</code>). The plugin is packed with specific tween options to help you improve the morph animation:</p>
<ul>
<li><kbd>showMorphInfo: true</kbd> when <code>true</code> the script will log valuable information about the morph such as default/current sample size, number of points based on sample size, the recommended index for points rotation, or if one of the shapes require to be reversed. By default this option is <code>false</code> for serious performance reasons.</li>
<li><kbd>morphPrecision: Number</kbd> option allows you to set the sampling size of the morph. The lesser value the better visual but the more power consumption and less performance. The default value is 25 but the <a href="http://bl.ocks.org/mbostock/3081153" target="_blank">D3.js example</a> uses 4.</li>
<li><kbd>morphIndex: Number</kbd> option allows you to rotate the second/end path in a way that the points travel the least possible distance during morph, and as an effect the morph animation feel more "natural". By default, this option is not set.</li>
<li><kbd>reverseFirstPath: true</kbd> when is <code>true</code> this option allows you to reverse the draw direction of the FIRST shape. By default this option is <code>false</code>.</li>
<li><kbd>reverseSecondPath: true</kbd> when is <code>true</code> this option allows you to reverse the draw direction of the SECOND shape. By default this option is also <code>false</code>.</li>
</ul>
<h4>Basic Example</h4>
<p>In the first morph example we are going to go through some basic steps on how to setup and how to improve the morph animation. Our demo is a morph from a rectangle into a star, so first let's create an SVG element with two paths, first is going to be visible, filled with color, while second is going to be hidden. The first path is the start shape and the second is the end shape, you guessed it, and we can also add some ID to the paths so we can easily target them with our code.</p>
<pre><code class="language-markup">&lt;svg id="morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
&lt;path id="rectangle" class="bg-lime" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531 c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
&lt;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.011"/>
&lt;/svg>
</code></pre>
<p>Now we can apply both <code>.to()</code> and <code>fromTo()</code> methods:</p>
<pre><code class="language-javascript">// the fromTo() method
var tween = KUTE.fromTo('#rectangle', {path: '#rectangle' }, { path: '#star' }).start();
// OR
// the to() method will take the path's d attribute value and use it as start value
var tween = KUTE.to('#rectangle', { path: '#star' }).start();
// OR
// simply pass in a valid path string without the need to have two paths in your SVG
var tween = KUTE.to('#rectangle', { path: 'M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011' }).start();
</code></pre>
<p>For all the above tween objects the animation should look like this:</p>
<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" >
<path id="rectangle" class="bg-lime" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531
c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
<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.011"/>
</svg>
<div class="example-buttons">
<a id="morphBtn" class="btn btn-green" href="javascript:void(0)">Start</a>
</div>
</div>
<p>As you can see, the animation could need some fine tunning. Let's open the console, and this time we'll pass in the <code>showMorphInfo: true</code> tween option that will help us find the best possible morph as performance and visual. Have a look:</p>
<pre><code class="language-javascript">// let's check the morph info again
var tween = KUTE.to('#rectangle', { path: '#star' }, {showMorphInfo: true}).start();
// The console log should show you this
/* ------------------------------------
KUTE.js Path Morph Log
The morph used 92 points to draw both paths based on 25 morphPrecision value.
You may also consider a morphIndex for the second path. Currently the best index seems to be 79.
If the current animation is not satisfactory, consider reversing one of the paths. Maybe the paths do not intersect or they really have different draw directions.
*/
</code></pre>
<p>Next, we're going to set the <code>morphIndex: 79</code> and we will get an improved morph.</p>
<div class="featurettes">
<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-blue" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531
c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
<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>
<div class="example-buttons">
<a id="morphBtn1" class="btn btn-orange" href="javascript:void(0)">Start</a>
</div>
</div>
<p>Much better! You can play with <code>morphIndex</code> value, maybe you can get an even better or more interesting morph.</p>
<h4>Multi Path Example</h4>
<p>In other cases, you may want to morph multiple paths at the same time. Let's have a look at the following paths:</p>
<pre><code class="language-markup">&lt;svg id="multi-morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
&lt;path d="M206.115,255.957c-23.854-12.259-47.043-18.479-68.94-18.479c-2.978,0-5.976,0.09-8.974,0.354 c-27.94,2.312-53.461,9.684-69.875,15.414c-4.354,1.599-8.817,3.288-13.415,5.152L0,414.096 c30.851-11.416,58.146-16.969,83.135-16.969c40.423,0,69.764,15.104,93.996,30.652c11.481-38.959,39.022-133.045,47.241-161.162 C218.397,262.975,212.334,259.332,206.115,255.957z
M264.174,295.535l-45.223,157.074c13.416,7.686,58.549,32.024,93.105,32.024 c27.896,0,59.127-7.147,95.417-21.896l43.179-150.988c-29.316,9.461-57.438,14.26-83.732,14.26 C318.945,326.01,285.363,310.461,264.174,295.535z
M146.411,184.395c38.559,0.399,67.076,15.104,90.708,30.251l46.376-158.672c-9.772-5.598-35.403-19.547-53.929-24.3c-12.193-2.842-25.01-4.308-38.602-4.308c-25.898,0.488-54.194,6.973-86.444,19.9 L60.3,202.564c32.404-12.218,60.322-18.17,86.043-18.17C146.366,184.395,146.411,184.395,146.411,184.395L146.411,184.395z
M512,99.062c-29.407,11.416-58.104,17.233-85.514,17.233c-45.844,0-79.646-15.901-101.547-31.183L278.964,244.23 c30.873,19.854,64.146,29.939,99.062,29.939c28.474,0,57.97-6.84,87.73-20.344l-0.091-1.111l1.867-0.443L512,99.062z"/>
&lt;path d="M0.175 256l-0.175-156.037 192-26.072v182.109z
M224 69.241l255.936-37.241v224h-255.936z
M479.999 288l-0.063 224-255.936-36.008v-187.992z
M192 471.918l-191.844-26.297-0.010-157.621h191.854z"/>
&lt;/svg>
</code></pre>
<p>As you can see, both these paths have additional subpaths, and KUTE.js will only animate the first of both in this case. To animate them all, we need to break them into multiple paths, so we can handle each path morph properly.</p>
<pre><code class="language-markup">&lt;svg id="multi-morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
&lt;path id="w11" d="M206.115,255.957c-23.854-12.259-47.043-18.479-68.94-18.479c-2.978,0-5.976,0.09-8.974,0.354 c-27.94,2.312-53.461,9.684-69.875,15.414c-4.354,1.599-8.817,3.288-13.415,5.152L0,414.096 c30.851-11.416,58.146-16.969,83.135-16.969c40.423,0,69.764,15.104,93.996,30.652c11.481-38.959,39.022-133.045,47.241-161.162 C218.397,262.975,212.334,259.332,206.115,255.957z"/>
&lt;path id="w12" d="M264.174,295.535l-45.223,157.074c13.416,7.686,58.549,32.024,93.105,32.024 c27.896,0,59.127-7.147,95.417-21.896l43.179-150.988c-29.316,9.461-57.438,14.26-83.732,14.26 C318.945,326.01,285.363,310.461,264.174,295.535z"/>
&lt;path id="w13" d="M146.411,184.395c38.559,0.399,67.076,15.104,90.708,30.251l46.376-158.672c-9.772-5.598-35.403-19.547-53.929-24.3c-12.193-2.842-25.01-4.308-38.602-4.308c-25.898,0.488-54.194,6.973-86.444,19.9 L60.3,202.564c32.404-12.218,60.322-18.17,86.043-18.17C146.366,184.395,146.411,184.395,146.411,184.395L146.411,184.395z"/>
&lt;path id="w14" d="M512,99.062c-29.407,11.416-58.104,17.233-85.514,17.233c-45.844,0-79.646-15.901-101.547-31.183L278.964,244.23 c30.873,19.854,64.146,29.939,99.062,29.939c28.474,0,57.97-6.84,87.73-20.344l-0.091-1.111l1.867-0.443L512,99.062z"/>
&lt;path id="w21" style="visibility:hidden" d="M0.175 256l-0.175-156.037 192-26.072v182.109z"/>
&lt;path id="w22" style="visibility:hidden" d="M224 69.241l255.936-37.241v224h-255.936z"/>
&lt;path id="w23" style="visibility:hidden" d="M479.999 288l-0.063 224-255.936-36.008v-187.992z"/>
&lt;path id="w24" style="visibility:hidden" d="M192 471.918l-191.844-26.297-0.010-157.621h191.854z"/>
&lt;/svg>
</code></pre>
<p>After a close inspection we determined that paths are not ordered the same so it seems we need to tween the paths in a way that their points travel the least possible distance, as follows: w11 to w24, w13 to w21, w14 to w22 and w12 to w23.</p>
<p>Now we can write the tween objects and get to working:</p>
<pre><code class="language-javascript">var multiMorph1 = KUTE.to('#w11', { path: '#w24' }).start();
var multiMorph2 = KUTE.to('#w13', { path: '#w21' }).start();
var multiMorph3 = KUTE.to('#w14', { path: '#w22' }).start();
var multiMorph3 = KUTE.to('#w12', { path: '#w23' }).start();
</code></pre>
<p>As you can imagine, it's quite hard if not impossible to code something that would do all this work automatically, so after a few minutes of tweaking the options, here's what we should see:</p>
<div class="featurettes">
<svg class="example-box-model example-box" id="multi-morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 550 550" >
<path id="w11" class="bg-red" d="M206.115,255.957c-23.854-12.259-47.043-18.479-68.94-18.479c-2.978,0-5.976,0.09-8.974,0.354 c-27.94,2.312-53.461,9.684-69.875,15.414c-4.354,1.599-8.817,3.288-13.415,5.152L0,414.096 c30.851-11.416,58.146-16.969,83.135-16.969c40.423,0,69.764,15.104,93.996,30.652c11.481-38.959,39.022-133.045,47.241-161.162 C218.397,262.975,212.334,259.332,206.115,255.957z"/>
<path id="w12" class="bg-orange" d="M264.174,295.535l-45.223,157.074c13.416,7.686,58.549,32.024,93.105,32.024 c27.896,0,59.127-7.147,95.417-21.896l43.179-150.988c-29.316,9.461-57.438,14.26-83.732,14.26 C318.945,326.01,285.363,310.461,264.174,295.535z"/>
<path id="w13" class="bg-green" d="M146.411,184.395c38.559,0.399,67.076,15.104,90.708,30.251l46.376-158.672c-9.772-5.598-35.403-19.547-53.929-24.3c-12.193-2.842-25.01-4.308-38.602-4.308c-25.898,0.488-54.194,6.973-86.444,19.9 L60.3,202.564c32.404-12.218,60.322-18.17,86.043-18.17C146.366,184.395,146.411,184.395,146.411,184.395L146.411,184.395z"/>
<path id="w14" class="bg-blue" d="M512,99.062c-29.407,11.416-58.104,17.233-85.514,17.233c-45.844,0-79.646-15.901-101.547-31.183L278.964,244.23 c30.873,19.854,64.146,29.939,99.062,29.939c28.474,0,57.97-6.84,87.73-20.344l-0.091-1.111l1.867-0.443L512,99.062z"/>
<path id="w21" style="visibility:hidden" d="M0.175 256l-0.175-156.037 192-26.072v182.109z"/>
<path id="w22" style="visibility:hidden" d="M224 69.241l255.936-37.241v224h-255.936z"/>
<path id="w23" style="visibility:hidden" d="M479.999 288l-0.063 224-255.936-36.008v-187.992z"/>
<path id="w24" style="visibility:hidden" d="M192 471.918l-191.844-26.297-0.010-157.621h191.854z"/>
</svg>
<div class="example-buttons">
<a id="multiMorphBtn" class="btn btn-olive" href="javascript:void(0)">Start</a>
</div>
</div>
<p>This final touch required using <code>reverseSecondPath:true</code> option for all tweens because each shape have a slightly different position from its corresponding shape, so make sure to check the <a href="assets/js/svg.js" target="_blank">svg.js</a> for a full code review.</p>
<h4>Complex Example</h4>
<p>The last morph example is a bit more complex as the paths have subpaths with different positions and other important differences such as having different amounts of subpaths. In that case you have to manually clone one or more paths in a way that the number of starting shapes is equal to the number of ending shapes, as well as making sure the starting shapes are close to their corresponding end shapes; at this point you should be just like in the previous example. So without further talking, let's get into it:</p>
<div class="featurettes">
<svg class="example-box-model example-box" id="multi-morph-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513">
<path id="rectangle-container" class="bg-blue" 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 id="symbol-left" class="bg-light" 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 id="symbol-left-clone" class="bg-light" 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 id="symbol-right" class="bg-lime" 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 id="circle-container" style="visibility: hidden;" d="M256 0c-141.385 0-256 114.614-256 256s114.614 256 256 256c141.385 0 256-114.615 256-256 0-141.386-114.615-256-256-256z"/>
<path id="eye-right" style="visibility: hidden;" d="M352 128c17.673 0 32 21.49 32 48s-14.327 48-32 48-32-21.49-32-48 14.327-48 32-48z"/>
<path id="eye-left" style="visibility: hidden;" d="M176 156.031c29.823 0 51 11.166 51 28.641 0 3.699 1.906 21.497-0.085 24.797-7.414-12.288-27.405-21.094-50.915-21.094s-43.501 8.806-50.915 21.094c-1.991-3.3-0.085-21.098-0.085-24.797 0-17.475 21.177-28.641 51-28.641z"/>
<path id="mouth" style="visibility: hidden;" d="M250.172 416c-59.621 0-111.929-32.14-141.446-80.476 35.205 27.53 97.267 32.905 162.644 19.989 70.124-13.853 124.555-45.771 144.227-88.297-10.827 83.98-80.759 148.784-165.425 148.784z"/>
</svg>
<div class="example-buttons">
<a id="compliMorphBtn" class="btn btn-red" href="javascript:void(0)">Start</a>
</div>
</div>
<p>While there are other tools such as <a href="http://alexk111.github.io/SVG-Morpheus/" target="_blank">SVGMorpheus</a> to enable this kind of multi-path morph, they lack in options to improve the visual and performance. The demos look acceptable in most cases, but the SVGs were manually prepared/optimized which makes it pretty much unusable on a broader horizon. Again, the SVG Plugin for KUTE.js uses approximatelly the same algorithm as D3.js for determining the coordinates for tween, it's super light, it's a better solution.</p>
<h4>Recommendations</h4>
<ul>
<li>The SVG morph animation is very expensive so try to optimize the number of morph animations that run at the same time.</li>
<li>When morphing subpaths/multipaths instead of cloning shapes to have same number of shapes in both starting and ending shapes, you should also consider a fade and/or scale animation to improve the overal animation performance, don't forget about mobile devices.</li>
<li>Large displays would need best resolution possible so a small <code>morphPrecision</code> value (1-10) would be required, assuming performant hardware are powering the displays. For small displays you can get quite comfortable with almost any value, including the default value.</li>
<li>Faster animation speed could be a great trick to hide any polygonal "artefacts".</li>
<li>Always use the <code>showMorphInfo:true</code> tween option to check how the values required for the morph change with every new option value, but <strong>never forget to disable it</strong> after you have optimized the morph to your liking, this option enables a function that detects the best index for points rotation that is very expensive and delays the animation for quite some time.</li>
</ul>
<h3>Drawing Stroke</h3>
<p>Next, we're going to animate the stroke of a <code>&lt;path></code> element, as this type of animation only works with this kind of SVG elements because it's the only one that supports the <code>.getTotalLength()</code> method. Here some code examples:</p>
<pre><code class="language-javascript">// draw the stroke from 0-10% to 90-100%
var tween1 = KUTE.fromTo('selector1',{draw:'0% 10%'}, {draw:'90% 100%'});
// draw the stroke from zero to full path length
var tween2 = KUTE.fromTo('selector1',{draw:'0% 0%'}, {draw:'0% 100%'});
// draw the stroke from full length to 50%
var tween3 = KUTE.fromTo('selector1',{draw:'0% 100%'}, {draw:'50% 50%'});
</code></pre>
<p>We're gonna chain these tweens and start the animation real quick.</p>
<div class="featurettes">
<svg class="example-box-model example-box" id="draw-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513">
<path fill="none" style="stroke:#2196F3; stroke-width:10; stroke-dashoffset: -724.077px; stroke-dasharray: 0px, 1448.15px" id="drawSVG" d="M432 64l-240 240-112-112-80 80 192 192 320-320z"/>
</svg>
<div class="example-buttons">
<a id="drawBtn" class="btn btn-blue" href="javascript:void(0)">Start</a>
</div>
</div>
<p>Remember: the <code>draw</code> property also accepts absolute values, eg. <code>draw: '0 150'</code>; the <code>.to()</code> method takes <code>0% 100%</code> as start value for your tweens when <code>stroke-dasharray</code> and <code>stroke-dashoffset</code> are not set.</p>
<h3>CSS Properties</h3>
<p>As you probably noticed in the above examples we've animated the background color for some of the shapes, that is <code>fill</code>, one of the properties supported by the SVG Plugin, so let's create some tweens real quick:</p>
<pre><code class="language-javascript">// fill HEX/RGBa
var tween1 = KUTE.to('selector', {fill: '#069'});
// fillOpacity Number 0-1
var tween2 = KUTE.to('selector',{fillOpacity: 0.2});
// stroke HEX/RGBa
var tween3 = KUTE.to('selector',{stroke: 'rgba(00,66,99,0.8)'});
// strokeOpacity Number 0-1
var tween4 = KUTE.to('selector',{strokeOpacity: 0.6});
// strokeWidth Number
var tween5 = KUTE.to('selector',{strokeWidth: 10});
</code></pre>
<p>A quick demo with the above:<p>
<div class="featurettes">
<svg class="example-box-model example-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 615 615">
<path class="bg-orange" id="fillSVG" style="stroke-width: 110px; stroke: #FF5722; transform: scale(0.85) translate(60px,60px); -webkit-transform: scale(0.85) translate(60px,60px);" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531
c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
</svg>
<div class="example-buttons">
<a id="cssBtn" class="btn btn-orange" href="javascript:void(0)">Start</a>
</div>
</div>
<p>Now let's have a look at gradients, here we can animate the <code>stopColor</code> defined within the SVG's <code>&lt;linearGradient&gt;</code> element.</p>
<pre><code class="language-markup">&lt;linearGradient id="gradient1" x1="0%" y1="0%" x2="0%" y2="100%">
&lt;stop offset="0%" style="stop-color: #ffd626; stop-opacity:1">&lt;/stop>
&lt;!-- our tween object targets the element below -->
&lt;stop id="myStopColor" offset="100%" style="stop-color: #FF5722; stop-opacity:1">&lt;/stop>
&lt;/linearGradient>
</code></pre>
<pre><code class="language-javascript">// stopColor HEX/RGBa
var tween6 = KUTE.to('#myStopColor',{stopColor: 'rgb(00,66,99)'});
</code></pre>
<p>Same as above, for <code>stopOpacity</code> we also target the right element defined within the SVG's <code>&lt;linearGradient&gt;</code> element.</p>
<pre><code class="language-markup">&lt;linearGradient id="gradient2" x1="0%" y1="0%" x2="0%" y2="100%">
&lt;stop offset="0%" style="stop-color: #2196F3; stop-opacity:1">&lt;/stop>
&lt;!-- our tween object targets the element below -->
&lt;stop id="myStopOpacity" offset="100%" style="stop-color: #e91b1f; stop-opacity:1">&lt;/stop>
&lt;/linearGradient>
</code></pre>
<pre><code class="language-javascript">// stopOpacity Number 0-1
var tween7 = KUTE.to('#myStopOpacity',{stopOpacity: 0.2});
</code></pre>
<div class="featurettes">
<svg class="example-box-model example-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 615 615">
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color: #ffd626; stop-opacity:1"></stop>
<stop id="stopCSVG" offset="100%" style="stop-color: #FF5722; stop-opacity:1"></stop>
</linearGradient>
</defs>
<path fill="url(#gradient1)" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531
c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
</svg>
<svg class="example-box-model example-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 615 615">
<defs>
<linearGradient id="gradient2" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color: #2196F3; stop-opacity:1"></stop>
<stop id="stopOSVG" offset="100%" style="stop-color: #e91b1f; stop-opacity:1"></stop>
</linearGradient>
</defs>
<path fill="url(#gradient2)" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531
c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z"/>
</svg>
<div class="example-buttons">
<a id="gradBtn" class="btn btn-yellow" href="javascript:void(0)">Start</a>
</div>
</div>
<p>The SVG Plugin can be combined with the <a href="attr.html">Attributes Plugin</a> to enable even more advanced/complex animations for SVG elements.</p>
</div>
<!-- FOOTER -->
<footer>
<div class="content-wrap">
<p class="pull-right"><a id="toTop" href="#">Back to top</a></p>
<p>&copy; 2007 - 2016 &middot; <a href="http://themeforest.net/user/dnp_theme?ref=dnp_theme">dnp_theme</a>.</p>
</div>
</footer>
</div><!-- /.site-wrapper -->
<!-- JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- highlighter -->
<script src="./assets/js/prism.js" type="text/javascript"></script>
<!--<script src="http://cdn.jsdelivr.net/kute.js/0.9.2/kute.full.min.js"></script> KUTE CDN -->
<script src="./src/kute.js"></script> <!-- some stuff -->
<script src="./src/kute-svg.js"></script> <!-- some stuff -->
<script src="./assets/js/scripts.js"></script> <!-- global scripts stuff -->
<script src="./assets/js/svg.js"></script> <!-- css plugin stuff -->
</body>
</html>

2
dist/kute-attr.min.js vendored Normal file
View file

@ -0,0 +1,2 @@
// Attributes Plugin for KUTE.js | dnp_theme | MIT License
!function(t){if("function"==typeof define&&define.amd)define(["./kute.js"],function(e){return t(e),e});else if("object"==typeof module&&"function"==typeof require){var e=require("./kute.js");module.exports=t(e)}else{if("undefined"==typeof window.KUTE)throw new Error("Attributes Plugin require KUTE.js.");t(e)}}(function(t){"use strict";var e=window.KUTE;e.gCA=function(t,e){return t.getAttribute(e)},e.prS.attr=function(t,r,n){var i={};for(var o in n)i[o.replace(/_+[a-z]+/,"")]=e.gCA(t,o.replace(/_+[a-z]+/,""));return i},"attr"in e.dom||(e.dom.attr=function(t,r,n){for(var i in t._vE[r])e.dom.attr.prototype[i](t,i,n)});var r=e.dom.attr.prototype;e.pp.attr=function(t,n){var i,o={};for(i in n)if(/%|px/.test(n[i])){var u=e.truD(n[i]).u,a=/%/.test(u)?"_percent":"_"+u;i+a in r||(r[i+a]=function(t,e,r){t._el.setAttribute(e.replace(a,""),t._vS.attr[e].v+(t._vE.attr[e].v-t._vS.attr[e].v)*r+t._vE.attr[e].u)}),o[i+a]=e.truD(n[i])}else i in r||(r[i]=function(t,e,r){t._el.setAttribute(e,t._vS.attr[e]+(t._vE.attr[e]-t._vS.attr[e])*r)}),o[i]=1*n[i];return o}});

2
dist/kute-css.min.js vendored Normal file
View file

@ -0,0 +1,2 @@
// CSS Plugin for KUTE.js | dnp_theme | MIT License
!function(t){if("function"==typeof define&&define.amd)define(["./kute.js"],function(r){return t(r),r});else if("object"==typeof module&&"function"==typeof require){var r=require("./kute.js");module.exports=t(r)}else{if("undefined"==typeof window.KUTE)throw new Error("CSS Plugin require KUTE.js.");t(r)}}(function(t){for(var r,e=window.KUTE,o=e.property("borderRadius"),i=e.property("borderTopLeftRadius"),n=e.property("borderTopRightRadius"),u=e.property("borderBottomLeftRadius"),d=e.property("borderBottomRightRadius"),a=["borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],v=["borderRadius","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"],l=["right","bottom","minWidth","minHeight","maxWidth","maxHeight","padding","margin","paddingTop","paddingBottom","paddingLeft","paddingRight","marginTop","marginBottom","marginLeft","marginRight","borderWidth","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","outlineWidth"],p=["fontSize","lineHeight","letterSpacing","wordSpacing"],f=["clip"],g=["backgroundPosition"],_=v.concat(l,p),s=a.concat(f,v,l,p,g),c=s.length,b=b||{},m=0;c>m;m++)r=s[m],-1!==a.indexOf(r)?b[r]="rgba(0,0,0,0)":-1!==_.indexOf(r)?b[r]=0:-1!==g.indexOf(r)?b[r]=[50,50]:"clip"===r&&(b[r]=[0,0,0,0]);for(var m=0,S=a.length;S>m;m++)r=a[m],e.pp[r]=function(t,r){return t in e.dom||(e.dom[t]=function(t,r,o){var i={};for(var n in t._vE[r].value)"a"!==n?i[n]=parseInt(t._vS[r].value[n]+(t._vE[r].value[n]-t._vS[r].value[n])*o)||0:i[n]=t._vS[r].value[n]&&t._vE[r].value[n]?parseFloat(t._vS[r].value[n]+(t._vE[r].value[n]-t._vS[r].value[n])*o):null;t._hex?t._el.style[r]=e.rth(i.r,i.g,i.b):t._el.style[r]=!i.a||_isIE8?"rgb("+i.r+","+i.g+","+i.b+")":"rgba("+i.r+","+i.g+","+i.b+","+i.a+")"}),e.pp.cls(t,r)},e.prS[r]=function(t,r,o){return e.gCS(t,r)||b[r]};for(var m=0,S=_.length;S>m;m++)r=_[m],e.pp[r]=function(t,r){return t in e.dom||(e.dom[t]=function(t,r,e){t._el.style[r]=t._vS[r].value+(t._vE[r].value-t._vS[r].value)*e+t._vE[r].unit}),e.pp.box(t,r)},e.prS[r]=function(t,r,o){return e.gCS(t,r)||b[r]};for(var m=0,S=v.length;S>m;m++)r=v[m],e.pp[r]=function(t,r){return t in e.dom||("borderRadius"===t?e.dom[t]=function(t,r,e){t._el.style[o]=t._vS[r].value+(t._vE[r].value-t._vS[r].value)*e+t._vE[r].unit}:"borderTopLeftRadius"===t?e.dom[t]=function(t,r,e){t._el.style[i]=t._vS[r].value+(t._vE[r].value-t._vS[r].value)*e+t._vE[r].unit}:"borderTopRightRadius"===t?e.dom[t]=function(t,r,e){t._el.style[n]=t._vS[r].value+(t._vE[r].value-t._vS[r].value)*e+t._vE[r].unit}:"borderBottomLeftRadius"===t?e.dom[t]=function(t,r,e){t._el.style[u]=t._vS[r].value+(t._vE[r].value-t._vS[r].value)*e+t._vE[r].unit}:"borderBottomRightRadius"===t&&(e.dom[t]=function(t,r,e){t._el.style[d]=t._vS[r].value+(t._vE[r].value-t._vS[r].value)*e+t._vE[r].unit})),e.pp.box(t,r)},e.prS[r]=function(t,r,o){return e.gCS(t,r)||b[r]};return e.pp.clip=function(t,r){if(t in e.dom||(e.dom[t]=function(t,r,e){var o=0,i=[];for(o;4>o;o++){var n=t._vS[r][o].v,u=t._vE[r][o].v,d=t._vE[r][o].u||"px";i[o]=n+(u-n)*e+d}t._el.style[r]="rect("+i+")"}),r instanceof Array)return[e.truD(r[0]),e.truD(r[1]),e.truD(r[2]),e.truD(r[3])];var o=r.replace(/rect|\(|\)/g,"");return o=/\,/g.test(o)?o.split(/\,/g):o.split(/\s/g),[e.truD(o[0]),e.truD(o[1]),e.truD(o[2]),e.truD(o[3])]},e.prS.clip=function(t,r,o){var i=e.gCS(t,r),n=e.gCS(t,"width"),u=e.gCS(t,"height");return/rect/.test(i)?i:[0,n,u,0]},e.pp.backgroundPosition=function(t,r){if(t in e.dom||(e.dom[t]=function(t,r,e){var o=t._vS[r].x.v,i=t._vE[r].x.v,n=t._vS[r].y.v,u=t._vE[r].y.v,d=o+(i-o)*e,a="%",v=n+(u-n)*e,l="%";t._el.style[r]=d+a+" "+v+l}),r instanceof Array)return{x:e.truD(r[0])||{v:50,u:"%"},y:e.truD(r[1])||{v:50,u:"%"}};var o,i,n=r.replace(/top|left/g,0).replace(/right|bottom/g,100).replace(/center|middle/g,50);return n=/\,/g.test(n)?n.split(/\,/g):n.split(/\s/g),n=2===n.length?n:[n[0],50],o=e.truD(n[0]),i=e.truD(n[1]),{x:o,y:i}},e.prS.backgroundPosition=function(t,r,o){return e.gCS(t,r)||b[r]},this});

2
dist/kute-svg.min.js vendored Normal file

File diff suppressed because one or more lines are too long

75
kute-attr.js Normal file
View file

@ -0,0 +1,75 @@
/* KUTE.js - The Light Tweening Engine
* package - Attributes Plugin
* desc - enables animation for any numeric presentation attribute
* by dnp_theme
* Licensed under MIT-License
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
// We assume, that require() is sync.
var KUTE = require("./kute.js");
// Export the modified one. Not really required, but convenient.
module.exports = factory(KUTE);
} else if ( typeof window.KUTE !== 'undefined' ) {
// Browser globals
factory(KUTE);
} else {
throw new Error("Attributes Plugin require KUTE.js.");
}
}( function (KUTE) {
'use strict';
var K = window.KUTE;
// get current attribute value
K.gCA = function(e,a){
return e.getAttribute(a);
}
K.prS['attr'] = function(el,p,v){
var f = {};
for (var a in v){
f[a.replace(/_+[a-z]+/,'')] = K.gCA(el,a.replace(/_+[a-z]+/,''));
}
return f;
};
// register the render attributes object
if (!('attr' in K.dom)) {
K.dom.attr = function(w,p,v){
for ( var o in w._vE[p] ){
K.dom.attr.prototype[o](w,o,v);
}
};
}
var ra = K.dom.attr.prototype;
// process attributes object K.pp.attr(t[x])
// and also register their render functions
K.pp['attr'] = function(a,o){
var ats = {}, p;
for ( p in o ) {
if ( /%|px/.test(o[p]) ) {
var u = K.truD(o[p]).u, s = /%/.test(u) ? '_percent' : '_'+u;
if (!(p+s in ra)) {
ra[p+s] = function(w,p,v){
w._el.setAttribute(p.replace(s,''), (w._vS.attr[p].v + (w._vE.attr[p].v - w._vS.attr[p].v) * v) + w._vE.attr[p].u);
}
}
ats[p+s] = K.truD(o[p]);
} else {
if (!(p in ra)) {
ra[p] = function(w,p,v){
w._el.setAttribute(p, w._vS.attr[p] + (w._vE.attr[p]- w._vS.attr[p]) * v);
}
}
ats[p] = o[p] * 1;
}
}
return ats;
}
}));

176
kute-css.js Normal file
View file

@ -0,0 +1,176 @@
/* KUTE.js - The Light Tweening Engine
* package CSS Plugin
* by dnp_theme
* Licensed under MIT-License
*/
(function(factory){
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
var KUTE = require("./kute.js");
// Export the modified one. Not really required, but convenient.
module.exports = factory(KUTE);
} else if(typeof window.KUTE != "undefined") {
factory(KUTE);
} else {
throw new Error("CSS Plugin require KUTE.js.")
}
})(function(KUTE){
var K = window.KUTE, p,
_br = K.property('borderRadius'), _brtl = K.property('borderTopLeftRadius'), _brtr = K.property('borderTopRightRadius'),
_brbl = K.property('borderBottomLeftRadius'), _brbr = K.property('borderBottomRightRadius'), // all radius props prefixed
_cls = ['borderColor', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'outlineColor'], // colors 'hex', 'rgb', 'rgba' -- #fff / rgb(0,0,0) / rgba(0,0,0,0)
_rd = ['borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'], // border radius px/any
_bm = ['right', 'bottom', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
'padding', 'margin', 'paddingTop','paddingBottom', 'paddingLeft', 'paddingRight', 'marginTop','marginBottom', 'marginLeft', 'marginRight',
'borderWidth', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'outlineWidth'], // dimensions / box model
_tp = ['fontSize','lineHeight','letterSpacing','wordSpacing'], // text properties
_clp = ['clip'], _bg = ['backgroundPosition'], // clip | background position
_mg = _rd.concat(_bm,_tp), // a merge of all properties with px|%|em|rem|etc unit
_all = _cls.concat(_clp, _rd, _bm, _tp, _bg), al = _all.length,
_d = _d || {}; //all properties default values
//populate default values object
for ( var i=0; i< al; i++ ){
p = _all[i];
if (_cls.indexOf(p) !== -1){
_d[p] = 'rgba(0,0,0,0)'; // _d[p] = {r:0,g:0,b:0,a:1};
} else if ( _mg.indexOf(p) !== -1 ) {
_d[p] = 0;
} else if ( _bg.indexOf(p) !== -1 ){
_d[p] = [50,50];
} else if ( p === 'clip' ){
_d[p] = [0,0,0,0];
}
}
// create prepare/render functions for additional colors properties
for (var i = 0, l = _cls.length; i<l; i++) {
p = _cls[i];
K.pp[p] = function(p,v) {
if ( (!(p in K.dom)) ) {
K.dom[p] = function(w,p,v) {
var _c = {};
for (var c in w._vE[p].value) {
if ( c !== 'a' ){
_c[c] = parseInt(w._vS[p].value[c] + (w._vE[p].value[c] - w._vS[p].value[c]) * v )||0;
} else {
_c[c] = (w._vS[p].value[c] && w._vE[p].value[c]) ? parseFloat(w._vS[p].value[c] + (w._vE[p].value[c] - w._vS[p].value[c]) * v) : null;
}
}
if ( w._hex ) {
w._el.style[p] = K.rth( _c.r, _c.g, _c.b );
} else {
w._el.style[p] = !_c.a || _isIE8 ? 'rgb(' + _c.r + ',' + _c.g + ',' + _c.b + ')' : 'rgba(' + _c.r + ',' + _c.g + ',' + _c.b + ',' + _c.a + ')';
}
};
}
return K.pp.cls(p,v);
};
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || _d[p];
};
}
// create prepare/render functions for additional box model properties
for (var i = 0, l = _mg.length; i<l; i++) {
p = _mg[i];
K.pp[p] = function(p,v){
if ( (!(p in K.dom)) ) {
K.dom[p] = function(w,p,v) {
w._el.style[p] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
}
return K.pp.box(p,v);
};
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || _d[p];
};
}
//create prepare/render functions for radius properties
for (var i = 0, l = _rd.length; i<l; i++) {
p = _rd[i];
K.pp[p] = function(p,v){
if ( (!(p in K.dom)) ) {
if (p === 'borderRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_br] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderTopLeftRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brtl] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderTopRightRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brtr] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderBottomLeftRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brbl] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
} else if (p === 'borderBottomRightRadius') {
K.dom[p] = function(w,p,v) {
w._el.style[_brbr] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v ) + w._vE[p].unit;
};
}
}
return K.pp.box(p,v);
};
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || _d[p];
};
}
// clip
K.pp['clip'] = function(p,v){
if ( !(p in K.dom) ) {
K.dom[p] = function(w,p,v) {
var h = 0, cl = [];
for (h;h<4;h++){
var c1 = w._vS[p][h].v, c2 = w._vE[p][h].v, cu = w._vE[p][h].u || 'px';
cl[h] = ((c1 + ( c2 - c1 ) * v)) + cu;
}
w._el.style[p] = 'rect('+cl+')';
};
}
if ( v instanceof Array ){
return [ K.truD(v[0]), K.truD(v[1]), K.truD(v[2]), K.truD(v[3]) ];
} else {
var ci = v.replace(/rect|\(|\)/g,'');
ci = /\,/g.test(ci) ? ci.split(/\,/g) : ci.split(/\s/g);
return [ K.truD(ci[0]), K.truD(ci[1]), K.truD(ci[2]), K.truD(ci[3]) ];
}
};
K.prS['clip'] = function(el,p,v){
var c = K.gCS(el,p), w = K.gCS(el,'width'), h = K.gCS(el,'height');
return !/rect/.test(c) ? [0, w, h, 0] : c;
};
// background position
K.pp['backgroundPosition'] = function(p,v) {
if ( !(p in K.dom) ) {
K.dom[p] = function(w,p,v) {
var px1 = w._vS[p].x.v, px2 = w._vE[p].x.v, py1 = w._vS[p].y.v, py2 = w._vE[p].y.v,
px = (px1 + ( px2 - px1 ) * v), pxu = '%', py = (py1 + ( py2 - py1 ) * v), pyu = '%';
w._el.style[p] = px + pxu + ' ' + py + pyu;
};
}
if ( v instanceof Array ){
return { x: K.truD(v[0])||{ v: 50, u: '%' }, y: K.truD(v[1])||{ v: 50, u: '%' } };
} else {
var posxy = v.replace(/top|left/g,0).replace(/right|bottom/g,100).replace(/center|middle/g,50), xp, yp;
posxy = /\,/g.test(posxy) ? posxy.split(/\,/g) : posxy.split(/\s/g); posxy = posxy.length === 2 ? posxy : [posxy[0],50];
xp = K.truD(posxy[0]); yp = K.truD(posxy[1]);
return { x: xp, y: yp };
}
}
K.prS['backgroundPosition'] = function(el,p,v){
return K.gCS(el,p) || _d[p];
}
return this;
});

292
kute-svg.js Normal file
View file

@ -0,0 +1,292 @@
/* KUTE.js - The Light Tweening Engine
* package - SVG Plugin
* desc - draw strokes, morph paths and SVG color props
* by dnp_theme
* Licensed under MIT-License
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(["./kute.js"], function(KUTE){ factory(KUTE); return KUTE; });
} else if(typeof module == "object" && typeof require == "function") {
// We assume, that require() is sync.
var KUTE = require("./kute.js");
// Export the modified one. Not really required, but convenient.
module.exports = factory(KUTE);
} else if ( typeof window.KUTE !== 'undefined' ) {
// Browser globals
window.KUTE.svg = window.KUTE.svg || factory(KUTE);
} else {
throw new Error("SVG Plugin require KUTE.js.");
}
}( function (KUTE) {
'use strict';
var K = window.KUTE, S = S || {}, p,
_svg = document.getElementsByTagName('path')[0],
_ns = _svg && _svg.ownerSVGElement && _svg.ownerSVGElement.namespaceURI || 'http://www.w3.org/2000/svg',
_nm = ['strokeWidth', 'strokeOpacity', 'fillOpacity', 'stopOpacity'], // numeric SVG CSS props
_cls = ['fill', 'stroke', 'stopColor'], // colors 'hex', 'rgb', 'rgba' -- #fff / rgb(0,0,0) / rgba(0,0,0,0)
trm = function(s){ if (!String.prototype.trim) { return s.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); } else { return s.trim(); }};
if (_svg && !_svg.ownerSVGElement) {return;} // if SVG API is not supported, return
// SVG MORPH
// get path d attribute or create a path with string value
S.getPath = function(e){
var p = {}, el = typeof e === 'object' ? e : /^\.|^\#/.test(e) ? document.querySelector(e) : null;
if ( el && /path|glyph/.test(el.tagName) ) {
p.e = S.forcePath(el);
p.o = el.getAttribute('d');
} else if (!el && /[a-z][^a-z]*/ig.test(e)) { // maybe it's a string path already
var np = S.createPath(trm(e));
p.e = np;
p.o = e;
}
return p;
}
S.pathCross = function(w){
// path tween options
this._mpr = w.morphPrecision || 25;
this._midx = w.morphIndex;
this._smi = w.showMorphInfo;
this._rv1 = w.reverseFirstPath;
this._rv2 = w.reverseSecondPath;
var p1 = S.getOnePath(w._vS.path.o), p2 = S.getOnePath(w._vE.path.o), arr;
arr = S._pathCross(p1,p2);
w._vS.path.d = arr[0];
w._vE.path.d = arr[1];
}
S._pathCross = function(s,e){
s = S.createPath(s); e = S.createPath(e);
var arr = S.getSegments(s,e,this._mpr), s1 = arr[0], e1 = arr[1], arL = e1.length, idx;
// reverse arrays
if (this._rv1) { s1.reverse(); }
if (this._rv2) { e1.reverse(); }
// determine index for best/minimum distance between points
if (this._smi) { idx = S.getBestIndex(s1,e1); }
// shift second array to for smallest tween distance
if (this._midx) {
var e11 = e1.splice(this._midx,arL-this._midx);
e1 = e11.concat(e1);
}
// the console.log helper utility
if (this._smi) {
console.log( 'KUTE.js Path Morph Log\nThe morph used ' + arL + ' points to draw both paths based on '+this._mpr+' morphPrecision value.\n'
+ (this._midx ? 'You\'ve configured the morphIndex to ' + this._midx + ' while the recommended is ' + idx+ '.\n' : 'You may also consider a morphIndex for the second path. Currently the best index seems to be ' + idx + '.\n')
+ (
!this._rv1 && !this._rv2 ? 'If the current animation is not satisfactory, consider reversing one of the paths. Maybe the paths do not intersect or they really have different draw directions.' :
'You\'ve chosen that the first path to have ' + ( this._rv1 ? 'REVERSED draw direction, ' : 'UNCHANGED draw direction, ') + 'while second path is to be ' + (this._rv2 ? 'REVERSED.\n' : 'UNCHANGED.\n')
)
);
}
s = e = null;
return [s1,e1]
}
S.getSegments = function(s,e,r){
var s1 = [], e1 = [], le1 = s.getTotalLength(), le2 = e.getTotalLength(), ml = Math.max(le1,le2),
d = r, ar = ml / r, j = 0, sl = ar*r; // sl = sample length
// populate the points arrays based on morphPrecision as sample size
while ( (j += r) < sl ) {
s1.push( [s.getPointAtLength(j).x, s.getPointAtLength(j).y]);
e1.push( [e.getPointAtLength(j).x, e.getPointAtLength(j).y]);
}
return [s1,e1];
}
S.getBestIndex = function(s,e){
var s1 = S.clone(s), e1 = S.clone(e), d = [], i, r = [], l = s1.length, t, ax, ay;
for (i=0; i<l; i++){
t = e1.splice(i,l-i); e1 = t.concat(e1);
ax = Math.abs(s1[i][0] - e1[i][0]);
ay = Math.abs(s1[i][1] - e1[i][1]);
d.push( Math.sqrt( ax * ax + ay * ay ) );
r.push( e1 );
e1 = []; e1 = S.clone(e); t = null;
}
return d.indexOf(Math.min.apply(null,d));
}
S.getOnePath = function(p){
var a = p.split(/z/i);
if (a.length > 2) {
return trm(a[0]) + 'z';
} else { return trm(p); }
}
S.createPath = function (p){
var c = document.createElementNS(_ns,'path'), d = typeof p === 'object' ? p.getAttribute('d') : p;
c.setAttribute('d',d); return c;
}
S.forcePath = function(p){
if (p.tagName === 'glyph') { // perhaps we can also change other SVG tags in the future
var c = S.createPath(p); p.parentNode.appendChild(c); return c;
}
return p;
}
S.clone = function(obj) {
var copy;
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = S.clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) {
copy[attr] = S.clone(obj[attr]);
}
}
return copy;
}
return obj;
}
// register the render SVG path object
// process path object and also register the render function
K.pp['path'] = function(a,o,l) {
if (!('path' in K.dom)) {
K.dom['path'] = function(w,p,v){
var curve =[], i, l;
for(i=0,l=w._vE.path.d.length;i<l;i++) { // for each point
curve[i] = [];
for(var j=0;j<2;j++) { // each point coordinate
curve[i].push(w._vS.path.d[i][j]+(w._vE.path.d[i][j]-w._vS.path.d[i][j])*v);
}
}
w._el.setAttribute("d", v === 1 ? w._vE.path.o : 'M' + curve.join('L') + 'Z' );
}
}
return S.getPath(o);
};
K.prS['path'] = function(el,p,v){
return el.getAttribute('d');
};
// SVG DRAW
S.getDraw = function(e,v){
var l = e.getTotalLength(), start, end, d, o;
if ( v instanceof Object ) {
return v;
} else if (typeof v === 'string') {
v = v.split(/\,|\s/);
start = /%/.test(v[0]) ? S.percent(trm(v[0]),l) : parseFloat(v[0]);
end = /%/.test(v[1]) ? S.percent(trm(v[1]),l) : parseFloat(v[1]);
} else if (typeof v === 'undefined') {
o = parseFloat(K.gCS(e,'strokeDashoffset'));
d = K.gCS(e,'strokeDasharray').split(/\,/);
start = 0-o;
end = parseFloat(d[0]) + start || l;
}
return { s: start, e: end, l: l }
};
S.percent = function(v,l){
return parseFloat(v) / 100 * l;
};
// register the draw
K.pp['draw'] = function(a,o,l){
if (!('draw' in K.dom)) {
K.dom['draw'] = function(w,p,v){
var l, s, e, o;
l = w._vS.draw.l;
s = w._vS.draw.s+(w._vE.draw.s-w._vS.draw.s)*v;
e = w._vS.draw.e+(w._vE.draw.e-w._vS.draw.e)*v;
o = 0 - s;
w._el.style.strokeDashoffset = o +'px';
w._el.style.strokeDasharray = e+o<1 ? '0px, ' + l + 'px' : (e+o) + 'px, ' + l + 'px';
}
}
return S.getDraw(l,o);
}
K.prS['draw'] = function(el,p,v){
return S.getDraw(el)
}
// SVG CSS Properties
for ( var i = 0, l = _cls.length; i< l; i++) {
p = _cls[i];
K.pp[p] = function(p,v){
if (!(p in K.dom)) {
K.dom[p] = function(w,p,v){
var _c = {};
for (var c in w._vE[p]) {
if ( c !== 'a' ){
_c[c] = parseInt(w._vS[p][c] + (w._vE[p][c] - w._vS[p][c]) * v )||0;
} else {
_c[c] = (w._vS[p][c] && w._vE[p][c]) ? parseFloat(w._vS[p][c] + (w._vE[p][c] - w._vS[p][c]) * v) : null;
}
}
if ( w._hex ) {
w._el.style[p] = K.rth( _c.r, _c.g, _c.b );
} else {
w._el.style[p] = !_c.a ? 'rgb(' + _c.r + ',' + _c.g + ',' + _c.b + ')' : 'rgba(' + _c.r + ',' + _c.g + ',' + _c.b + ',' + _c.a + ')';
}
}
}
return K.truC(v);
}
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || 'rgba(0,0,0,0)';
}
}
for ( var i = 0, l = _nm.length; i< l; i++) { // for numeric CSS props SVG related
p = _nm[i];
if (p === 'strokeWidth'){
K.pp[p] = function(p,v){
if (!(p in K.dom)) {
K.dom[p] = function(w,p,v) {
w._el.style[p] = (w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v) + w._vS[p].unit;
}
}
return K.pp.box(p,v);
}
} else {
K.pp[p] = function(p,v){
if (!(p in K.dom)) {
K.dom[p] = function(w,p,v) {
w._el.style[p] = w._vS[p].value + (w._vE[p].value - w._vS[p].value) * v;
}
}
return K.pp.unl(p,v);
}
}
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || 0;
}
}
return S;
}));