SVG动画vivus.js库使用小结(实例代码)

SVG动画vivus.js库使用整理,具体实例代码如下所示:

使用方法如图:

HTML例子代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vivus.js - test</title>
<style type="text/css">
  svg * {fill: none;stroke: currentColor;stroke-width:4;}
  .sunrise {color: #f037a5; background-color: #f8c72c;}
  .matrix  {color: #86e0c4; background-color: #181f21;}
  .electric {color: #78C9DB; background-color: #E4175B;}
  .night  {color: #D3D679; background-color: #316BD2;}
  i{ font-style:normal; color:#f00;}
  span{ color:#316BD2;}
</style>
</head>
<body>
  <div>
    <p>
    <span>var synthD</span> = new Vivus('<i>synth-dynamic</i>', {<br>
      <i>file: </i>'vivus-git/synth.svg',<br>
      <i>type: </i>'oneByOne',<br>
      duration: 200,<br>
      <i>start: </i>'manual',<br>
      <i>animTimingFunction:</i> Vivus.EASE_OUT_BOUNCE<br>
    });
    </p>
    <p>
    <span>synth-dynamic:</span>SVG的ID 或 加载外部SVG文件的父标签
    </p>
    <p>
    <span>file:</span><i>vivus-git/synth.svg</i>,如果是SVG的ID则可省略此设置,如果是加载外部SVG文件的父标签,对应的值则是SVG文件的路径
    </p>
    <p>
    <span>type:</span><br>
      对就值:<i>delayed</i> 每条路径元素绘制在同一时间用小延迟开始。这是目前默认动画。<br>
      对就值:<i>scenario-sync</i> 每一行都是同步的。他们都在同一时间开始和结束,因此得名“同步”。<br>
      对就值:<i>oneByOne</i> 每个路径元素是一个接一个。这个动画给人最好的印象的绘画。
    </p>
    <p>
    <span>start:</span>是否自动播放,可省略此设置,不设置则默认自动播放<br>
      对就值:<i>autostart</i> 默认值,自动播放<br>
      对就值:<i>manual</i> 不自动播放,需要事件触发播放
    </p>
    <p>
    <span>animTimingFunction:</span>动画效果<br>
      对就值:<i>LINEAR</i> 动画从头到尾的速度是相同的<br>
      对就值:<i>EASE</i> 动画以低速开始,然后加快,在结束前变慢。<br>
      对就值:<i>EASE_IN</i> 动画以低速开始。<br>
      对就值:<i>EASE_OUT</i> 动画以低速结束。<br>
      对就值:<i>EASE_OUT_BOUNCE</i> 动画弹性结束
    </p>
  </div>
  <div>
    <p>
      <span>synthD</span><i>.play();</i> 播放动画<br>
      <span>synthD</span><i>.reset().play();</i> 重新播放动画<br>
      <span>synthD</span><i>.play(-3);</i> 倒带,反向收回之前完成的动画
    </p>
  </div>
  <div class="matrix">
    <div>
     <p>每条路径元素绘制在同一时间用小延迟开始。这是目前默认动画。<br>vivus-git/obturateur.svg</p>
     <button onclick="obt1.reset().play();">重新播放动画</button>
     <button onclick="obt1.play(-3);">倒带</button>
    </div>
    <!--
    <div id="obt"></div>
    -->
    <div>
     <object id="obt" data="vivus-git/obturateur.svg" type="image/svg+xml" style="width: 100%; max-height: 250px;"></object>
    </div>
  </div>
  <div class="sunrise">
    <div>
     <p>每一行都是同步的。他们都在同一时间开始和结束,因此得名“同步”。<br>vivus-git/polaroid.svg</p>
     <button onclick="polaroidD.reset().play();">重新播放动画</button>
     <button onclick="polaroidD.play(-3);">倒带</button>
    </div>
    <div id="polaroid-dynamic"></div>
  </div>
  <div class="electric">
    <div>
     <p>每一行都是同步的。他们都在同一时间开始和结束,因此得名“同步”。<br>vivus-git/hi-there.svg</p>
     <button onclick="hiD.play();">播放动画</button>
     <button onclick="hiD.play(-3);">倒带</button>
    </div>
    <!--<div id="hi-dynamic" style="max-width: 300px; margin: auto;"></div>-->
    <svg height="300" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 404.7 354" enable-background="new 0 0 404.7 354" id="hi-dynamic" onclick="hiD.reset().play();">
      <!-- HI -->
      <path data-duration="10" d="M324.6,61.2c16.6,0,29.5-12.9,29.5-29.5c0-16.6-12.9-29.5-29.5-29.5c-16.6,0-29.5,12.9-29.5,29.5C295.1,48.4,308,61.2,324.6,61.2z" style="stroke-dasharray: 186px, 226px; stroke-dashoffset: 0px;"></path>
      <path data-duration="130" d="M366.2,204.2c-9.8,0-15-5.6-15-15.1V77.2h-85v28h19.5c9.8,0,8.5,2.1,8.5,11.6v72.4c0,9.5,0.5,15.1-9.3,15.1H277h-20.7c-8.5,0-14.2-4.1-14.2-12.9V52.4c0-8.5,5.7-12.3,14.2-12.3h18.8v-28h-127v28h18.1c8.5,0,9.9,2.1,9.9,8.9v56.1h-75V53.4c0-11.5,8.6-13.3,17-13.3h11v-28H2.2v28h26c8.5,0,12,2.1,12,7.9v142.2c0,8.5-3.6,13.9-12,13.9h-21v33h122v-33h-11c-8.5,0-17-4.1-17-12.2v-57.8h75v58.4c0,9.1-1.4,11.6-9.9,11.6h-18.1v33h122.9h5.9h102.2v-33H366.2z" style="stroke-dasharray: 2216px, 2256px; stroke-dashoffset: 0px;"></path>
      <path data-async="" data-delay="20" d="M358.8,82.8c11.1-4.2,18.8-14.7,18.8-27.5c0-8.5-3.4-16-8.9-21.3" style="stroke-dasharray: 60px, 100px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M124.2,105.7V77c0-11.5,9.1-13.8,17.5-13.8h10.5V44.7" style="stroke-dasharray: 84px, 124px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M147.9,40.2L171.2,63.2L175.7,63.2" style="stroke-dasharray: 38px, 78px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M295.1,32.1L275.2,12.2" style="stroke-dasharray: 29px, 69px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M266.2,204.7V75.9c0-8.5,5.2-12.8,13.7-12.8h18.3V44.7" style="stroke-dasharray: 187px, 227px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M265.9,105.2L289.2,129.2L293.7,129.2" style="stroke-dasharray: 38px, 78px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M374.2,204.7L374.2,94.2L358.8,82.8L351.2,77.2" style="stroke-dasharray: 140px, 180px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M148.2,237.2L171.2,261.2L294.6,261.2L300.5,261.2L402.2,261.2L402.2,228.2L379.2,204.2" style="stroke-dasharray: 331px, 371px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M124.2,204.7L124.2,157.2L175.7,157.2" style="stroke-dasharray: 99px, 139px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M147.7,228.2L129.2,204.2" style="stroke-dasharray: 31px, 71px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M7.2,237.3L30.2,261.2L152.2,261.2L152.2,241.7" style="stroke-dasharray: 175px, 215px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M1.9,40.2L26,63.2L39.7,63.2" style="stroke-dasharray: 48px, 88px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M129.2,12.2L148.2,33.2" style="stroke-dasharray: 29px, 69px; stroke-dashoffset: 0px;"></path>
      <path data-async="" d="M303.9,53L328.1,77.2" style="stroke-dasharray: 35px, 75px; stroke-dashoffset: 0px;"></path>
      <path d="M345.1,10.5L368.7,34" style="stroke-dasharray: 34px, 74px; stroke-dashoffset: 0px;"></path>
      <!-- there -->
      <path data-delay="30" data-duration="60" stroke-linecap="round" stroke-linejoin="round" d="M76.8,337.3c0,0,1.9,12.2,13.1,12.2c22.1,0,23.8-1.8,59-66.4c-19.7,35.7-36.4,66.2-19.3,66.2c15.2,0,22.9-14.2,28.3-23.7c3.3-0.5,24-3.2,35-25.5c4-8.1,4.1-17.8-8.1-15.2c-5.6,1.2-13.1,14.8-15.7,19.2c-7.6,12.7-22.4,45.2-22.4,45.2s10.3-22.4,21.5-22.4c15.5,0-9.4,22.4,4.7,22.4c4.9,0,11.7-11.4,16.6-20.9c7.5,4.7,19.7,1.7,24.5-8.1c10.1-20.4-14.4-12.8-24.5,8.1c-5.5,11.3-2.2,21.1,11.2,21.1c16.4,0,26.1-28.3,30.5-37.5c9.9,2.5,14,2.5,22.7-1.1c-3.5,5.1-24,38.1-8.3,38.1c6.7,0,11.7-11.4,16.6-20.9c7.5,4.7,19.7,1.7,24.5-8.1c10.1-20.4-14.4-12.8-24.5,8.1c-5.5,11.3-2.2,21.1,11.2,21.1c16.4,0,20.6-4,24.7-10.5" style="stroke-dasharray: 851px, 891px; stroke-dashoffset: 0px;"></path>
      <path stroke-linecap="round" stroke-linejoin="round" d="M157.3,300.8c3.8-2.3-29,0.8-35.6,3.2" style="stroke-dasharray: 37px, 77px; stroke-dashoffset: 0px;"></path>
    </svg>
  </div>
  <div class="night">
    <div>
     <p>每个路径元素是一个接一个。这个动画给人最好的印象的绘画。<br>vivus-git/synth.svg</p>
     <button onclick="synthD.play();">播放动画</button>
     <button onclick="synthD.play(-3);">倒带</button>
    </div>
    <div id="synth-dynamic" style="max-width: 400px; margin: auto;"></div>
  </div>
  <!--<script src="vivus.js"></script>-->
  <script src="http://cdn.jsdelivr.net/vivus/latest/vivus.min.js"></script>
  <script>
   if (window.location.protocol === 'file:') {
     alert('请使用HTTP服务器服务(http://localhost/)访问此页面。');
   }
   var obt1 = new Vivus('obt', {
    /*
    加载SVG外部文件的方法:
    1、有object标签则 不用 加载SVG外部文件的代码:file: 'vivus-git/obturateur.svg'
    以上HTML中有此代码:<object id="obt" data="vivus-git/obturateur.svg" type="image/svg+xml" style="width: 100%; max-height: 250px;"></object>
    2、没有object标签则 要 加载SVG外部文件的代码:file: 'vivus-git/obturateur.svg'
    以上HTML中有此代码 已注释:<div id="obt"></div>
    */
    //file: 'vivus-git/obturateur.svg',
    type: 'delayed',//每条路径元素绘制在同一时间用小延迟开始。这是目前默认动画。
    duration: 150,
    //start: 'autostart'
   });
   var polaroidD = new Vivus('polaroid-dynamic', {
    file: 'vivus-git/polaroid.svg',
    //file: 'vivus-git/111.svg',
    type: 'scenario-sync',//每一行都是同步的。他们都在同一时间开始和结束,因此得名“同步”。
    duration: 20,
    start: 'autostart'
   });
   var hiD = new Vivus('hi-dynamic', {
    /*
    1、SVG内部标签, 不用 加载SVG外部文件的代码:file: 'vivus-git/hi-there.svg'
    以上HTML中有此代码:<svg height="300" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 404.7 354" enable-background="new 0 0 404.7 354" id="hi-dynamic" onclick="hiD.reset().play();">
    2、加载SVG外部文件的方法:file: 'vivus-git/hi-there.svg'
    以上HTML中有此代码 已注释:<div id="hi-dynamic" style="max-width: 300px; margin: auto;"></div>
    */
    //file: 'vivus-git/hi-there.svg',
    type: 'scenario-sync',
    duration: 20,
    start: 'manual'
   });
   var synthD = new Vivus('synth-dynamic', {
    file: 'vivus-git/synth.svg',
    type: 'oneByOne',//每个路径元素是一个接一个。这个动画给人最好的印象的绘画。
    duration: 200,
    start: 'manual',
    animTimingFunction: Vivus.EASE_OUT
   });
//   function easeOutBounce (x) {
//    var base = -Math.cos(x * (0.5 * Math.PI)) + 1;
//    var rate = Math.pow(base,1.5);
//    var rateR = Math.pow(1 - x, 2);
//    var progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
//    return (1- rateR) + (progress * rateR);
//   }
  </script>
 </body>
</html>
hi-there.svg代码:
[html] view plain copy
<svg height="300" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 404.7 354" enable-background="new 0 0 404.7 354">
 <g stroke="#f9f9f9" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10">
  <!-- HI -->
  <path data-duration="10" d="M324.6,61.2c16.6,0,29.5-12.9,29.5-29.5c0-16.6-12.9-29.5-29.5-29.5c-16.6,0-29.5,12.9-29.5,29.5C295.1,48.4,308,61.2,324.6,61.2z"/>
  <path data-duration="130" d="M366.2,204.2c-9.8,0-15-5.6-15-15.1V77.2h-85v28h19.5c9.8,0,8.5,2.1,8.5,11.6v72.4c0,9.5,0.5,15.1-9.3,15.1H277h-20.7c-8.5,0-14.2-4.1-14.2-12.9V52.4c0-8.5,5.7-12.3,14.2-12.3h18.8v-28h-127v28h18.1c8.5,0,9.9,2.1,9.9,8.9v56.1h-75V53.4c0-11.5,8.6-13.3,17-13.3h11v-28H2.2v28h26c8.5,0,12,2.1,12,7.9v142.2c0,8.5-3.6,13.9-12,13.9h-21v33h122v-33h-11c-8.5,0-17-4.1-17-12.2v-57.8h75v58.4c0,9.1-1.4,11.6-9.9,11.6h-18.1v33h122.9h5.9h102.2v-33H366.2z"/>
  <path data-async="" data-delay="20" d="M358.8,82.8c11.1-4.2,18.8-14.7,18.8-27.5c0-8.5-3.4-16-8.9-21.3"/>
  <path data-async="" d="M124.2,105.7V77c0-11.5,9.1-13.8,17.5-13.8h10.5V44.7"/>
  <polyline data-async="" points="147.9,40.2 171.2,63.2 175.7,63.2"/>
  <line data-async="" x1="295.1" y1="32.1" x2="275.2" y2="12.2"/>
  <path data-async="" d="M266.2,204.7V75.9c0-8.5,5.2-12.8,13.7-12.8h18.3V44.7"/>
  <polyline data-async="" points="265.9,105.2 289.2,129.2 293.7,129.2"/>
  <polyline data-async="" points="374.2,204.7 374.2,94.2 358.8,82.8 351.2,77.2"/>
  <polyline data-async="" points="148.2,237.2 171.2,261.2 294.6,261.2 300.5,261.2 402.2,261.2 402.2,228.2 379.2,204.2"/>
  <polyline data-async="" points="124.2,204.7 124.2,157.2 175.7,157.2"/>
  <line data-async="" x1="147.7" y1="228.2" x2="129.2" y2="204.2"/>
  <polyline data-async="" points="7.2,237.3 30.2,261.2 152.2,261.2 152.2,241.7"/>
  <polyline data-async="" points="1.9,40.2 26,63.2 39.7,63.2"/>
  <line data-async="" x1="129.2" y1="12.2" x2="148.2" y2="33.2"/>
  <line data-async="" x1="303.9" y1="53" x2="328.1" y2="77.2"/>
  <line x1="345.1" y1="10.5" x2="368.7" y2="34"/>
  <!-- there -->
  <path data-delay="30" data-duration="60" stroke-linecap="round" stroke-linejoin="round" d="M76.8,337.3c0,0,1.9,12.2,13.1,12.2c22.1,0,23.8-1.8,59-66.4c-19.7,35.7-36.4,66.2-19.3,66.2c15.2,0,22.9-14.2,28.3-23.7c3.3-0.5,24-3.2,35-25.5c4-8.1,4.1-17.8-8.1-15.2c-5.6,1.2-13.1,14.8-15.7,19.2c-7.6,12.7-22.4,45.2-22.4,45.2s10.3-22.4,21.5-22.4c15.5,0-9.4,22.4,4.7,22.4c4.9,0,11.7-11.4,16.6-20.9c7.5,4.7,19.7,1.7,24.5-8.1c10.1-20.4-14.4-12.8-24.5,8.1c-5.5,11.3-2.2,21.1,11.2,21.1c16.4,0,26.1-28.3,30.5-37.5c9.9,2.5,14,2.5,22.7-1.1c-3.5,5.1-24,38.1-8.3,38.1c6.7,0,11.7-11.4,16.6-20.9c7.5,4.7,19.7,1.7,24.5-8.1c10.1-20.4-14.4-12.8-24.5,8.1c-5.5,11.3-2.2,21.1,11.2,21.1c16.4,0,20.6-4,24.7-10.5"/>
  <path stroke-linecap="round" stroke-linejoin="round" d="M157.3,300.8c3.8-2.3-29,0.8-35.6,3.2"/>
 </g>
</svg>
obturateur.svg代码:
[html] view plain copy
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="100%" height="200px" style="height:200px;" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
 <g stroke="#f60" fill="none" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" >
  <circle cx="100" cy="100" r="90"/>
  <circle cx="100" cy="100" r="85.74"/>
  <circle cx="100" cy="100" r="72.947"/>
  <circle cx="100" cy="100" r="39.74"/>
  <line x1="34.042" y1="131.189" x2="67.047" y2="77.781"/>
  <line x1="31.306" y1="75.416" x2="92.41" y2="60.987"/>
  <line x1="68.81" y1="34.042" x2="122.219" y2="67.046"/>
  <line x1="124.584" y1="31.305" x2="139.013" y2="92.409"/>
  <line x1="165.957" y1="68.809" x2="132.953" y2="122.219"/>
  <line x1="168.693" y1="124.584" x2="107.59" y2="139.012"/>
  <line x1="131.19" y1="165.957" x2="77.781" y2="132.953"/>
  <line x1="75.417" y1="168.693" x2="60.987" y2="107.59"/>
 </g>
</svg>
polaroid.svg代码:
[html] view plain copy
<svg id="polaroid" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" style="height:200px;" viewBox="0 0 200 160" enable-background="new 0 0 200 160">
 <g stroke="#f9f9f9" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10">
  <!-- Case -->
  <!-- The case items will be drawn at the same time (attribute `data-async` on each tag) with a custom duration of 40 frames (attribute `data-duration`). WARNING: When you want to draw a bloc asynchronously (like here), the last item need to be `data-async` free. Otherwise the following tags will also start at the same time. I know it's a bit confusing, play a bit with it and you'll see. -->
  <path data-async="" data-duration="40" d="
   M106.725,104.742c-0.773,2.498-3.586,4.229-6.285,3.867L12.473,96.802c-2.699-0.363-4.262-2.682-3.49-5.18l25.164-81.436
   c0.771-2.496,3.584-4.229,6.283-3.866l87.966,11.808c2.699,0.362,4.264,2.68,3.49,5.179L106.725,104.742z"/>
  <path data-async="" data-duration="40" d="
   M101.02,123.207c-0.773,2.5-3.587,4.23-6.286,3.867L6.766,115.27c-2.699-0.363-4.26-2.682-3.488-5.182l2.91-9.417
   c0.771-2.499,3.585-4.23,6.285-3.87l87.967,11.809c2.699,0.361,4.261,2.682,3.49,5.18L101.02,123.207z"/>
  <line data-async="" data-duration="40" x1="103.377" y1="128.225" x2="154.768" y2="155.32"/>
  <line data-async="" data-duration="40" x1="109.852" y1="112.684" x2="155.035" y2="136.906"/>
  <path data-async="" data-duration="40" d="
   M9.096,120.207l47.932,21.994c0,0,98.06,12.414,97.74,13.119c-0.318,0.709,5.426-16.205,5.426-16.205l-2.646-96.842
   c-1.098-7.587-2.467-11.8-8.559-15.024l-12.635-6.604"/>
  <path data-async="" data-duration="40" d="
   M161.586,38.135l30.717,16.085c0,0,5.295,2.323,4.543,6.504l-3.215,10.527c-0.648,2.621-2.939,4.988-8.229,2.798l-9.154-4.701
   l-11.834,56.441"/>
  <path data-duration="40" d="
   M183.148,49.518c0,0,5.295,2.324,4.543,6.506l-3.215,10.526c-0.648,2.622-2.938,4.988-8.229,2.798"/>
  <!-- Lens -->
  <!-- All item will be drawn line by line, with an exception for the first one, a little delay (attribute `data-delay) to make a break between the drawing of the case and the start of the lens part -->
  <path data-delay="20" d="
   M87.176,56.143C83.274,68.78,69.043,77.538,55.395,75.706S33.846,62.146,37.75,49.511c3.903-12.637,18.135-21.392,31.783-19.562
   C83.181,31.782,91.081,43.51,87.176,56.143z"/>
  <path d="
   M92.745,56.891c-4.785,15.48-22.219,26.213-38.942,23.969C37.079,78.615,27.4,64.245,32.184,48.763
   c4.783-15.48,22.218-26.211,38.94-23.968C87.848,27.041,97.528,41.411,92.745,56.891z"/>
  <path d="
   M78.99,26.933c16.169,7.426,19.398,10.989,22.026,20.105c1.283,4.449,1.271,9.411-0.3,14.489
   c-4.783,15.479-22.217,26.213-38.941,23.969c-8.68-1.165-21.171-7.963-25.613-14.055"/>
  <path d="
   M42.602,50.162c3.137-10.157,14.573-17.193,25.543-15.722"/>
  <!-- Flash -->
  <!-- This tag does not have any extra attribute. So it will start when the previous tag is finished. His duration and delay will be the one given in the options. -->
  <path d="
   M103.789,29.275c-0.568,1.841,0.582,3.549,2.57,3.818l12.807,1.72c1.988,0.266,4.062-1.012,4.633-2.851l1.66-5.38
   c0.568-1.843-0.582-3.551-2.57-3.816l-12.807-1.72c-1.988-0.268-4.062,1.01-4.633,2.85L103.789,29.275z"/>
  <!-- Output -->
  <!-- Same case as Flash -->
  <path d="
   M11.129,105.791c-0.297,0.965,0.305,1.855,1.346,1.994l81.446,10.932c1.038,0.141,2.123-0.527,2.42-1.49l0,0
   c0.298-0.961-0.304-1.855-1.343-1.996l-81.447-10.93C12.51,104.16,11.426,104.828,11.129,105.791L11.129,105.791z"/>
  <!-- Design (color lines on the front) -->
  <!-- All the lines will start at the same time, because they all have the attribute `data-async` -->
  <line data-async="" x1="47.583" y1="101.505" x2="51.561" y2="88.267"/>
  <line data-async="" x1="53.391" y1="102.326" x2="57.047" y2="90.125"/>
  <line data-async="" x1="59.224" y1="103.068" x2="62.749" y2="91.295"/>
  <line data-async="" x1="65.057" y1="103.814" x2="69.015" y2="90.637"/>
  <line data-async="" x1="72.87" y1="19.969" x2="75.497" y2="11.082"/>
  <line data-async="" x1="78.512" y1="21.325" x2="81.317" y2="11.868"/>
  <line data-async="" x1="83.833" y1="23.718" x2="87.16" y2="12.582"/>
  <line data-async="" x1="89.145" y1="26.141" x2="92.939" y2="13.498"/>
 </g>
</svg>
synth.svg代码:
[html] view plain copy
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="378.995px" height="259.5px" viewBox="0 0 378.995 259.5" enable-background="new 0 0 378.995 259.5" xml:space="preserve">
<g id="Synth">
  <path fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
    M375.5,108.934c1.549,2.693,0.627,5.739-2.059,6.804L72.043,235.257c-2.685,1.064-6.116-0.254-7.665-2.946L5.362,129.69
    c-1.548-2.692-0.625-5.737,2.059-6.802L308.818,3.369c2.686-1.065,6.117,0.254,7.666,2.946L375.5,108.934z"/>
  <path fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
    M376.246,111.47l-2.068,18.344c0,0-0.621,5.361-4.932,7.726L69.601,256.365c-2.685,1.064-6.116-0.254-7.665-2.946L3.693,152.145
    c-1.548-2.692-0.878-9.891-0.878-9.891l0.82-7.014"/>
    <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="373.785" y1="112.765" x2="371.715" y2="130.65"/>
    <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="70.318" y1="250.17" x2="371.715" y2="130.65"/>
    <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="319.578" y1="22.078" x2="19.852" y2="140.935"/>
    <polyline fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
    19.852,140.935 72.387,232.284 70.318,250.17   "/>
    <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="371.715" y1="130.65" x2="365.053" y2="119.063"/>
  <g id="octaves_1_">
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="93.572" y1="226.72" x2="73.09" y2="191.106"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="114.616" y1="218.126" x2="94.134" y2="182.512"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="136.629" y1="209.646" x2="82.765" y2="115.986"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="158.158" y1="201.108" x2="137.674" y2="165.493"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="179.688" y1="192.572" x2="159.203" y2="156.957"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="201.213" y1="184.034" x2="180.732" y2="148.419"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="222.742" y1="175.497" x2="168.879" y2="81.838"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="244.27" y1="166.959" x2="223.789" y2="131.346"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="265.799" y1="158.423" x2="245.318" y2="122.809"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="287.328" y1="149.886" x2="233.463" y2="56.226"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="308.855" y1="141.349" x2="288.375" y2="105.734"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="330.385" y1="132.812" x2="309.902" y2="97.197"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="351.912" y1="124.274" x2="331.432" y2="88.66"/>
      <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="373.441" y1="115.737" x2="319.578" y2="22.078"/>
  </g>
  <g id="bemols_1_">
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        67.427,190.815 35.241,134.85 39.708,133.061 44.176,131.271 76.24,177.929 76.362,187.236       "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        69.3,180.708 36.616,135.539 44.606,132.34 76.24,177.929       "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="69.077" y1="183.09" x2="68.222" y2="187.702"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        89.117,182.213 56.931,126.247 61.398,124.458 65.866,122.669 97.93,169.326 98.052,178.634      "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        90.99,172.105 58.306,126.937 66.295,123.736 97.93,169.326      "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="90.767" y1="174.487" x2="89.912" y2="179.1"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        132.012,165.204 99.826,109.238 104.293,107.449 108.762,105.661 140.825,152.317 140.948,161.625     "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        133.885,155.098 101.202,109.928 109.191,106.728 140.825,152.317       "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="133.661" y1="157.479" x2="132.807" y2="162.091"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        153.541,156.666 121.354,100.7 125.821,98.911 130.289,97.122 162.354,143.779 162.475,153.088       "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        155.416,146.559 122.729,101.39 130.719,98.19 162.354,143.779      "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="155.191" y1="148.94" x2="154.335" y2="153.554"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        175.068,148.129 142.881,92.164 147.348,90.374 151.817,88.585 183.881,135.242 184.004,144.551      "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        176.941,138.021 144.256,92.853 152.247,89.653 183.881,135.242      "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="176.719" y1="140.403" x2="175.863" y2="145.017"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        218.127,131.056 185.939,75.089 190.406,73.3 194.875,71.512 226.938,118.169 227.061,127.476     "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        220,120.948 187.314,75.778 195.305,72.579 226.938,118.169      "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="219.775" y1="123.329" x2="218.922" y2="127.942"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        239.656,122.518 207.469,66.553 211.936,64.763 216.402,62.975 248.467,109.631 248.59,118.939       "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        241.529,112.411 208.844,67.241 216.834,64.042 248.467,109.631      "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="241.305" y1="114.792" x2="240.449" y2="119.405"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        282.713,105.443 250.525,49.478 254.992,47.688 259.459,45.9 291.523,92.558 291.646,101.864      "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        284.584,95.337 251.902,50.168 259.891,46.968 291.523,92.558       "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="284.361" y1="97.718" x2="283.508" y2="102.33"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        304.24,96.906 272.055,40.941 276.52,39.151 280.988,37.363 313.053,84.02 313.174,93.328     "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        306.113,86.8 273.43,41.631 281.42,38.431 313.053,84.02     "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="305.891" y1="89.181" x2="305.035" y2="93.794"/>
    </g>
    <g>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        325.768,88.369 293.582,32.404 298.049,30.614 302.518,28.825 334.58,75.482 334.703,84.791      "/>
        <polygon fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
        327.641,78.262 294.957,33.093 302.947,29.894 334.58,75.482     "/>
        <line fill="none" stroke="#241F20" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="327.418" y1="80.644" x2="326.562" y2="85.257"/>
    </g>
  </g>
</g>
</svg>
(vivus.min.js)CDN引用地址:http://cdn.jsdelivr.net/vivus/latest/vivus.min.js
vivus.js代码:
[html] view plain copy
/**
 * vivus - JavaScript library to make drawing animation on SVG
 * @version v0.4.0
 * @link https://github.com/maxwellito/vivus
 * @license MIT
 */
'use strict';
(function (window, document) {
 'use strict';
/**
 * Pathformer
 * Beta version
 *
 * Take any SVG version 1.1 and transform
 * child elements to 'path' elements
 *
 * This code is purely forked from
 * https://github.com/Waest/SVGPathConverter
 */
/**
 * Class constructor
 *
 * @param {DOM|String} element Dom element of the SVG or id of it
 */
function Pathformer(element) {
 // Test params
 if (typeof element === 'undefined') {
  throw new Error('Pathformer [constructor]: "element" parameter is required');
 }
 // Set the element
 if (element.constructor === String) {
  element = document.getElementById(element);
  if (!element) {
   throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
  }
 }
 if (element.constructor instanceof window.SVGElement || /^svg$/i.test(element.nodeName)) {
  this.el = element;
 } else {
  throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
 }
 // Start
 this.scan(element);
}
/**
 * List of tags which can be transformed
 * to path elements
 *
 * @type {Array}
 */
Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
/**
 * List of attribute names which contain
 * data. This array list them to check if
 * they contain bad values, like percentage.
 *
 * @type {Array}
 */
Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', 'y1', 'y2'];
/**
 * Finds the elements compatible for transform
 * and apply the liked method
 *
 * @param {object} options Object from the constructor
 */
Pathformer.prototype.scan = function (svg) {
 var fn, element, pathData, pathDom,
   elements = svg.querySelectorAll(this.TYPES.join(','));
 for (var i = 0; i < elements.length; i++) {
  element = elements[i];
  fn = this[element.tagName.toLowerCase() + 'ToPath'];
  pathData = fn(this.parseAttr(element.attributes));
  pathDom = this.pathMaker(element, pathData);
  element.parentNode.replaceChild(pathDom, element);
 }
};
/**
 * Read `line` element to extract and transform
 * data, to make it ready for a `path` object.
 *
 * @param {DOMelement} element Line element to transform
 * @return {object}       Data for a `path` element
 */
Pathformer.prototype.lineToPath = function (element) {
 var newElement = {},
   x1 = element.x1 || 0,
   y1 = element.y1 || 0,
   x2 = element.x2 || 0,
   y2 = element.y2 || 0;
 newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
 return newElement;
};
/**
 * Read `rect` element to extract and transform
 * data, to make it ready for a `path` object.
 * The radius-border is not taken in charge yet.
 * (your help is more than welcomed)
 *
 * @param {DOMelement} element Rect element to transform
 * @return {object}       Data for a `path` element
 */
Pathformer.prototype.rectToPath = function (element) {
 var newElement = {},
   x   = parseFloat(element.x)   || 0,
   y   = parseFloat(element.y)   || 0,
   width = parseFloat(element.width) || 0,
   height = parseFloat(element.height) || 0;
 newElement.d = 'M' + x + ' ' + y + ' ';
 newElement.d += 'L' + (x + width) + ' ' + y + ' ';
 newElement.d += 'L' + (x + width) + ' ' + (y + height) + ' ';
 newElement.d += 'L' + x + ' ' + (y + height) + ' Z';
 return newElement;
};
/**
 * Read `polyline` element to extract and transform
 * data, to make it ready for a `path` object.
 *
 * @param {DOMelement} element Polyline element to transform
 * @return {object}       Data for a `path` element
 */
Pathformer.prototype.polylineToPath = function (element) {
 var newElement = {},
   points = element.points.trim().split(' '),
   i, path;
 // Reformatting if points are defined without commas
 if (element.points.indexOf(',') === -1) {
  var formattedPoints = [];
  for (i = 0; i < points.length; i+=2) {
   formattedPoints.push(points[i] + ',' + points[i+1]);
  }
  points = formattedPoints;
 }
 // Generate the path.d value
 path = 'M' + points[0];
 for(i = 1; i < points.length; i++) {
  if (points[i].indexOf(',') !== -1) {
   path += 'L' + points[i];
  }
 }
 newElement.d = path;
 return newElement;
};
/**
 * Read `polygon` element to extract and transform
 * data, to make it ready for a `path` object.
 * This method rely on polylineToPath, because the
 * logic is similar. The path created is just closed,
 * so it needs an 'Z' at the end.
 *
 * @param {DOMelement} element Polygon element to transform
 * @return {object}       Data for a `path` element
 */
Pathformer.prototype.polygonToPath = function (element) {
 var newElement = Pathformer.prototype.polylineToPath(element);
 newElement.d += 'Z';
 return newElement;
};
/**
 * Read `ellipse` element to extract and transform
 * data, to make it ready for a `path` object.
 *
 * @param {DOMelement} element ellipse element to transform
 * @return {object}       Data for a `path` element
 */
Pathformer.prototype.ellipseToPath = function (element) {
 var newElement = {},
   rx = parseFloat(element.rx) || 0,
   ry = parseFloat(element.ry) || 0,
   cx = parseFloat(element.cx) || 0,
   cy = parseFloat(element.cy) || 0,
   startX = cx - rx,
   startY = cy,
   endX = parseFloat(cx) + parseFloat(rx),
   endY = cy;
 newElement.d = 'M' + startX + ',' + startY +
         'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
         'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
 return newElement;
};
/**
 * Read `circle` element to extract and transform
 * data, to make it ready for a `path` object.
 *
 * @param {DOMelement} element Circle element to transform
 * @return {object}       Data for a `path` element
 */
Pathformer.prototype.circleToPath = function (element) {
 var newElement = {},
   r = parseFloat(element.r) || 0,
   cx = parseFloat(element.cx) || 0,
   cy = parseFloat(element.cy) || 0,
   startX = cx - r,
   startY = cy,
   endX = parseFloat(cx) + parseFloat(r),
   endY = cy;
 newElement.d = 'M' + startX + ',' + startY +
         'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
         'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
 return newElement;
};
/**
 * Create `path` elements form original element
 * and prepared objects
 *
 * @param {DOMelement} element Original element to transform
 * @param {object} pathData   Path data (from `toPath` methods)
 * @return {DOMelement}     Path element
 */
Pathformer.prototype.pathMaker = function (element, pathData) {
 var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
 for(i = 0; i < element.attributes.length; i++) {
  attr = element.attributes[i];
  if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
   pathTag.setAttribute(attr.name, attr.value);
  }
 }
 for(i in pathData) {
  pathTag.setAttribute(i, pathData[i]);
 }
 return pathTag;
};
/**
 * Parse attributes of a DOM element to
 * get an object of attribute => value
 *
 * @param {NamedNodeMap} attributes Attributes object from DOM element to parse
 * @return {object}         Object of attributes
 */
Pathformer.prototype.parseAttr = function (element) {
 var attr, output = {};
 for (var i = 0; i < element.length; i++) {
  attr = element[i];
  // Check if no data attribute contains '%', or the transformation is impossible
  if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
   throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
  }
  output[attr.name] = attr.value;
 }
 return output;
};
 'use strict';
var requestAnimFrame, cancelAnimFrame, parsePositiveInt;
/**
 * Vivus
 * Beta version
 *
 * Take any SVG and make the animation
 * to give give the impression of live drawing
 *
 * This in more than just inspired from codrops
 * At that point, it's a pure fork.
 */
/**
 * Class constructor
 * option structure
 *  type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
 *  duration: <int> (in frames)
 *  start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
 *  delay: <int> (delay between the drawing of first and last path)
 *  dashGap <integer> whitespace extra margin between dashes
 *  pathTimingFunction <function> timing animation function for each path element of the SVG
 *  animTimingFunction <function> timing animation function for the complete SVG
 *  forceRender <boolean> force the browser to re-render all updated path items
 *  selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
 *
 * The attribute 'type' is by default on 'delayed'.
 * - 'delayed'
 *  all paths are draw at the same time but with a
 *  little delay between them before start
 * - 'sync'
 *  all path are start and finish at the same time
 * - 'oneByOne'
 *  only one path is draw at the time
 *  the end of the first one will trigger the draw
 *  of the next one
 *
 * All these values can be overwritten individually
 * for each path item in the SVG
 * The value of frames will always take the advantage of
 * the duration value.
 * If you fail somewhere, an error will be thrown.
 * Good luck.
 *
 * @constructor
 * @this {Vivus}
 * @param {DOM|String}  element Dom element of the SVG or id of it
 * @param {Object}    options Options about the animation
 * @param {Function}   callback Callback for the end of the animation
 */
function Vivus (element, options, callback) {
 // Setup
 this.isReady = false;
 this.setElement(element, options);
 this.setOptions(options);
 this.setCallback(callback);
 if (this.isReady) {
  this.init();
 }
}
/**
 * Timing functions
 **************************************
 *
 * Default functions to help developers.
 * It always take a number as parameter (between 0 to 1) then
 * return a number (between 0 and 1)
 */
Vivus.LINEAR     = function (x) {return x;};
Vivus.EASE      = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
Vivus.EASE_OUT    = function (x) {return 1 - Math.pow(1-x, 3);};
Vivus.EASE_IN     = function (x) {return Math.pow(x, 3);};
Vivus.EASE_OUT_BOUNCE = function (x) {
 var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
  rate = Math.pow(base,1.5),
  rateR = Math.pow(1 - x, 2),
  progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
 return (1- rateR) + (progress * rateR);
};
/**
 * Setters
 **************************************
 */
/**
 * Check and set the element in the instance
 * The method will not return anything, but will throw an
 * error if the parameter is invalid
 *
 * @param {DOM|String}  element SVG Dom element or id of it
 */
Vivus.prototype.setElement = function (element, options) {
 // Basic check
 if (typeof element === 'undefined') {
  throw new Error('Vivus [constructor]: "element" parameter is required');
 }
 // Set the element
 if (element.constructor === String) {
  element = document.getElementById(element);
  if (!element) {
   throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
  }
 }
 this.parentEl = element;
 // Create the object element if the property `file` exists in the options object
 if (options && options.file) {
  var objElm = document.createElement('object');
  objElm.setAttribute('type', 'image/svg+xml');
  objElm.setAttribute('data', options.file);
  objElm.setAttribute('built-by-vivus', 'true');
  element.appendChild(objElm);
  element = objElm;
 }
 switch (element.constructor) {
 case window.SVGSVGElement:
 case window.SVGElement:
  this.el = element;
  this.isReady = true;
  break;
 case window.HTMLObjectElement:
  // If we have to wait for it
  var onLoad, self;
  self = this;
  onLoad = function (e) {
   if (self.isReady) {
    return;
   }
   self.el = element.contentDocument && element.contentDocument.querySelector('svg');
   if (!self.el && e) {
    throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
   }
   else if (self.el) {
    if (element.getAttribute('built-by-vivus')) {
     self.parentEl.insertBefore(self.el, element);
     self.parentEl.removeChild(element);
     self.el.setAttribute('width', '100%');
     self.el.setAttribute('height', '100%');
    }
    self.isReady = true;
    self.init();
    return true;
   }
  };
  if (!onLoad()) {
   element.addEventListener('load', onLoad);
  }
  break;
 default:
  throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
 }
};
/**
 * Set up user option to the instance
 * The method will not return anything, but will throw an
 * error if the parameter is invalid
 *
 * @param {object} options Object from the constructor
 */
Vivus.prototype.setOptions = function (options) {
 var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
 var allowedStarts = ['inViewport', 'manual', 'autostart'];
 // Basic check
 if (options !== undefined && options.constructor !== Object) {
  throw new Error('Vivus [constructor]: "options" parameter must be an object');
 }
 else {
  options = options || {};
 }
 // Set the animation type
 if (options.type && allowedTypes.indexOf(options.type) === -1) {
  throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
 }
 else {
  this.type = options.type || allowedTypes[0];
 }
 // Set the start type
 if (options.start && allowedStarts.indexOf(options.start) === -1) {
  throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
 }
 else {
  this.start = options.start || allowedStarts[0];
 }
 this.isIE     = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
 this.duration   = parsePositiveInt(options.duration, 120);
 this.delay    = parsePositiveInt(options.delay, null);
 this.dashGap   = parsePositiveInt(options.dashGap, 1);
 this.forceRender = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
 this.reverseStack = !!options.reverseStack;
 this.selfDestroy = !!options.selfDestroy;
 this.onReady   = options.onReady;
 this.map     = [];
 this.frameLength = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
 this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
 this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
 this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
 if (this.delay >= this.duration) {
  throw new Error('Vivus [constructor]: delay must be shorter than duration');
 }
};
/**
 * Set up callback to the instance
 * The method will not return enything, but will throw an
 * error if the parameter is invalid
 *
 * @param {Function} callback Callback for the animation end
 */
Vivus.prototype.setCallback = function (callback) {
 // Basic check
 if (!!callback && callback.constructor !== Function) {
  throw new Error('Vivus [constructor]: "callback" parameter must be a function');
 }
 this.callback = callback || function () {};
};
/**
 * Core
 **************************************
 */
/**
 * Map the svg, path by path.
 * The method return nothing, it just fill the
 * `map` array. Each item in this array represent
 * a path element from the SVG, with informations for
 * the animation.
 *
 * ```
 * [
 *  {
 *   el: <DOMobj> the path element
 *   length: <number> length of the path line
 *   startAt: <number> time start of the path animation (in frames)
 *   duration: <number> path animation duration (in frames)
 *  },
 *  ...
 * ]
 * ```
 *
 */
Vivus.prototype.mapping = function () {
 var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
 timePoint = totalLength = lengthMeter = 0;
 paths = this.el.querySelectorAll('path');
 for (i = 0; i < paths.length; i++) {
  path = paths[i];
  if (this.isInvisible(path)) {
   continue;
  }
  pathObj = {
   el: path,
   length: Math.ceil(path.getTotalLength())
  };
  // Test if the path length is correct
  if (isNaN(pathObj.length)) {
   if (window.console && console.warn) {
    console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
   }
   continue;
  }
  this.map.push(pathObj);
  path.style.strokeDasharray = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
  path.style.strokeDashoffset = pathObj.length + this.dashGap;
  pathObj.length += this.dashGap;
  totalLength += pathObj.length;
  this.renderPath(i);
 }
 totalLength = totalLength === 0 ? 1 : totalLength;
 this.delay = this.delay === null ? this.duration / 3 : this.delay;
 this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
 // Reverse stack if asked
 if (this.reverseStack) {
  this.map.reverse();
 }
 for (i = 0; i < this.map.length; i++) {
  pathObj = this.map[i];
  switch (this.type) {
  case 'delayed':
   pathObj.startAt = this.delayUnit * i;
   pathObj.duration = this.duration - this.delay;
   break;
  case 'oneByOne':
   pathObj.startAt = lengthMeter / totalLength * this.duration;
   pathObj.duration = pathObj.length / totalLength * this.duration;
   break;
  case 'sync':
  case 'async':
  case 'nsync':
   pathObj.startAt = 0;
   pathObj.duration = this.duration;
   break;
  case 'scenario-sync':
   path = pathObj.el;
   pAttrs = this.parseAttr(path);
   pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
   pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
   timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
   this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
   break;
  case 'scenario':
   path = pathObj.el;
   pAttrs = this.parseAttr(path);
   pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
   pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
   this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
   break;
  }
  lengthMeter += pathObj.length;
  this.frameLength = this.frameLength || this.duration;
 }
};
/**
 * Interval method to draw the SVG from current
 * position of the animation. It update the value of
 * `currentFrame` and re-trace the SVG.
 *
 * It use this.handle to store the requestAnimationFrame
 * and clear it one the animation is stopped. So this
 * attribute can be used to know if the animation is
 * playing.
 *
 * Once the animation at the end, this method will
 * trigger the Vivus callback.
 *
 */
Vivus.prototype.drawer = function () {
 var self = this;
 this.currentFrame += this.speed;
 if (this.currentFrame <= 0) {
  this.stop();
  this.reset();
 } else if (this.currentFrame >= this.frameLength) {
  this.stop();
  this.currentFrame = this.frameLength;
  this.trace();
  if (this.selfDestroy) {
   this.destroy();
  }
 } else {
  this.trace();
  this.handle = requestAnimFrame(function () {
   self.drawer();
  });
  return;
 }
 this.callback(this);
 if (this.instanceCallback) {
  this.instanceCallback(this);
  this.instanceCallback = null;
 }
};
/**
 * Draw the SVG at the current instant from the
 * `currentFrame` value. Here is where most of the magic is.
 * The trick is to use the `strokeDashoffset` style property.
 *
 * For optimisation reasons, a new property called `progress`
 * is added in each item of `map`. This one contain the current
 * progress of the path element. Only if the new value is different
 * the new value will be applied to the DOM element. This
 * method save a lot of resources to re-render the SVG. And could
 * be improved if the animation couldn't be played forward.
 *
 */
Vivus.prototype.trace = function () {
 var i, progress, path, currentFrame;
 currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
 for (i = 0; i < this.map.length; i++) {
  path = this.map[i];
  progress = (currentFrame - path.startAt) / path.duration;
  progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
  if (path.progress !== progress) {
   path.progress = progress;
   path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
   this.renderPath(i);
  }
 }
};
/**
 * Method forcing the browser to re-render a path element
 * from it's index in the map. Depending on the `forceRender`
 * value.
 * The trick is to replace the path element by it's clone.
 * This practice is not recommended because it's asking more
 * ressources, too much DOM manupulation..
 * but it's the only way to let the magic happen on IE.
 * By default, this fallback is only applied on IE.
 *
 * @param {Number} index Path index
 */
Vivus.prototype.renderPath = function (index) {
 if (this.forceRender && this.map && this.map[index]) {
  var pathObj = this.map[index],
    newPath = pathObj.el.cloneNode(true);
  pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
  pathObj.el = newPath;
 }
};
/**
 * When the SVG object is loaded and ready,
 * this method will continue the initialisation.
 *
 * This this mainly due to the case of passing an
 * object tag in the constructor. It will wait
 * the end of the loading to initialise.
 *
 */
Vivus.prototype.init = function () {
 // Set object variables
 this.frameLength = 0;
 this.currentFrame = 0;
 this.map = [];
 // Start
 new Pathformer(this.el);
 this.mapping();
 this.starter();
 if (this.onReady) {
  this.onReady(this);
 }
};
/**
 * Trigger to start of the animation.
 * Depending on the `start` value, a different script
 * will be applied.
 *
 * If the `start` value is not valid, an error will be thrown.
 * Even if technically, this is impossible.
 *
 */
Vivus.prototype.starter = function () {
 switch (this.start) {
 case 'manual':
  return;
 case 'autostart':
  this.play();
  break;
 case 'inViewport':
  var self = this,
  listener = function () {
   if (self.isInViewport(self.parentEl, 1)) {
    self.play();
    window.removeEventListener('scroll', listener);
   }
  };
  window.addEventListener('scroll', listener);
  listener();
  break;
 }
};
/**
 * Controls
 **************************************
 */
/**
 * Get the current status of the animation between
 * three different states: 'start', 'progress', 'end'.
 * @return {string} Instance status
 */
Vivus.prototype.getStatus = function () {
 return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
};
/**
 * Reset the instance to the initial state : undraw
 * Be careful, it just reset the animation, if you're
 * playing the animation, this won't stop it. But just
 * make it start from start.
 *
 */
Vivus.prototype.reset = function () {
 return this.setFrameProgress(0);
};
/**
 * Set the instance to the final state : drawn
 * Be careful, it just set the animation, if you're
 * playing the animation on rewind, this won't stop it.
 * But just make it start from the end.
 *
 */
Vivus.prototype.finish = function () {
 return this.setFrameProgress(1);
};
/**
 * Set the level of progress of the drawing.
 *
 * @param {number} progress Level of progress to set
 */
Vivus.prototype.setFrameProgress = function (progress) {
 progress = Math.min(1, Math.max(0, progress));
 this.currentFrame = Math.round(this.frameLength * progress);
 this.trace();
 return this;
};
/**
 * Play the animation at the desired speed.
 * Speed must be a valid number (no zero).
 * By default, the speed value is 1.
 * But a negative value is accepted to go forward.
 *
 * And works with float too.
 * But don't forget we are in JavaScript, se be nice
 * with him and give him a 1/2^x value.
 *
 * @param {number} speed Animation speed [optional]
 */
Vivus.prototype.play = function (speed, callback) {
 this.instanceCallback = null;
 if (speed && typeof speed === 'function') {
  this.instanceCallback = speed; // first parameter is actually the callback function
  speed = null;
 }
 else if (speed && typeof speed !== 'number') {
  throw new Error('Vivus [play]: invalid speed');
 }
 // if the first parameter wasn't the callback, check if the seconds was
 if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
  this.instanceCallback = callback;
 }
 this.speed = speed || 1;
 if (!this.handle) {
  this.drawer();
 }
 return this;
};
/**
 * Stop the current animation, if on progress.
 * Should not trigger any error.
 *
 */
Vivus.prototype.stop = function () {
 if (this.handle) {
  cancelAnimFrame(this.handle);
  this.handle = null;
 }
 return this;
};
/**
 * Destroy the instance.
 * Remove all bad styling attributes on all
 * path tags
 *
 */
Vivus.prototype.destroy = function () {
 this.stop();
 var i, path;
 for (i = 0; i < this.map.length; i++) {
  path = this.map[i];
  path.el.style.strokeDashoffset = null;
  path.el.style.strokeDasharray = null;
  this.renderPath(i);
 }
};
/**
 * Utils methods
 * include methods from Codrops
 **************************************
 */
/**
 * Method to best guess if a path should added into
 * the animation or not.
 *
 * 1. Use the `data-vivus-ignore` attribute if set
 * 2. Check if the instance must ignore invisible paths
 * 3. Check if the path is visible
 *
 * For now the visibility checking is unstable.
 * It will be used for a beta phase.
 *
 * Other improvments are planned. Like detecting
 * is the path got a stroke or a valid opacity.
 */
Vivus.prototype.isInvisible = function (el) {
 var rect,
  ignoreAttr = el.getAttribute('data-ignore');
 if (ignoreAttr !== null) {
  return ignoreAttr !== 'false';
 }
 if (this.ignoreInvisible) {
  rect = el.getBoundingClientRect();
  return !rect.width && !rect.height;
 }
 else {
  return false;
 }
};
/**
 * Parse attributes of a DOM element to
 * get an object of {attributeName => attributeValue}
 *
 * @param {object} element DOM element to parse
 * @return {object}     Object of attributes
 */
Vivus.prototype.parseAttr = function (element) {
 var attr, output = {};
 if (element && element.attributes) {
  for (var i = 0; i < element.attributes.length; i++) {
   attr = element.attributes[i];
   output[attr.name] = attr.value;
  }
 }
 return output;
};
/**
 * Reply if an element is in the page viewport
 *
 * @param {object} el Element to observe
 * @param {number} h Percentage of height
 * @return {boolean}
 */
Vivus.prototype.isInViewport = function (el, h) {
 var scrolled  = this.scrollY(),
  viewed    = scrolled + this.getViewportH(),
  elBCR    = el.getBoundingClientRect(),
  elHeight   = elBCR.height,
  elTop    = scrolled + elBCR.top,
  elBottom   = elTop + elHeight;
 // if 0, the element is considered in the viewport as soon as it enters.
 // if 1, the element is considered in the viewport only when it's fully inside
 // value in percentage (1 >= h >= 0)
 h = h || 0;
 return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
};
/**
 * Alias for document element
 *
 * @type {DOMelement}
 */
Vivus.prototype.docElem = window.document.documentElement;
/**
 * Get the viewport height in pixels
 *
 * @return {integer} Viewport height
 */
Vivus.prototype.getViewportH = function () {
 var client = this.docElem.clientHeight,
  inner = window.innerHeight;
 if (client < inner) {
  return inner;
 }
 else {
  return client;
 }
};
/**
 * Get the page Y offset
 *
 * @return {integer} Page Y offset
 */
Vivus.prototype.scrollY = function () {
 return window.pageYOffset || this.docElem.scrollTop;
};
/**
 * Alias for `requestAnimationFrame` or
 * `setTimeout` function for deprecated browsers.
 *
 */
requestAnimFrame = (function () {
 return (
  window.requestAnimationFrame    ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame  ||
  window.oRequestAnimationFrame   ||
  window.msRequestAnimationFrame   ||
  function(/* function */ callback){
   return window.setTimeout(callback, 1000 / 60);
  }
 );
})();
/**
 * Alias for `cancelAnimationFrame` or
 * `cancelTimeout` function for deprecated browsers.
 *
 */
cancelAnimFrame = (function () {
 return (
  window.cancelAnimationFrame    ||
  window.webkitCancelAnimationFrame ||
  window.mozCancelAnimationFrame  ||
  window.oCancelAnimationFrame   ||
  window.msCancelAnimationFrame   ||
  function(id){
   return window.clearTimeout(id);
  }
 );
})();
/**
 * Parse string to integer.
 * If the number is not positive or null
 * the method will return the default value
 * or 0 if undefined
 *
 * @param {string} value String to parse
 * @param {*} defaultValue Value to return if the result parsed is invalid
 * @return {number}
 *
 */
parsePositiveInt = function (value, defaultValue) {
 var output = parseInt(value, 10);
 return (output >= 0) ? output : defaultValue;
};
 if (typeof define === 'function' && define.amd) {
  // AMD. Register as an anonymous module.
  define([], function() {
   return Vivus;
  });
 } else if (typeof exports === 'object') {
  // Node. Does not work with strict CommonJS, but
  // only CommonJS-like environments that support module.exports,
  // like Node.
  module.exports = Vivus;
 } else {
  // Browser globals
  window.Vivus = Vivus;
 }
}(window, document)); 

总结

以上所述是小编给大家介绍的SVG动画vivus.js库使用小结(实例代码),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • SVG描边动画

    效果如下: 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>nubia</title> <style> .nubia_logo{ position: absolute; opacity: 0; animation:fadeIn 2s ease-in forwards; -webki

  • 推荐10 款 SVG 动画的 JavaScript 库

    SVG 通常可以用作跨分辨率视频.这意味着在一块高分屏幕上不会降低图片的锐度.此外,你甚至可以让SVG动起来,通过使用一些javascript类库.下面,我们分享一些javascript类库,这些类库会帮助我们将SVG动画提高一个等级. Vivus Vivus 是一个能动画js类库,它能够给SVG图像显示出被画出来的过程.Vivus是没有其他类库依赖的(比如jQuery).你仅仅需要在页面中加入这个.js文件,然后传入需要被用来动画的SVG部分就行.同时通过指定一些配置,它能够在页面加载后直接显

  • svg动画之动态描边效果

    1.首先先做一个简单的线一点一点画出来的效果,主要使用svg中的"strokeDasharray"."strokeDashoffset"属性,通过css3中的transtion改变strokeDashoffset来实现动画. 注:path中的数据通过在ai中划线后存储为svg格式就可以拿到: 效果图: 代码如下: <svg class="move_line1" xmlns="http://www.w3.org/2000/svg&q

  • 基于jquery和svg实现超炫酷的动画特效

    今天给大家分享一款基于jquery和svg超炫的网页动画.这款动画效果非常炫.下面还有重播.慢速.和反向动画按钮.效果非常漂亮.一起看下效果图: 实现的代码. html代码: 复制代码 代码如下: <div id="intro">         <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"          

  • SVG动画vivus.js库使用小结(实例代码)

    SVG动画vivus.js库使用整理,具体实例代码如下所示: 使用方法如图: HTML例子代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta

  • JS动画实现回调地狱promise的实例代码详解

    1. js实现动画 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>animate</title> <style> .ball { width: 40px; height: 40px; margin-bottom: 5px; border-radius: 20px; } .ball1 { ba

  • 动态加载js、css的实例代码

    一.原生js: /** * 加载js和css文件 * @param jsonData.path 前缀路径 * @param jsonData.url 需要加载的js路径或css路径 * @param jsonData.type 需要加载的类型 js或css */ function loadWriteFiles(jsonData) { jsonData.path = jsonData.path != undefined ? jsonData.path : ""; if(jsonData.

  • Bootstrap jquery.twbsPagination.js动态页码分页实例代码

    Bootstrap风格的分页控件自适应的: 参考网址:分页参考文档 1.风格样式: 2.首先引入js文件jQuery.twbsPagination.js <span style="font-size:14px;"><script type="text/javascript" src="plugins/page/jquery.twbsPagination.js"></script></span> 3.

  • 使用cropper.js裁剪头像的实例代码

    最近项目需要头像裁剪的功能,在网上找了一下,发现了github上的cropper项目还不错,借鉴了一下..用起来挺简单的,下面是我做的一个小例子: 开始先放个成品图: 下面给出前后端的代码 前端页面是一个单独的jsp页面,用来做弹出层来裁剪图片比较好. 关于jsp页面引用的两个关于cropper的 文件,我就不提供了.大家需要的可以去官方的github上去下载. 地址:https://github.com/fengyuanchen/cropper <%@ page language="ja

  • 简单封装js的dom查询实例代码

    最近一直在啃犀牛书,有感,于是写了个简单的js的dom查询 $ = function (val) { switch(val.charAt(0)) { case '#' : return document.getElementById(val.substring(1)); break; case '.' : val = val.replace('.',''); if(document.getElementsByClassName) return document.getElementsByClas

  • react.js 翻页插件实例代码

    废话不多说了,下面给大家分享react.js翻页插件的代码,具体代码如下所示: var Page = React.createClass({ render:function() { //中间代码更新 var totalRows = this.props.totalRows; var listRows = this.props.listRows; var nowPage = this.props.nowPage>0?this.props.nowPage:1; var firstRow = this

  • JDK 7 新特性小结实例代码解析

    1.switch支持String做参数 /*** * switch支持字符串做参数 jdk7 * @author huangjiawei */ public class SwitchTest { public static void switchTest(String arg) { switch (arg) { case "Lisa": System.err.println("我是Lisa!"); break; case "Mike": Syst

  • 原生js实现each方法实例代码详解

    jquery里面有个each方法,将循环操作简化.便捷. 随后es出了个forEach方法,两个虽然用法相近,但是不能处理对象类型.且无法通过return true达到continue效果. 此外还有个every方法,该方法虽然可以实现continue效果,但是在处理类数组与对象类型时,完全无用. 在不使用 jquery 的 each 方法时,该如何处理:或者说用原生如何来实现? 前些前写了个类库: jTool , 其中就实现了该方法. 简单实现: // 通过字面量方式实现的函数each var

随机推荐