kute.js/svg.html
2017-09-08 11:43:15 +03:00

596 lines
55 KiB
HTML

<!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, minimum-scale=1.0">
<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,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 -->
<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>
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
<!-- legacy browsers support via polyfill, you must remove the above when used
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,getComputedStyle|gated"> </script> -->
</head>
<body>
<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="text.html">Text 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="options.html">Tween Options</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 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>
<ul>
<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 15 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-red" 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 go ahead and play with the new <a href="http://codepen.io/thednp/pen/YGayLg">utility</a>, it's gonna make your SVG morph work a breeze.</p>
<p>Well, we're going to set the <code>morphIndex: 127</code> tween option and we will get an improved morph. Sometimes the recommended value isn't what we're looking for, so you just have to experience values
around the recommended one. I also made a <a href="http://codepen.io/thednp/pen/bpRRZd" target="_blank">pen</a> for you to play with.</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 the <code>morphIndex</code> value, maybe you can get a more interesting morph.</p>
<h4>Morphing Polygon Paths</h4>
<p>When your paths are only <code>lineto</code>, <code>vertical-lineto</code> and <code>horizontal-lineto</code> based shapes (the <code>d</code> attribute consists of <code>L</code>, <code>V</code> and
<code>H</code> path commands), the SVG Plugin will work differently: it will use their points instead of sampling new ones. As a result, we boost the visual and maximize the performance. The
<code>morphPrecision</code> option will not apply since the paths are already polygons, still you will have access to all the other options.</p>
<p>The plugin will try to convert paths to absolute values for polygons, but it might not find most accurate coordinates values for relative <code>v</code> and <code>h</code> path commands. I highly
recommend using my <a href="http://codepen.io/thednp/full/EgVqLw/">utility converter</a> to prepare your paths in that case.</p>
<pre><code class="language-javascript">// let's morph a triangle into a star
var tween1 = KUTE.to('#triangle', { path: '#star' }).start();
// or same path into a square
var tween2 = KUTE.to('#triangle', { path: '#square' }).start();
</code></pre>
<p>In the example below the triangle shape will morph into a square, then the square will morph into a star, so 2 tweens chained with a third that will morph back to the original triangle shape. For each
tween the morph will use the number of points from the shape with most points as a sample size for the other shape. Let's have a look at the demo.</p>
<div class="featurettes">
<svg class="example-box-model example-box" id="morph-example2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<path id="square" style="visibility:hidden" d="M25.508,12.011 L576.715,12.011 L576.715,584.766 L25.508,584.766 L25.508,12.011 z"/>
<path id="square2" style="visibility:hidden" d="M25.508,12.011 H576.715 V584.766 H25.508 V12.011z"/>
<path id="square3" style="visibility:hidden" d="M25.508,12.011 L576.715,12.011 V584.766 L25.508,584.766 V12.011 z"/>
<path id="triangle" fill="#673AB7" d="M301.113,12.011L576.715,584.766L25.508,584.766L301.113,12.011z"/>
<path id="star2" style="visibility:hidden" d="M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808
l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011z"/>
</svg>
<div class="example-buttons">
<a id="morphBtn2" class="btn btn-green" href="javascript:void(0)">Start</a>
</div>
</div>
<p>The morph for polygon paths is the best morph in terms of performance so it's worth keeping that in mind. Also using paths with only <code>L</code> path command will make sure to prevent value processing
and allow the animation to start as fast as possible.</p>
<h4>Multi Path Example</h4>
<p>In other cases, you may want to morph paths that have subpaths. 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 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: <code>#w11</code>
to <code>#w24</code>, <code>#w13</code> to <code>#w21</code>, <code>#w14</code> to <code>#w22</code> and <code>#w12</code> to <code>#w23</code>.</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 minute or two 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" fill="#e91b1f" 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" fill="#FF5722" 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" fill="#4CAF50" 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" fill="#2196F3" 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>Note that 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 as well as significant
differences of their positions. In this 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.</p>
<p>An important aspect of multi path morph is syncronization: since the <code>.to()</code> method will prepare the paths for interpolation at animation start, and this usually takes a bit of time,
the problem can be easily solved as always using the <code>.fromTo()</code> method. So, let's get into it:</p>
<pre><code class="language-javascript">// complex multi morph, the paths should be self explanatory
var morph1 = KUTE.fromTo('#start-container', { path: '#start-container' }, { path: '#end-container' });
var morph2 = KUTE.fromTo('#startpath1', { path: '#startpath1' }, { path: '#endpath1' });
var morph3 = KUTE.fromTo('#startpath1-clone', { path: '#startpath1-clone' }, { path: '#endpath1' });
var morph4 = KUTE.fromTo('#startpath2', { path: '#startpath2' }, { path: '#endpath2' });
</code></pre>
<p>As with the previous example, you should change which path will morph to which path so that their points travel the least possible distance and the morph animation looks visually appealing. In the next
example, we have used a <code>mask</code> where we included the subpaths of both start and end shape, just to get the same visual as the originals.</p>
<div class="featurettes">
<svg class="example-box-model example-box" id="multi-morph-example-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513">
<defs>
<mask id="symbol">
<rect width="100%" height="100%" fill="#fff"></rect>
<path id="symbol-left" fill="#000" d="M155.889 333.394h-55.632c-3.351 0-5.854-1.504-7.271-3.792-1.467-2.379-1.542-5.464 0-8.534l59.11-104.313c0.063-0.114 0.063-0.19 0-0.316l-37.615-65.116c-1.556-3.098-1.783-6.157-0.316-8.534 1.417-2.301 4.235-3.477 7.586-3.477h55.632c8.535 0 12.72 5.499 15.489 10.431 0 0 38.020 66.33 38.249 66.696-2.252 3.97-60.059 106.21-60.059 106.21-2.844 5.131-6.852 10.745-15.173 10.745z"></path>
<path id="symbol-left-clone" fill="#000" d="M155.889 333.394h-55.632c-3.351 0-5.854-1.504-7.271-3.792-1.467-2.379-1.542-5.464 0-8.534l59.11-104.313c0.063-0.114 0.063-0.19 0-0.316l-37.615-65.116c-1.556-3.098-1.783-6.157-0.316-8.534 1.417-2.301 4.235-3.477 7.586-3.477h55.632c8.535 0 12.72 5.499 15.489 10.431 0 0 38.020 66.33 38.249 66.696-2.252 3.97-60.059 106.21-60.059 106.21-2.844 5.131-6.852 10.745-15.173 10.745z"></path>
<path id="symbol-right" fill="#000" d="M418.956 75.269l-123.176 217.79c-0.075 0.115-0.075 0.255 0 0.367l78.431 143.295c1.556 3.084 1.593 6.221 0.113 8.597-1.415 2.288-4.033 3.552-7.383 3.552h-55.57c-8.522 0-12.783-5.663-15.54-10.596 0 0-78.848-144.646-79.050-145.023 3.944-6.98 123.797-219.523 123.797-219.523 2.984-5.362 6.587-10.596 14.894-10.596h56.203c3.351 0 5.981 1.265 7.396 3.553 1.466 2.376 1.428 5.511-0.115 8.584z"></path>
<path id="eye-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>
<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>
<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"></path>
</mask>
</defs>
<path id="rectangle-container" fill="#2196F3" mask="url(#symbol)" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
<path id="circle-container" style="visibility: hidden;" d="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>
</svg>
<div class="example-buttons">
<a id="compliMorphBtn" class="btn btn-red" href="javascript:void(0)">Start</a>
</div>
</div>
<p>So you have many options to improve the visual and performance for your complex animation ideas. 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 lighter script, it might be a better solution for your applications.</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>Polygons with only <code>lineto</code> path commands are best for performance.</li>
<li>Faster animation speed could be a great trick to hide any polygonal "artefacts". Strokes are also very useful for hiding the polygons' edges.</li>
<li>Don't forget about the <a href="http://codepen.io/thednp/pen/YGayLg">path morph utility</a>, it's gonna make your work a lot easier.</li>
<li>The SVG morph performance is the same for both <code>.to()</code> and <code>.fromTo()</code> methods, but the ones that use the second method will start faster, because the values have been prepared
already and for the first method the processing of the two paths happens on tween start delaying the animation, so keep that in mind when working with syncing multiple tweens, the <code>.to()</code>
based morph will always start later. Of course this assumes the you cache the tween objects first and start the animation later, if not (you start the animation on object creation), both methods will
be delayed.</li>
</ul>
<h3>Drawing Stroke</h3>
<p>Next, we're going to animate the stroking of some elements. Starting with KUTE.js version 1.5.2, along with <code>&lt;path></code> shapes, <code>&lt;circle></code>, <code>&lt;ellipse></code>, <code>&lt;rect></code>,
<code>&lt;line></code>, <code>&lt;polyline></code> and <code>&lt;polygon></code> shapes are also supported; the script uses the SVG standard <code>.getTotalLength()</code> method for <code>&lt;path></code>
shapes, while the others use some helper methods. 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 style="width:600px" class="example-box-model example-box" id="draw-example" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2046 513">
<path fill="none" style="stroke:#2196F3; stroke-width:20; stroke-dashoffset: -724.077px; stroke-dasharray: 0px, 1448.15px" id="drawSVG" d="M432 64l-240 240-112-112-80 80 192 192 320-320z"/>
<circle fill="none" r="220" cx="780" cy="255" style="stroke:#4CAF50; stroke-width:20; stroke-dashoffset: -690.8px; stroke-dasharray: 0px, 1381.6px" id="drawSVG1"/>
<ellipse fill="none" rx="220" ry="100" cx="780" cy="255" style="stroke:#55c55a; stroke-width:20; stroke-dashoffset: -690.8px; stroke-dasharray: 0px, 1381.6px" id="drawSVG11"/>
<rect fill="none" width="430" height="430" x="1070" y="30" style="stroke:#FF5722; stroke-width:20; stroke-dashoffset: -860px; stroke-dasharray: 0px, 1720px" id="drawSVG2"/>
<polygon fill="none" points="1579,307 1623,117 1801,33 1978,117 2022,307 1899,460 1702,460 1579,307" style="stroke:#673AB7; stroke-width:20; stroke-dashoffset: -860px; stroke-dasharray: 0px, 1720px" id="drawSVG3"/>
</svg>
<div class="example-buttons">
<a id="drawBtn" class="btn btn-blue" href="javascript:void(0)">Start</a>
</div>
</div>
<p>Remember: the <code class="bg-indigo">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>SVG Transforms</h3>
<p>Starting with KUTE.js 1.5.2, the SVG Plugin features a new tween property for cross browser SVG transforms, but was coded as a separate set of methods for SVG only, to keep performance tight and solve
most browser inconsistencies. 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 SVG transforms
in a <a href="https://css-tricks.com/transforms-on-svg-elements/" target="_blank">reliable and cross-browser</a> supported fashion.</p>
<p>With KUTE.js 1.6.0 the SVG transform is a bigger part of the SVG Plugin for two reasons: first is the ability to use the <code>transformOrigin</code> just like for CSS3 transforms and secondly the unique
way to normalize translation to work with the transform origin in a way that the animation is just as consistent as for CSS3 transforms on non-SVG elements. Also the value processing is consistent with
the <a href="https://www.w3.org/TR/SVG/coords.html#EstablishingANewUserSpace">working draft</a>.</p>
<p>While you can still use regular <a href="examples.html">CSS3 transforms</a> for SVGs on browsers like Google Chrome, Opera and others, Firefox struggles big time with the percentage based
<code>transform-origin</code> values and ALL Internet Explorer versions have no implementation for CSS3 transforms on SVG elements.</p>
<p>KUTE.js SVG Plugin comes with a better way to animate transforms on SVGs shapes reliably on all browsers, by the use of the <code>transform</code> presentation attribute and the
<code class="bg-indigo">svgTransform</code> tween property with a special notation:</p>
<pre><code class="language-javascript">// using the svgTransform property works in all SVG enabled browsers
var tween2 = KUTE.to('shape', {svgTransform: { translate: [150,100], rotate: 45, skewX: 15, skewY: 20, scale: 1.5 }});
// regular CSS3 transforms apply to SVG elements but not all browsers fully/partially supported
var tween1 = KUTE.to('shape', { translate: [150,100], rotate: 45, skewX: 15, skewY: 20, scale: 1.5 }, { transformOrigin: '50% 50%' });
</code></pre>
<p>As you can see we have some familiar notation, but an important notice here is that <code class="bg-indigo">svgTransform</code> tween property treat all SVG transform functions as if you are using the
<code>50% 50%</code> of the shape box at all times by default, even if the default value is "0px 0px 0px" on SVGs in most browsers.</p>
<p>Perhaps the most important thing to remember is the fact that SVG tranformations always use SVG coordinates system, and the <code>transform</code> attribute accepts no measurement units such as degrees
or pixels. For these reasons the <code>transformOrigin</code> tween option can also accept array values just in case you need coordinates relative to the parent <code>&lt;svg></code> element. Also values
like <i>top left</i> values will work.</p>
<p>In the following examples we showcase the animation of CSS3 transform applied to SVG shapes (LEFT) as well as <code class="bg-indigo">svgTransform</code> based animations (RIGHT). I highly encourage you
to test all of them in all browsers, and as a word ahead, animations in Webkit browsers will look identical, while others are inconsistent or not responding to DOM changes. Let's break it down to pieces.</p>
<h4>SVG Rotation</h4>
<p>Our first chapter of the SVG transform is all about rotations, perhaps the most important part here. As of with KUTE.js 1.6.0 the <code class="bg-indigo">svgTransform</code> will only accept single value
for the angle value <code>rotate: 45</code>, the rotation will go around the shape's center point by default, again, contrary to the browsers' default value and you can set a <code>transformOrigin</code>
tween option to override the behavior.</p>
<p>The argument for this implementation is that this is something you would expect from regular HTML elements rotation and probably most needed, not to mention the amount of savings in the codebase department.
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 CSS3 transform notation and the animation clearly shows the shape rotating around it's center coordinate, as we've set <code>transformOrigin</code> option to <i>50% 50%</i>, but this
animation doesn't work in IE browsers, while in Firefox is inconsistent with the SVG coordinate system. The second tween uses the <code>rotate: 360</code> notation and the animation shows the shape rotating
around it's own central point and without any option, an animation that DO WORK in all SVG enabled browsers.</p>
<p>When for CSS3 transforms we could have used values such as <i>center bottom</i> as <code>transform-origin</code> (also not supported in all modern browsers for SVGs), the entire processing was basically in/by
the browser, however when it comes to SVGs the plugin here will compute the <code>transformOrigin</code> tween setting value accordingly to use a shape's <code>.getBBox()</code> value to determine for instance
the coordinates for <i>25% 75%</i> position or <i>center top</i>.</p>
<p>In other cases you may want to rotate shapes around the center point of the parent <code>&lt;svg></code> or <code>&lt;g></code> element, and we use it's <code>.getBBox()</code> to determine the <i>50% 50%</i>
coordinate, so here's how to deal with it:</p>
<pre><code class="language-javascript">// rotate around parent svg's "50% 50%" coordinate as transform-origin
// get the bounding box of the parent element
var svgBB = element.ownerSVGElement.getBBox(); // returns an object of the parent &lt;svg> element
// we need to know the current translate position of the element [x,y]
// in our case is:
var translation = [580,0];
// determine the X point of transform-origin for 50%
var svgOriginX = svgBB.width * 50 / 100 - translation[0];
// determine the Y point of transform-origin for 50%
var svgOriginY = svgBB.height * 50 / 100 - translation[1];
// set your rotation tween with "50% 50%" transform-origin of the parent &lt;svg> element
var rotationTween = KUTE.to(element, {svgTransform: {rotate: 150}}, { transformOrigin: [svgOriginX, svgOriginY]} );
</code></pre>
<div class="featurettes">
<svg id="svgRotate1" 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="rotateBtn1" class="btn btn-red" href="javascript:void(0)">Start</a>
</div>
</div>
<p>Note that this is the only SVG transform example in which we have adapted the <code>transform-origin</code> for the CSS3 transform rotation so that both animations look consistent in all browsers, and if you are
interested in learning about this fix, similar to the above, just we are adding "px" to the calculated value, but you better make sure to check <a href="./assets/js/svg.js">svg.js</a> file.</p>
<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 CSS3 <code>translate: 580</code> notation for the end value, while the second tween uses the <code>translate: [0,0]</code> as <code class="bg-indigo">svgTransform</code> value.
For the second example 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 both X and Y axis in a chain via regular CSS3 transforms and the second tween skews the shape on X and Y axis via the <code class="bg-indigo">svgTransform</code> tween
property. You will notice translation kicking in to set the transform origin and the example also showcases the fact that chain transformations for SVGs via <code>transform</code> attribute works just
as for the CSS3 transformations.</p>
<h4>SVG Scaling</h4>
<p>Another 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> via regular CSS3 transforms, and the second tween scales down the shape at <code>scale: 0.5</code> value via <code class="bg-indigo">svgTransform</code>.
If you inspect the elements, you will notice for the second shape translation is involved, and this is to keep <code>transform-origin</code> at an expected <i>50% 50%</i> value. A similar case as with the skews.</p>
<h4>SVG Mixed Transform Functions</h4>
<p>Our last transform example for SVGs is the mixed transformation. Just like for the other examples the plugin will try to adjust the rotation <code>transform-origin</code> to make it look as you would expect it
from regular HTML elements. Let's combine 3 functions at the same time and see what happens:</p>
<div class="featurettes">
<svg id="svgMixed" class="example-box-model example-box" style="width: 320px; overflow: visible;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1085 513" xmlns:xml="http://www.w3.org/XML/1998/namespace" xml:space="preserve" version="1.1">
<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-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="mixedBtn" class="btn btn-teal" href="javascript:void(0)">Start</a>
</div>
</div>
<p>Both shapes are scaled at <code>scale: 1.5</code>, translated to <code>translate: 250</code> and skewed at <code>skewX: -15</code>. If you inspect the elements, you will notice the second shape's translation is
different from what we've set in the tween object, and this is to keep <code>transform-origin</code> at an expected <i>50% 50%</i> value. This means that the plugin will also compensate rotation transform origin
when skews are used, so that both CSS3 transform property and SVG transform attribute have an identical animation.</p>
<h4>Chained SVG transforms</h4>
<p>The SVG Plugin does not work with SVG specific chained transform functions right away (do not confuse with tween chain), but if your SVGs only use this feature to set a custom <code>transform-origin</code>,
it should look like this:</p>
<pre><code class="language-markup">&lt;svg>
&lt;circle transform="translate(150,150) rotate(45) scale(1.2) translate(-150,-150)" r="20">&lt;/circle>
&lt;/svg>
</code></pre>
<p>Well in this case I would recommend using the values of the first translation as <code>transform-origin</code> for your tween built with the <code>.fromTo()</code> method like so:</p>
<pre><code class="language-javascript">// a possible workaround for animating a SVG element that uses chained transform functions
KUTE.fromTo(element,
{svgTransform : { translate: 0, rotate: 45, scale: 0.5 }}, // we asume the current translation is zero on both X &amp; Y axis
{svgTransform : { translate: 450, rotate: 0, scale: 1.5 }}, // we will translate the X to a 450 value and scale to 1.5
{transformOrigin: [256,256]} // tween options use the transform-origin of the target SVG element
).start();
</code></pre>
<p>Before you hit the <kbd>Start</kbd> button, make sure to check the <code>transform</code> attribute value. The below tween will reset the element's transform attribute to original value when the animation is complete.</p>
<div class="featurettes">
<svg id="svgChained" class="example-box-model example-box" style="overflow: visible;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 513 513" xmlns:xml="http://www.w3.org/XML/1998/namespace" xml:space="preserve" version="1.1">
<path 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"
transform="translate(256,256) rotate(45) scale(0.5) translate(-256,-256)"></path>
</svg>
<div class="example-buttons">
<a id="chainedBtn" class="btn btn-lime" href="javascript:void(0)">Start</a>
</div>
</div>
<p>This way we make sure to count the real current transform-origin and produce a consistent animation with the SVG coordinate system, just as the above example showcases.</p>
<h4>Recommendations for SVG Transforms</h4>
<ul>
<li>The SVG Plugin coming with KUTE.js version 1.6.0 is successfuly handling all possible combinations of transform functions, and <b>always uses same order of transform functions</b>: <code>translate</code>,
<code>rotate</code>, <code>skewX</code>, <code>skewY</code> and <code>scale</code> to keep animation consistent and with same aspect as for CSS3 transforms on non-SVG elements.</li>
<li>Keep in mind that the SVG transforms will use the center of a shape as transform origin by default, contrary to the SVG draft.</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 partialy/completely hidden while animating. You might want to set <code>overflow: visible</code>
or some browser specific tricks if that is the case.</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>Similar to the CSS3 transform animation featured in the core engine, the <code class="bg-indigo">svgTransform</code> property DOES stack transform functions for chained tween objects created with the
<code>.to()</code> method, you will have to provide only values for the functions that will change and the plugin will try to keep the unchanged values. However, there's a catch: you need to follow all
the properties and I highly recommend checking the example code for skews in the <a href="./assets/js/svg.js">svg.js</a> file.</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> tween property does not support 3D transforms, because they are not supported in all SVG enabled browsers.</li>
</ul>
<h3>SVG Plugin Tips</h3>
<ul>
<li>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.</li>
<li>Since SVG morph scripting works only with <code>path</code> or <code>glyph</code> elements, you might need a <code>convertToPath</code> feature, so
<a href="https://github.com/Waest/SVGPathConverter" target="_blank">check this out</a>.</li>
</ul>
</div>
<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 %23KUTEJS animation engine by @dnp_theme 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></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>
<!-- 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.6.0/kute.min.js"></script> KUTE CDN -->
<script src="./src/kute.min.js"></script>
<!-- some stuff -->
<script src="./src/kute-attr.min.js"></script>
<!-- some stuff -->
<script src="./src/kute-svg.min.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>