在SVG中定义圆形/弧形动画

11

有人知道如何在SVG中定义一个动画弧/圆,使得弧从0度开始,到360度结束吗?


我想要对扫描角度进行动画处理,但在SVG中,弧线是通过起始点和终止点来定义的。 - GarethOwen
7个回答

9

您可以使用路径的lineto手动绘制它,并计算弧的位置:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
   viewBox="0 0 1200 800"
   preserveAspectRatio="xMidYMid"
   style="width:100%; height:100%; position:absolute; top:0; left:0;"
   onload="drawCircle();"> 
  <script> 
    function drawCircle() {
        var i = 0;
        var circle = document.getElementById("arc");
        var angle = 0;
        var radius = 100;     
        window.timer = window.setInterval(
        function() {
            angle -=5;  
            angle %= 360;
            var radians= (angle/180) * Math.PI;
            var x = 200 + Math.cos(radians) * radius;
            var y = 200 + Math.sin(radians) * radius;
            var e = circle.getAttribute("d");
            if(i==0) {
                var d = e+ " M "+x + " " + y;
            }
            else {
                var d = e+ " L "+x + " " + y;
            }
            if (angle === -5 && i !== 0) {
                window.clearInterval(window.timer);
            }

            circle.setAttribute("d", d);
            i++;
        } 
      ,10)
    }
    </script> 

    <path d="M200,200 " id="arc" fill="none" stroke="blue" stroke-width="2" />
</svg>

http://jsfiddle.net/k99jy/138/


谢谢 räph。 我对 SVG 还很陌生,之前也没有使用过 <script> 元素。我不确定它是否适用于我具体的问题。 但是,由于您的代码片段完美地回答了我的问题,我将其标记为正确答案。 - GarethOwen
你在为网络编程吗?这个脚本示例可以在Firefox、Safari、Chrome和Opera中运行!作为替代方案,你也可以使用SMIL,但并不适用于所有浏览器。 - räph
我写了另一个答案来详细说明我的架构 - 请见下文,并再次感谢您的帮助。 - GarethOwen

8

一种方法是使用圆形,并动画化 stroke-dashoffset(你也需要 'stroke-dasharray')。这样的动画示例(不是用圆形,但是相同的原理适用)可以在此处查看here

另一个选项是使用路径动画和arc path segments,要对路径进行动画化/变形,请参见此example


谢谢Erik - 链接到http://www.carto.net/papers/svg/samples网站给我展示了一些有趣的SVG动画的想法和技巧。 - GarethOwen

7

您也可以使用circle和以下技术手工绘制SVG:

  1. circle添加一个stroke
  2. 使stroke成为虚线,虚线长度等于圆的周长。
  3. stroke偏移一个与圆周长相等的长度。
  4. 对stroke进行动画处理。

HTML:

<svg width="200" height="200">
  <circle class="path" cx="100" cy="100" r="96" stroke="blue" stroke-width="4" fill="none" />
</svg>

CSS:

circle {
  stroke-dasharray: /* circumference */;
  stroke-dashoffset: /* circumference */;
  animation: dash 5s linear forwards;
}

@keyframes dash {
  to {
    stroke-dashoffset: /* length at which to stop the animation */;
  }
}

点击这里进入jsfiddle网站。

原文来源:https://css-tricks.com/svg-line-animation-works/


3

或者你可以揭示一个预先绘制的圆形来产生所需的效果:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" width="400" height="400">
  <rect x="0" y="0" width="1000" height="1000"/>
  <circle cx="500" cy="500" r="500" fill="red"/>
  <rect x="0" y="500" width="1000" height="500"/>
  <rect x="0" y=  "0" width="1000" height="500">
    <animateTransform attributeName="transform" type="rotate" begin="0s" dur="5s" fill="freeze" from="0,500,500" to="180,500,500"/>
  </rect>
</svg>

揭示圆形是一个很酷的想法,我喜欢你对半圆情况的例子。 - GarethOwen

2

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
</head>
<body>
    
</body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
   viewBox="0 0 1200 800"
   preserveAspectRatio="xMidYMid"
   style="width:100%; height:100%; position:absolute; top:0; left:0;"
   onload="drawCircle();"> 
  <script> 
    function drawCircle() {
        // center point
        var cX = 300,
            cY = 300;
            radius = 300,

            p1 = {x: cX+radius, y: cY},
            p2 = {x: cX-radius, y: cY},

            circle = document.getElementById("arc"),
            angle = 0;

        window.timer = window.setInterval(
            function() {
            angle -= 5;  
            angle %= 360;
            var radians= (angle/180) * Math.PI;
            var x = cX + Math.cos(radians) * radius;
            var y = cY + Math.sin(radians) * radius;

            if (Math.abs(angle) < 180 && angle != 0)
                d= 'M ' + p1.x + ',' + p1.y + ' A' + radius+ ',' + radius+ (Math.abs(angle)==180?' 0 1 0 ':' 0 0 0 ')+x+' '+y;
            else
                d= 'M ' + p1.x + ',' + p1.y + ' A' + radius+ ',' + radius+ ' 0 1 0 '+p2.x+' '+p2.y +
            ' M ' + p2.x + ',' + p2.y + ' A' + radius+ ',' + radius+ (Math.abs(angle)==0?' 0 1 0 ':' 0 0 0 ')+x+' '+y;
            
            circle.setAttribute("d", d);

            if (Math.abs(angle) == 0)
                window.clearInterval(window.timer);
        } 
      ,10)
    }
    </script> 
    <path d="" id="arc" fill="none" stroke="blue" stroke-width="2" />
</svg>
</html>


2

我也有点失望,不能仅通过百分比或角度绘制圆弧。

现在,当我需要一个不是长路径的圆弧时,我使用圆形和strokeDasharray技巧来显示这个圆的一部分。

svg {
  outline: solid;
  height: 100px;
  width: 100px;
}
.arc {
  fill: transparent;
  stroke-width: 5;
  stroke: red;
  stroke-dasharray: 94.24778 219.91149;
}
<svg viewport="0 0 100 100">
  <circle cx="50" cy="50" r="50" class="arc"></circle>
</svg>

您可以在这里看到一个改进版的链接,该链接使用Sass进行计算,以便提高效率。


-1

谢谢您的答案 - 这里有一些更多关于我为什么想要在SVG中制作动画圆的信息:

我们有一个服务器-客户端应用程序。 我计划在服务器上生成SVG图像以表示图表(饼图/柱状图),并将SVG发送到客户端。 我们有Java和.NET客户端。 我将编写客户端代码来解析和渲染从服务器接收的SVG图像。 我计划仅使用SVG格式的子集 - 不超过我们需要表示我们的图表,但动画是必需的。

从长远来看,拥有一个可以运行在没有Java或.NET运行时的浏览器上的ajax客户端将是不错的选择。这就是为什么我选择了SVG格式的原因。

对于短期解决方案,我现在认为我将添加自己的元素到SVG中,使用起始和扫描角度定义弧形。 然后,我可以通过动画扫描角度轻松定义所需的动画,并简化我的实现。

从长远来看 - 如果我们真正开始实施AJAX / HTML客户端 - 我将不得不重新实现并坚持SVG标准。


好的!我很好奇:关于您短期解决方案的问题,当您声明自己的SVG元素时,您的客户端会如何呈现它们?您会解析XML并在本地绘制它们吗? - räph
是的,我将解析 XML 并使用本地的图形 API(如 Java 中的 Graphics2D、.NET 中的 GDI+)来绘制元素。 - GarethOwen
1
你最好编辑你的问题而不是回答它。 顺便说一下,你可以使用半画圆来绘制弧形;我回答中的Codepen向你展示了一个动画。 - long-lazuli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接