欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-09-08 12:03:09
svg动画vivus.js库使用整理,具体实例代码如下所示: 使用方法如图:...

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库使用小结(实例代码),希望对大家有所帮助