【问题标题】:Animating SVG pie chart from 0% to 100% in pure SMIL在纯 SMIL 中动画 SVG 饼图从 0% 到 100%
【发布时间】:2019-02-09 23:14:15
【问题描述】:

如何在纯 SMIL 中重新创建这个 SVG 饼图动画?我希望放弃复杂的 JS,并且还能够控制动画的总持续时间:

http://jsfiddle.net/frank_o/gFnw9/19/

到目前为止,这就是我得到的全部:

http://jsfiddle.net/frank_o/46mH2/(感谢Ian

但不幸的是:

  • 它的位置远离画布(或者一开始不是一个完整的圆圈)
  • 从 9 点开始,而不是 12 点开始
  • 使用 Snap.svg(宁愿不依赖任何外部库,但如果必须的话)

HTML:

<svg width="600" height="425">
    <path d="M 100, 100 m -75, 0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0" fill="none" stroke="black" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000">
        <animate attributeType="XML" attributeName="stroke-dashoffset" from="0" to="600" dur="1s" repeatCount="1" fill="freeze"/> 
    </path>
</svg>

JS:

var s = Snap(600,600);

var c = s.circle(150, 150, 80).attr({
    fill: "none",
    stroke: 'red',
    strokeWidth: 161,
    strokeDasharray: "0 600 600 0",
    strokeDashoffset: 1000
});

Snap.animate(0,600, function( value ){ 
       c.attr({ 'strokeDashoffset': value })

},5000 );

更新:

问题:

应该是:

【问题讨论】:

    标签: javascript svg smil


    【解决方案1】:

    您可以像这样在路径上应用转换:

    <svg width="600" height="425">
        <path d="M 100, 100 m -75, 0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0" fill="none" stroke="black" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000" transform="translate(75,75) rotate(90,100,100) ">
            <animate attributeType="XML" attributeName="stroke-dashoffset" from="0" to="600" dur="2s" repeatCount="1" fill="freeze"/> 
        </path>
    </svg>
    

    http://jsfiddle.net/46mH2/1/

    旋转变换将使它从 12 点开始,平移会将其偏移一半笔划宽度,因此它位于视图框内。
    确保以正确的顺序应用转换,否则将不会得到相同的结果。

    更新
    是的,您可以避免这两种转换:

    <svg width="600" height="425">
        <path d="M 175, 175 m 0, -75 a 75,75 0 1,0 0,150 a 75,75 0 1,0 0,-150" fill="none" stroke="black" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000">
            <animate attributeType="XML" attributeName="stroke-dashoffset" from="0" to="600" dur="2s" repeatCount="1" fill="freeze"/> 
        </path>
    </svg>
    

    http://jsfiddle.net/46mH2/3/

    在您的 svg 上设置一个 viewBox,以便您可以缩放元素并仍然使整个图像可见:

    <svg width="600" height="425" viewBox="0 0 600 425">
        <path d="M 100, 100 m -75, 0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0" fill="none" stroke="black" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000" transform="translate(75,75) rotate(90,100,100) ">
            <animate attributeType="XML" attributeName="stroke-dashoffset" from="0" to="600" dur="2s" repeatCount="1" fill="freeze"/> 
        </path>
    </svg>
    

    如果您没有按比例缩放它,请检查使用 preserveAspectRatio 看看哪个适合您

    【讨论】:

    • 这太棒了,谢谢!有没有办法让它直接从 12 点开始,而不必旋转它?
    • 在我们完成之前:1)如何在动画完成后删除它?,2)如何通过 CSS 控制其大小? svg { width: N; height: N; } 只是切断它。
    • 还有一点——attributeType="XML" 真的需要吗?
    • 我已经编辑了你最后一个问题的答案。我认为在这种情况下不需要 attributeType,因为 xml 和 css 不共享该属性名称。
    • 准确!如此美丽的小提琴,尤其是与我发布的小提琴相比。非常感谢!
    【解决方案2】:

    为了解决您在更新标签中发布的问题,请查看我对 2 个解决方案的比较: 为了在解决方案一中执行动画,旋转了 2 个半圆。在第二个解决方案中,stroke-dashoffset 是动画的。 这两种解决方案都不是纯 SMIL,而是我更喜欢的纯 Web Animations API。 在 web-animations.min.js polyfill 的帮助下,此代码甚至可以在 IE 11 中运行。

    <html>
    <head>
      <meta charset="utf-8">
      <title>SVG mit CSS animieren</title>
      <script src="web-animations.min.js"></script>
    </head>
    <body>
    <h1>SVG mit CSS animieren</h1>
    
    <main>
    <h2>Kreis in SVG - mit CSS animiert</h2>
    <svg width="400px" height="400px" viewBox="-1 -1 2 2" style="margin-left:20px; margin-top:10px; background: lightgray; border-radius: 50%">
      <path id="slice1"      fill="#c32e04"   stroke="none" d="M0,1 a1,1 0 0,1 0,-2 z" />
      <path id="slice2"      fill="#c32e04"   stroke="none" d="M0,1 a1,1 0 0,1 0,-2 z" />
      <path id="slice_cover" fill="lightgray" stroke="none" d="M0,1 a1,1 0 0,1 0,-2 z" />
      <script>
         const duration=5000;
         var anim11, anim12;
         var slice1=document.getElementById("slice1");
         var slice2=document.getElementById("slice2");
         function slice2_ontop() { slice2.parentNode.appendChild(slice2); }
         anim11=slice1.animate([
           {transform: 'rotate(0deg)'},
           {transform: 'rotate(180deg)'}
         ], { duration: duration/2, iterations: 1, fill: "forwards"});
         anim11.onfinish=slice2_ontop;
         anim12=slice2.animate([
           {transform: 'rotate(0deg)'},
           {transform: 'rotate(360deg)'}
         ], { duration: duration, iterations: 1, fill: "forwards"});
      </script>
    </svg> 
    <svg width="400px" height="400px" viewBox="-1 -1 2 2" style="margin-left:20px; background: lightgray; border-radius: 50%; transform: rotate(-90deg)">
      <circle id="circle" cx="0" cy="0" r="0.5" fill="none" stroke="#c32e04" stroke-width="1px" style="stroke-dasharray: 3.1416 3.1416; stroke-dashoffset: 3.1416"/>
      <script>
         var anim2;
         anim2=document.getElementById("circle").animate([
           {strokeDashoffset: '3.1416px'},
           {strokeDashoffset: '0px'}
         ], { duration: duration, iterations: 1, fill: 'forwards'});
      </script>
    </svg> 
    
    </main>
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 2014-02-24
      • 1970-01-01
      • 2015-01-14
      • 1970-01-01
      • 2015-04-02
      • 1970-01-01
      • 2017-07-01
      • 1970-01-01
      • 2016-09-18
      相关资源
      最近更新 更多