* Added SVG Transforms for SVG Plugin

* Documentation/demo updates
This commit is contained in:
thednp 2016-08-22 01:45:23 +03:00
parent 7d44719816
commit 5482d8383e
5 changed files with 299 additions and 81 deletions

View file

@ -98,6 +98,56 @@ drawBtn.addEventListener('click', function(){
}, false);
// svgTransform examples
var svgRotate = document.getElementById('svgRotate');
var rotateBtn = document.getElementById('rotateBtn');
var svgr1 = svgRotate.getElementsByTagName('path')[0];
var svgr2 = svgRotate.getElementsByTagName('path')[1];
var svgTween11 = KUTE.to(svgr1, {svgTransform: { rotate: [-360,0,0] } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
var svgTween12 = KUTE.to(svgr2, {svgTransform: { translate: 580 , rotate: 360 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
rotateBtn.addEventListener('click', function(){
!svgTween11.playing && svgTween11.start();
!svgTween12.playing && svgTween12.start();
}, false);
var svgTranslate = document.getElementById('svgTranslate');
var translateBtn = document.getElementById('translateBtn');
var svgt1 = svgTranslate.getElementsByTagName('path')[0];
var svgt2 = svgTranslate.getElementsByTagName('path')[1];
var svgTween21 = KUTE.to(svgt1, {svgTransform: { translate: 580 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
var svgTween22 = KUTE.to(svgt2, {svgTransform: { translate: 0 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
translateBtn.addEventListener('click', function(){
!svgTween21.playing && svgTween21.start();
!svgTween22.playing && svgTween22.start();
}, false);
var svgSkew = document.getElementById('svgSkew');
var skewBtn = document.getElementById('skewBtn');
var svgsk1 = svgSkew.getElementsByTagName('path')[0];
var svgsk2 = svgSkew.getElementsByTagName('path')[1];
var svgTween31 = KUTE.to(svgsk1, {svgTransform: { skewX: -15 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
var svgTween32 = KUTE.to(svgsk2, {svgTransform: { translate: 580, skewY: 15 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
skewBtn.addEventListener('click', function(){
!svgTween31.playing && svgTween31.start();
!svgTween32.playing && svgTween32.start();
}, false);
var svgScale = document.getElementById('svgScale');
var scaleBtn = document.getElementById('scaleBtn');
var svgs1 = svgScale.getElementsByTagName('path')[0];
var svgs2 = svgScale.getElementsByTagName('path')[1];
var svgTween41 = KUTE.to(svgs1, {svgTransform: { scale: 1.5 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
var svgTween42 = KUTE.to(svgs2, {svgTransform: { translate: 580, scale: 0.5 } }, {yoyo: true, repeat: 1, duration: 1500, easing: "easingCubicOut"});
scaleBtn.addEventListener('click', function(){
!svgTween41.playing && svgTween41.start();
!svgTween42.playing && svgTween42.start();
}, false);
// fill HEX/RGBa
var tween1 = KUTE.to('#fillSVG', {fill: '#069'}, {duration: 1500, yoyo:true, repeat: 1});

View file

@ -9,8 +9,8 @@
<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="KUTE.js is a minimal Javascript animation engine with outstanding performance and supporting 3D transforms, SVG Morph, draw SVG, scroll, CSS3 properties and many more.">
<meta name="keywords" content="kute,kute.js,animation,javascript animation,tweening engine,animation engine,morph svg,draw svg,css3,3d transform,scroll,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="description" content="KUTE.js is a minimal Javascript animation engine with outstanding performance and supporting 3D transforms, SVG Morph, draw SVG, SVG transform, cross-browser animation, scroll animation, CSS3 properties and many more.">
<meta name="keywords" content="kute,kute.js,animation,javascript animation,tweening engine,animation engine,morph svg,draw svg,svg transform,css3,3d transform,scroll,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png">

View file

@ -88,27 +88,37 @@
<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 single value size transformation. Eg. <code>scale:2</code> will enlarge an element by a degree of 2. Supported on IE9.</li>
<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. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-blue">rotate</kbd> property applies rotation to an element on the Z axis or the plain document. Eg. <code>rotate:250</code> will rotate an element clockwise by 250 degrees. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-blue">skewX</kbd> property applies a skew transformation on the X axis. Eg. <code>skewX:25</code> will skew an element by 25 degrees. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-blue">skewY</kbd> property applies a skew transformation on the Y axis. Eg. <code>skewY:25</code> will skew an element by 25 degrees. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-blue">scale</kbd> property applies a single value size transformation. Eg. <code>scale:2</code> will enlarge an element by a degree of 2. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-red">matrix</kbd>, double axis <kbd class="bg-red">skew</kbd> and double axis <kbd class="bg-red">scale</kbd> properties are 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-blue">translateX</kbd> property is for horizontal translation. EG. <code>translateX:150</code> to translate an element 150px to the right. <kbd class="bg-lime">IE10+</kbd></li>
<li><kbd class="bg-blue">translateY</kbd> property is for vertical translation. EG. <code>translateY:-250</code> to translate an element 250px towards the top. <kbd class="bg-lime">IE10+</kbd></li>
<li><kbd class="bg-blue">translateZ</kbd> property is for translation 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. Requires a <code>perspective</code> tween option to be used; the smaller perspective value, the deeper translation. <kbd class="bg-lime">IE10+</kbd></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. Also requires using a <code>perspective</code> tween option. <kbd class="bg-lime">IE10+</kbd></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. Requires perspective. <kbd class="bg-lime">IE10+</kbd></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. Requires perspective. <kbd class="bg-lime">IE10+</kbd></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. <kbd class="bg-lime">IE10+</kbd></li>
<li><kbd class="bg-red">matrix3d</kbd>, <kbd class="bg-red">rotate3d</kbd>, and <kbd class="bg-red">scale3d</kbd> properties are not supported.</li>
</ul>
<h3>SVG Transform</h3>
<p>The <a href="svg.html">SVG Plugin</a> features cross browser 2D transform animations via the <kbd class="bg-olive">svgTransform</kbd> tween property and the <code>transform</code> presentation attribute, similar in functionality as the Attributes Plugin.</p>
<ul>
<li><kbd class="bg-olive">translate</kbd> sub-property applies horizontal and / or vertical translation. EG. <code>translate:150</code> to translate a shape 150px to the right or <code>translate:[-150,200]</code> to move the element to the left by 150px and to bottom by 200px. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-olive">rotate</kbd> sub-property applies rotation to a shape on the Z axis. Eg. <code>rotate:150</code> will rotate a shape clockwise by 150 degrees or <code>rotate: [45,25,25]</code> to rotate the shape by 45 degrees around the <i>[25,25]</i> coordinate of the parent <code>&lt;svg></code>. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-olive">skewX</kbd> sub-property used to apply a skew transformation on the X axis. Eg. <code>skewX:25</code> will skew a shape by 25 degrees. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-olive">skewY</kbd> sub-property used to apply a skew transformation on the Y axis. Eg. <code>skewY:25</code> will skew a shape by 25 degrees. <kbd class="bg-lime">IE9+</kbd></li>
<li><kbd class="bg-olive">scale</kbd> sub-property used to apply a single value size transformation. When using this sub-property, the <kbd class="bg-olive">translate</kbd> will be automatically adjusted to make sure the animation looks as you would expect it from a regular HTML5 element. Eg. <code>scale:0.5</code> will scale down a shape to half of it's initial size. <kbd class="bg-lime">IE9+</kbd></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>

View file

@ -204,7 +204,7 @@
return a;
}
S.pTA = function(p) { // simple pathToAbsolute for polygons | this is still a work in progress
S.pTA = function(p) { // simple pathToAbsolute for polygons | this is still BETA / a work in progress
var np = p.match(pathReg), wp = [], l = np.length, s, c, r, x = 0, y = 0;
for (var i = 0; i<l; i++){
np[i] = np[i]; c = np[i][0]; r = new RegExp(c+'[^\\d|\\-]*','i');
@ -279,8 +279,7 @@
return parseFloat(v) / 100 * l;
};
// register the draw
K.pp['draw'] = function(a,o,l){
K.pp['draw'] = function(a,o,l){ // register the draw property
if (!('draw' in K.dom)) {
K.dom['draw'] = function(w,p,v){
var l, s, e, o;
@ -299,60 +298,6 @@
K.prS['draw'] = function(el,p,v){
return S.gDr(el)
}
for ( var i = 0, l = _cls.length; i< l; i++) { // SVG CSS Color Properties
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 for SVG elements
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] + (w._vE[p] - w._vS[p]) * v;
}
}
return parseFloat(v);
}
}
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || 0;
}
}
// SVG DRAW UTILITITES
S.gL = function(el){ // getLength - returns the result of any of the below functions
@ -378,7 +323,7 @@
S.gPL = function(el){ // getPolygonLength - return the length of the Polygon / Polyline
var points = el.getAttribute('points').split(' '), len = 0;
if (points.length > 1) {
function coord(p) {
var coord = function (p) {
var c = p.split(',');
if (c.length != 2) {
return; // return undefined
@ -387,14 +332,14 @@
return;
}
return [parseFloat(c[0]), parseFloat(c[1])];
}
};
function dist(c1, c2) {
var dist = function (c1, c2) {
if (c1 != undefined && c2 != undefined) {
return Math.sqrt(Math.pow((c2[0]-c1[0]), 2) + Math.pow((c2[1]-c1[1]), 2));
}
return 0;
}
};
if (points.length > 2) {
for (var i=0; i<points.length-1; i++) {
@ -425,5 +370,129 @@
return ((Math.sqrt(.5 * ((len * len) + (wid * wid)))) * (Math.PI * 2)) / 2;
}
// SVG CSS Color 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 from any type of SVG shape
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] + (w._vE[p] - w._vS[p]) * v;
}
}
return parseFloat(v);
}
}
K.prS[p] = function(el,p,v){
return K.gCS(el,p) || 0;
}
}
// SVG Transform
K.pp['svgTransform'] = function(p,v,l){
// register the render function
if (!('svgTransform' in K.dom)) {
K.dom['svgTransform'] = function(w,p,v) {
var tr = '', i;
for (i in w._vE[p]){
tr += i + '('; // start string
if ( i === 'translate'){ // translate
tr += (w._vS[p][i][1] === w._vE[p][i][1] && w._vE[p][i][1] === 0 )
? (w._vS[p][i][0] + (w._vE[p][i][0] - w._vS[p][i][0]) * v )
: (w._vS[p][i][0] + (w._vE[p][i][0] - w._vS[p][i][0]) * v ) + ' ' + (w._vS[p][i][1] + (w._vE[p][i][1] - w._vS[p][i][1]) * v );
} else if ( i === 'rotate'){ // rotate
tr += w._vS[p][i][0] + (w._vE[p][i][0] - w._vS[p][i][0]) * v + ' ';
tr += !w.reversed ? w._vE[p][i][1] + ',' + w._vE[p][i][2] : w._vS[p][i][1] + ',' + w._vS[p][i][2]; // make sure to always use the right transform-origin
} else { // scale, skewX or skewY
tr += w._vS[p][i] + (w._vE[p][i] - w._vS[p][i]) * v;
}
tr += ') '; // end string
}
w._el.setAttributeNS(null,'transform', tr.replace(/\)\s$/,')') );
}
}
// return transform object
var tf = {}, bb = l.getBBox(), cx = bb.x + bb.width/2, cy = bb.y + bb.height/2, i, r, t;
for ( i in v ) {
if (i === 'rotate'){
r = v[i] instanceof Array ? v[i]
: /\s/.test(v[i]) ? [v[i].split(' ')[0]*1, v[i].split(' ')[1].split(',')[0]*1, v[i].split(' ')[1].split(',')[1]*1]
: [v[i],cx,cy];
tf[i] = r;
} else if (i === 'translate'){
t = v[i] instanceof Array ? v[i] : /\s/.test(v[i]) ? v[i].split(' ') : [v[i],0];
tf[i] = [t[0] * 1||0, t[1] * 1];
} else if (i === 'scale'){
tf[i] = v[i] * 1||1;
} else {
tf[i] = v[i] * 1||0;
}
}
// http://www.petercollingridge.co.uk/interactive-svg-components/pan-and-zoom-control
// try to adjust translation when scale is used
if ('scale' in tf) {
tf['translate'] = !( 'translate' in tf ) ? [0,0] : tf['translate'];
tf['translate'][0] += (1-tf['scale']) * bb.width/2;
tf['translate'][1] += (1-tf['scale']) * bb.height/2;
}
return tf;
}
// KUTE.prepareStart K.prS[p](el,p,to[p])
// returns an obect with current transform attribute value
K.prS['svgTransform'] = function(l,p,t) {
var tr = {}, cta = l.getAttributeNS(null,'transform'),
ct = cta && /\)/.test(cta) ? cta.split(')') : 'none', i, j, ctr ={}, pr;
if (ct instanceof Array) {
for (j=0; j<ct.length; j++){
pr = ct[j].split('(');
pr[0] !== '' && (ctr[pr[0].replace(/\s/,'')] = pr[1] );
}
}
// find a value in current attribute value or add a default value
for (i in t) { tr[i] = i in ctr ? ctr[i] : 0; }
return tr;
}
return S;
}));

101
svg.html
View file

@ -10,7 +10,7 @@
<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 SVG morph, draw SVG, as well as some SVG specific CSS properties.">
<meta name="keywords" content="kute,kute.js,animation,javascript animation,tweening engine,animation engine,morph svg,draw svg,svg animation,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="keywords" content="kute,kute.js,animation,javascript animation,svg transform,cross-browser svg transform,tweening engine,animation engine,morph svg,draw svg,svg animation,Javascript,Native Javascript,vanilla javascript,jQuery">
<meta name="author" content="dnp_theme">
<link rel="shortcut icon" href="./assets/img/favicon.png"> <!-- TO DO -->
@ -80,7 +80,7 @@
<div class="content-wrap">
<h2>SVG Plugin</h2>
<p>The SVG Plugin for KUTE.js extends the core engine and enables animation for various SVG specific CSS properties, as well as SVG morphing of 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>The SVG Plugin for KUTE.js extends the core engine and enables animation for various SVG specific CSS properties, SVG morphing of path shapes and SVG transforms. 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> so make sure to fiter out your SVG tweens.</p>
<h3>SVG Morphing</h3>
<p>One of the most important parts of the plugin is the SVG 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>). On initialization or animation start, depending on the chosen KUTE.js method, it will <a href="http://phrogz.net/SVG/convert_path_to_polygon.xhtml" target="_blank">sample a number of points</a> along the two paths based on a default / given sample size and will create two arrays with these points, the arrays that we need for interpolation. Further more, with a set of options we can then rearrange / reverse these arrays to optimize and / or maximize the visual effect of the morph:</p>
@ -313,7 +313,97 @@ var tween3 = KUTE.fromTo('selector1',{draw:'0% 100%'}, {draw:'50% 50%'});
</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>
<h3>SVG Transforms</h3>
<p>Starting with KUTE.js 1.5.2, the SVG Plugin features a new tween property for cross browser transforms for SVG, but I decided to code a separate set of methods for SVG only, to keep performance tight. A very simple roadmap was described <a href="https://github.com/thednp/kute.js/issues/31" target="_blank">here</a>; in brief we needed to find a way to enable transforms for SVG in a <a href="https://css-tricks.com/transforms-on-svg-elements/" target="_blank">reliable and cross-browser</a> supported fashion. In that sense the plugin will allow you to animate SVG shapes via the <code>transform</code> presentation attribute and the <code class="bg-indigo">svgTransform</code> tween property. To make sure we don't mess up with the current methods, we changed the syntax a little bit:</p>
<pre><code class="language-javascript">// using all possible values
var tween1 = KUTE.to('selector', {svgTransform: { translate: [150,100], rotate: [45,0,0], skewX: 15, skewY: 20, scale: [1.2,1.3] }});
// using shorthand notations
var tween2 = KUTE.to('selector', {svgTransform: { translate: 120, rotate: 45, scale: 1.2 }});
</code></pre>
<p>As you can see we have some familiar notation as well as new notation. Let's break it down.</p>
<h4>SVG Rotation</h4>
<p>In our first example we'll have a look at rotations. For instance setting <code>rotate: [45,0,0]</code>, the first value is the angle to which the shape will rotate to and the other two values are coordinates for the <code>transform-origin</code>. When <code>rotate: 45</code> notation is used, the script will calculate the coordinates of the shape's central point, as if your <code>transform-origin</code> default value is <i>50% 50%</i>, something you would expect from regular HTML elements. However keep in mind that the <code>transform-origin</code> coordinates are relative to the parent <code>&lt;svg></code> element. Let's have a look at a quick demo:</p>
<div class="featurettes">
<svg id="svgRotate" class="example-box-model example-box" style="width:320px; overflow: visible;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1085 513">
<path class="bg-olive" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
<path class="bg-blue" transform="translate(580)" 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>
</svg>
<div class="example-buttons">
<a id="rotateBtn" class="btn btn-red" href="javascript:void(0)">Start</a>
</div>
</div>
<p>The first tween uses the <code>rotate: [-360,0,0]</code> notation and the animation clearly shows the shape rotating around it's top left coordinate. The second tween uses the <code>rotate: 360</code> notation and the animation shows the shape rotating around it's own central point.</p>
<p>When for CSS3 <code>transforms</code> we could have used values such as <i>50% 50%</i> or <i>center bottom</i> as <code>transform-origin</code> and the entire processing was basically none, when it comes to SVG we need to make use of the SVG API functions to determine the proper value. But stay cool, here comes <code>.getBBox()</code> to the rescue! And here's how to:</p>
<pre><code class="language-javascript">// get the bounding box
var bb = element.getBBox(); // returns an object like {x:0, y:20, width:200, height: 200} for any type of shape
// determine the X point of transform-origin for 25%
var transformOriginX = bb.x + (25 * bb.width / 100);
// determine the Y point of transform-origin for 75%
var transformOriginY = bb.y + (75 * bb.height / 100);
// set your rotation tween with "25% 75%" transform-origin
var rotationTween = KUTE.to(element, {svgTransform: {rotate: [45, transformOriginX, transformOriginY]}});
</code></pre>
<h4>SVG Translation</h4>
<p>In this example we'll have a look at translations, so when setting <code>translate: [150,0]</code>, the first value is X (horizontal) coordinate to which the shape will translate to and the second value is Y (vertical) coordinate for translation. When <code>translate: 150</code> notation is used, the script will understand that's the X value and the Y value is 0 just like for the regular HTML elements transformation. Let's have a look at a quick demo:</p>
<div class="featurettes">
<svg id="svgTranslate" class="example-box-model example-box" style="width:320px; overflow: visible;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1085 513">
<path class="bg-green" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
<path class="bg-orange" transform="translate(580)" 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>
</svg>
<div class="example-buttons">
<a id="translateBtn" class="btn btn-blue" href="javascript:void(0)">Start</a>
</div>
</div>
<p>The first tween uses the <code>translate: [580,0]</code> notation and the second tween uses the <code>translate: 0</code> notation. Keep in mind that the values are unitless and are relative to the <code>viewBox</code> attribute.</p>
<h4>SVG Skew</h4>
<p>For skews for SVGs we have a very simple notation: <code>skewX: 25</code> or <code>skewY: -25</code> as SVGs don't support the <code>skew: [X,Y]</code> function. Here's a quick demo:</p>
<div class="featurettes">
<svg id="svgSkew" class="example-box-model example-box" style="width:320px; overflow: visible;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1085 513">
<path class="bg-yellow" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
<path class="bg-indigo" transform="translate(580)" 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>
</svg>
<div class="example-buttons">
<a id="skewBtn" class="btn btn-red" href="javascript:void(0)">Start</a>
</div>
</div>
<p>The first tween skews the shape on X (horizontal) axis and the second tween skews the shape on Y (vertical) axis.</p>
<h4>SVG Scaling</h4>
<p>Our last transform example for SVGs is the scale. Unlike translations, for scale animation the plugin only accepts single value like <code>scale: 1.5</code>, for both X (horizontal) axis and Y (vertical) axis, to keep it simple and even if SVGs do support <code>scale(X,Y)</code>. But because the scaling on SVGs depends very much on the shape's position, the script will always try to adjust the translation to make the animation look as we would expect. A quick demo:</p>
<div class="featurettes">
<svg id="svgScale" class="example-box-model example-box" style="width:320px; overflow: visible;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1085 513">
<path class="bg-lime" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
<path class="bg-olive" transform="translate(580)" 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>
</svg>
<div class="example-buttons">
<a id="scaleBtn" class="btn btn-pink" href="javascript:void(0)">Start</a>
</div>
</div>
<p>The first tween scales the shape at <code>scale: 1.5</code> and the second tween scales down the shape at <code>scale: 0.5</code> value. If you inspect the elements, you will notice for both shapes translation is involved, and this is to keep <code>transform-origin</code> at an expected <i>50% 50%</i> value, well, approximately.</p>
<h4>Recommendations for SVG Transforms</h4>
<ul>
<li>To make sure animations don't go out of control, <b>always use same order of transform properties</b>: <code>translate</code>, <code>rotate</code>, <code>skewX</code>, <code>skewY</code>, <code>scale</code>.</li>
<li>Keep in mind the adjustments required for rotations, remember the <code>.getBBox()</code> method, it's really useful to set custom <code>transform-origin</code>.</li>
<li>By default browsers use <code>overflow: hidden</code> for <code>&lt;svg></code> so child elements are partially/completelly hidden while animating. You might want to set <code>overflow: visible</code> if that is the case or some browser specific tricks.</li>
<li>When using <code>viewBox="0 0 500 500"</code> attribute for <code>&lt;svg></code> and no <code>width</code> and/or <code>height</code> attribute(s), means that you expect the SVG to be scalable and most Internet Explorer versions simply don't work. You might want to <a href="https://css-tricks.com/scale-svg/" target="_blank">check this tutorial</a>.</li>
<li>Unlike the CSS3 <code class="bg-indigo">transform</code> animation featured in the core engine, the <code class="bg-indigo">svgTransform</code> feature does not stack properties for chains of tween objects created with the <code>.to()</code> method, you will have to provide all properties that you need in all chained tweens.</li>
<li>In other cases when you need maximum control and precision or when shapes are already affected by translation, you might want to use the <code>.fromTo()</code> method with all proper values.</li>
<li>Also the <code class="bg-indigo">svgTransform</code> feature does not support 3D transforms, because they are not supported in all browsers.</li>
<li>Rotations will always use the <i>valuesEnd</i> value of the transform origin and cannot be animated, so that translations don't get messed up.</li>
</ul>
<h3>CSS Properties Specific to SVGs</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'});
@ -330,7 +420,7 @@ 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>
<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
@ -392,8 +482,7 @@ var tween7 = KUTE.to('#myStopOpacity',{stopOpacity: 0.2});
<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>
<h3>Future Plans</h3>
<p>The future versions of the SVG Plugin might also feature improved cross browser transform animations, as currently the core engine only works and was tested with HTML elements of most types except SVG.</p>
<p>Since most of this plugin scripting works with <code>path</code> or <code>glyph</code> elements, I'm also considering a very light <code>convertToPath</code> feature, but there are some <a href="https://github.com/Waest/SVGPathConverter" target="_blank">already out there</a>.</p>
<p>Since SVG morph scripting works only with <code>path</code> or <code>glyph</code> elements, I'm also considering a very light <code>convertToPath</code> feature, but there are some <a href="https://github.com/Waest/SVGPathConverter" target="_blank">already out there</a>.</p>
</div>
<ul id="share" class="nav">