如何使用SMIL / CSS按顺序在饼图/甜甜圈图中设置多个SVG路径的动画

时间:2019-02-12 07:16:56

标签: javascript css animation svg smil

我有一个svg组,其中包含一系列代表饼图不同区域的路径,这些路径由一个圆形标记转换,并且该图显示为一个甜甜圈图。

<svg width="71" height="70" xmlns="http://www.w3.org/2000/svg">
    <g class="graph-arc" transform="translate(1,1)">
        <path stroke="#3f88c5" fill="#3f88c5" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(225, 34.5, 34.5)"></path>
        <path stroke="#3f88c5" fill="#3f88c5" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(238.5, 34.5, 34.5)"></path>
        <path stroke="#3A8DC3" fill="#3A8DC3" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(252, 34.5, 34.5)"></path>
        <path stroke="#3593BF" fill="#3593BF" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(265.5, 34.5, 34.5)"></path>
        <path stroke="#3398BE" fill="#3398BE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(279, 34.5, 34.5)"></path>
        <path stroke="#3398BE" fill="#3398BE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(292.5, 34.5, 34.5)"></path>
        <path stroke="#359DBB" fill="#359DBB" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(306, 34.5, 34.5)"></path>
        <path stroke="#36A3B9" fill="#36A3B9" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(319.5, 34.5, 34.5)"></path>
        <path stroke="#36A3B9" fill="#36A3B9" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(333, 34.5, 34.5)"></path>
        <path stroke="#38A8B6" fill="#38A8B6" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(346.5, 34.5, 34.5)"></path>
        <path stroke="#39ADB4" fill="#39ADB4" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(360, 34.5, 34.5)"></path>
        <path stroke="#39ADB4" fill="#39ADB4" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(373.5, 34.5, 34.5)"></path>
        <path stroke="#3BB3B2" fill="#3BB3B2" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(387, 34.5, 34.5)"></path>
        <path stroke="#3DB8AE" fill="#3DB8AE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(400.5, 34.5, 34.5)"></path>
        <path stroke="#3DB8AE" fill="#3DB8AE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(414, 34.5, 34.5)"></path>
        <path stroke="#3EBDAD" fill="#3EBDAD" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(427.5, 34.5, 34.5)"></path>
        <path stroke="#40C3AA" fill="#40C3AA" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(441, 34.5, 34.5)"></path>
        <path stroke="#40C3AA" fill="#40C3AA" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(454.5, 34.5, 34.5)"></path>
        <path stroke="#00c8a8" fill="#00c8a8" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(468, 34.5, 34.5)"></path>
        <path stroke="#00c8a8" fill="#00c8a8" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55386505302874, 0.9532377462801749 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(481.5, 34.5, 34.5)"></path>
        <path stroke="#e5e5e5" fill="#e5e5e5" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 34.5, 0 z" xmlns="http://www.w3.org/2000/svg" transform="rotate(495, 34.5, 34.5)"></path>
    </g>
    <circle r="25.875" cx="35.5" cy="35.5" fill="#fff"></circle> . 
</svg>

我希望整体效果是这样的:https://codepen.io/seanstopnik/pen/GqHng

有很多使用笔触-dasharray进行线条显示的示例,但是我还没有找到任何可以动画显示多条路径的东西!最好的方法是什么?

2 个答案:

答案 0 :(得分:3)

按照常规方法,您没有要进行动画处理的笔触。因此,您可以将动画的描边线变成遮罩。然后将该蒙版应用于您更复杂的形状。

#progress circle {
  animation: do-progress 4s infinite;
}

@keyframes do-progress {
    0% { stroke-dashoffset: 0px; }
   50% { stroke-dashoffset: -146px; }
  100% { stroke-dashoffset: 0px; }
}
<svg width="71" height="70" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <mask id="progress" maskUnits="userSpaceOnUse">
            <rect x="-1" y="-1" width="100%" height="100%" fill="#fff"/>
            <circle r="30.5" cx="34.5" cy="34.5" fill="none" stroke="#000" stroke-width="10" stroke-dasharray="146 192" transform="rotate(-227, 34.5, 34.5)"/>
        </mask>
    </defs>
    <g class="graph-arc" transform="translate(1,1)" mask="url(#progress)">
        <path stroke="#3f88c5" fill="#3f88c5" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(225, 34.5, 34.5)"/>
        <path stroke="#3f88c5" fill="#3f88c5" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(238.5, 34.5, 34.5)"/>
        <path stroke="#3A8DC3" fill="#3A8DC3" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(252, 34.5, 34.5)"/>
        <path stroke="#3593BF" fill="#3593BF" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55 0.95 z" transform="rotate(265.5, 34.5, 34.5)"/>
        <path stroke="#3398BE" fill="#3398BE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(279, 34.5, 34.5)"/>
        <path stroke="#3398BE" fill="#3398BE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(292.5, 34.5, 34.5)"/>
        <path stroke="#359DBB" fill="#359DBB" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(306, 34.5, 34.5)"/>
        <path stroke="#36A3B9" fill="#36A3B9" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(319.5, 34.5, 34.5)"/>
        <path stroke="#36A3B9" fill="#36A3B9" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(333, 34.5, 34.5)"/>
        <path stroke="#38A8B6" fill="#38A8B6" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(346.5, 34.5, 34.5)"/>
        <path stroke="#39ADB4" fill="#39ADB4" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(360, 34.5, 34.5)"/>
        <path stroke="#39ADB4" fill="#39ADB4" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(373.5, 34.5, 34.5)"/>
        <path stroke="#3BB3B2" fill="#3BB3B2" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(387, 34.5, 34.5)"/>
        <path stroke="#3DB8AE" fill="#3DB8AE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(400.5, 34.5, 34.5)"/>
        <path stroke="#3DB8AE" fill="#3DB8AE" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(414, 34.5, 34.5)"/>
        <path stroke="#3EBDAD" fill="#3EBDAD" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(427.5, 34.5, 34.5)"/>
        <path stroke="#40C3AA" fill="#40C3AA" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(441, 34.5, 34.5)"/>
        <path stroke="#40C3AA" fill="#40C3AA" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(454.5, 34.5, 34.5)"/>
        <path stroke="#00c8a8" fill="#00c8a8" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(468, 34.5, 34.5)"/>
        <path stroke="#00c8a8" fill="#00c8a8" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 42.55, 0.95 z" transform="rotate(481.5, 34.5, 34.5)"/>
        <path stroke="#e5e5e5" fill="#e5e5e5" d="M 34.5,34.5 L34.5,0 A34.5,34.5 0 0,1 34.5, 0 z" transform="rotate(495, 34.5, 34.5)"/>
    </g>
    <circle r="25.875" cx="35.5" cy="35.5" fill="#fff"/>
</svg>

答案 1 :(得分:2)

正如Temani Afif所说,使用多路径并不是一种好方法。这就是我的方法:

要计算路径长度(155.53),我使用了JS和方法getTotalLength。我已将路径计算为半径为33的圆弧,从3*Math.PI/4Math.PI/4结束。

动画发生在鼠标悬停上。

svg{border:1px solid;width:90vh}

#thePath{
  stroke-dasharray : 155.53px;
  stroke-dashoffset : 155.53px;
  transition: stroke-dashoffset .5s;
}

svg:hover #thePath{
  stroke-dashoffset : 0px;
}
<svg viewBox ="0 0 71 70" id="svg">
<defs>
  <linearGradient id="lg">
   <stop offset="0%" stop-color="#3f88c5"></stop>
   <stop offset="100%" stop-color="#00c8a8"></stop>
  </linearGradient>
 </defs>
  
  <path id="thePath" d="M12.165476220843935,58.33452377915607A33,33,0 1 1 58.834523779156065,58.334523779156065" fill="none" stroke="url(#lg)" stroke-width="4" />
</svg>

这是我使用JS计算所有代码的代码:

let R = 33;// the radius of the arc for the path
// the starting point of the path
let x = 35.5 + R * Math.cos(3 * Math.PI / 4);
let y = 35 + R * Math.sin(3 * Math.PI / 4);
// the end point of the path
let _x = 35.5 + R * Math.sin(Math.PI / 4);
let _y = 35 + R * Math.sin(Math.PI / 4);
// the value of the d attribute of the path
let d = `M${x},${y}A${R},${R},0 1 1 ${_x},${_y}`;
thePath.setAttributeNS(null, "d", d);

let pathLength = thePath.getTotalLength();

thePath.setAttribute(
  "style",
  `stroke-dasharray : ${pathLength}px; stroke-dashoffset : ${pathLength}px;`
);
svg{border:1px solid;width:90vh;}

#thePath{ 
  transition: stroke-dashoffset .5s;
}

svg:hover #thePath{
  stroke-dashoffset : 0px!important;
}
<svg viewBox ="0 0 71 70" id="svg">
<defs>
  <linearGradient id="lg">
   <stop offset="0%" stop-color="#3f88c5"></stop>
   <stop offset="100%" stop-color="#00c8a8"></stop>
  </linearGradient>
 </defs>
  
  <path id="thePath" fill="none" stroke="url(#lg)" stroke-width="4" />
</svg>