Define a circle / arc animation in SVG
Asked Answered
H

7

11

Does anyone know how to define an animated arc / circle in SVG, such that the arc starts at 0 degrees and ends at 360 degrees?

Horning answered 15/7, 2010 at 15:11 Comment(1)
I want to animate the sweep angle, but in SVG an arc is defined using the start and end points.Horning
F
9

you can paint it "by hand" using path's lineto and calculate the position of the arc:

<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/

Florie answered 16/7, 2010 at 7:23 Comment(3)
Thanks räph. I'm still new to SVG and haven't used the <script> element before. I'm not sure if it will work in the concrete problem that i have. But as your snippet answers my question perfectly I mark it as being correct.Horning
Are you programming for the web? The script example works in firefox, safari, chrome and opera! As alternative you could also use SMIL - but that doesn't work in all browsersSmallsword
I wrote another answer to explain my architecture in detail - please see below, and thanks again for the help.Horning
G
9

One way is to use a circle, and animate the stroke-dashoffset (you need 'stroke-dasharray' too). An example of such an animation (not with a circle, but the same principle applies) can be seen here.

The other option is to use a path animation, and arc path segments, for animating/morphing between paths see this example.

Godevil answered 16/7, 2010 at 6:55 Comment(1)
thanks erik - the link to the carto.net/papers/svg/samples site showed me some interesting ideas and techniques for svg animation.Horning
F
9

you can paint it "by hand" using path's lineto and calculate the position of the arc:

<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/

Florie answered 16/7, 2010 at 7:23 Comment(3)
Thanks räph. I'm still new to SVG and haven't used the <script> element before. I'm not sure if it will work in the concrete problem that i have. But as your snippet answers my question perfectly I mark it as being correct.Horning
Are you programming for the web? The script example works in firefox, safari, chrome and opera! As alternative you could also use SMIL - but that doesn't work in all browsersSmallsword
I wrote another answer to explain my architecture in detail - please see below, and thanks again for the help.Horning
W
7

You can also draw the SVG by hand using a circle and the following technique:

  1. Give the circle a stroke.
  2. Make the stroke dashed with a dash length equal to the circle's circumference.
  3. Offset the stroke by a length equal to the circle's circumference.
  4. Animate the 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

source: https://css-tricks.com/svg-line-animation-works/

Wolcott answered 5/1, 2017 at 15:5 Comment(0)
M
3

Or perhaps you could uncover a pre-drawn circle to give the required effect:

<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>
Moyers answered 8/9, 2013 at 18:44 Comment(1)
Uncovering the circle is a cool idea, and I like your example for the half circle case.Horning
E
2

I was also a bit disapointed to not be able to simply make an circle's arc with a percent, or an angle.

Nowadays, when I need an arc which is not part of a longer path, I use a circle and strokeDasharray trick to show just a part of this circle.

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>

You can see an improved version here which use Sass to make the calculations.

Entrepreneur answered 25/11, 2015 at 19:22 Comment(0)
D
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>
Decreasing answered 19/3, 2016 at 19:59 Comment(0)
H
-1

Thanks for the answers - here is a little more information regarding why I want to animate a circle in SVG:

We have a server-client application. I plan to generate SVG images to represent charts (pie charts / bar charts) on the server and send the SVG to the clients. We have Java and .NET clients. I will write client-side code to parse and render the SVG images received from the server. I plan to use only a subset of the SVG format - not more than what we need to represent our charts, but animation is a requirement.

Long-term it would be nice to have an ajax client - that will run on browsers without java or .NET runtime. That is why I have chosen the SVG format.

For a short term solution I now think I will add my own element to the SVG, defining an arc using start and sweep angles. Then I can easily define the animation I require by animating the sweep angle, and makes my implementation simple.

Long term - if we really get around to imlpementing an AJAX/HTML client - I will have to re-implement and stick to the SVG standard.

Horning answered 16/7, 2010 at 11:21 Comment(3)
Alright! I'm curious: Regarding your short-term solution, when you declare your own svg elements - how will your client render these? Do you parse your xml and paint them natively?Smallsword
Yes, I will parse the XML and paint the elements using native Graphics APIs (Graphics2D in java, GDI+ in .NET.)Horning
You probably should edit your question instead of answering it. By the way; you could use halfstroked circles to draw arc; The codepen in my answer show you an animation.Entrepreneur

© 2022 - 2024 — McMap. All rights reserved.