How to convert animation in Canvas/JS to SVG?

Asked

Viewed 1,005 times

31

I’ve been using a javascript library to make icones/symbols of a weather app. I now wanted to do in SVG the symbol of the cloud (cloudy sky), and wonder what the best approach.

I made a svg with the cloud line, static (jsFiddle), and a basic rotation which is not the intended effect once the original cloud (in animation with canvas/js) has 5 arches that expand and contract as they rotate.

Possible approaches I thought:

  • make 5 circles, using "Dash" to have only bows, and then try to animate this value and make everything rotate around an axis
  • make 5 path, and then try to animate that value and make everything rotate around an axis

There will be a better way (and that works in modern browsers) to recreate the animation but with SVG?

The example of js, as in jsFiddle above:

var skycons = new Skycons({
    "color": "black"
});
var canvas = document.querySelectorAll('canvas');
[].forEach.call(canvas, function (el) {
    skycons.add(el, el.dataset.icon);
});

skycons.play();
<script src="https://rawgit.com/darkskyapp/skycons/master/skycons.js"></script>
<div class="fe_forecast">
    <div class="fe_currently">
        <canvas id="fe_current_icon" data-icon="cloudy" width="160" height="160" style="width:120px; height:120px"></canvas>
    </div>
</div>

  • @Felipe, thanks for the help to bring up the question! I can add that in the meantime I made an improvement that I left in a comment there in the library. It got better, but the doubt that generated the question still exists, namely: what is the correct way to do this in svg.

  • 1

    Yes the difficulty is in keeping the animations, I even coerced ways to keep picking pixel to pixel of the canvas in a continuous loop more even optimizing was nothing performatic.

  • About svg Transform and css utilities for svg, this would be an option?

  • 1

    @Felipeasunción if you agree leaves the reward open until the end of time for others to be able to contribute answers too.

  • 1

    Yes, the current answer although quite complete is not very objective, I found it very theoretical and I look for a more technical answer. I understand that we are focused on coding and creating svgs with the use of a program is basically beyond the scope of Javascript, I’m looking for an approach similar to this: http://willianjusten.com.br/manipulando-svg-com-js/ focused on creating and manipulating javascript

  • @Felipeasuncion What kind of animation do you want to do? What are the resources you need in animation?

  • The last time I played with canvas and svg, I ended up using a library called Fabric.js, it has animation support. Have you seen the examples?

  • 1

    I will be more specific, considering the use of javascript as the main tool, the library that Sergio used https://rawgit.com/darkskyapp/skycons/master/skycons.js has exact 10 models of Weather icons being made entirely in javascript, I seek an approach that allows me to do something similar. Sergio so is an experienced programmer just see the contributions he has made here in the community so I assume he even consulted the basics on SVG before asking here.

  • 1

    An appropriate approach would be to explain as follows: - How to create the shapes with the use of coding (how it works, how to make a curve and etc.) - How to manipulate the elements also with the use of javascript, How to modify the elements at runtime in the most performative way, to allow it to create a viable and coherent solution, because if it has to use a thousand external software to do what it has already found ready on canvas will certainly not be worth replacing.

  • Just look at the body of the question he already knows the introductory even reached a minimum solution

Show 5 more comments

3 answers

30

Update: Animation with Javascript

For a simpler approach, see Animation (below)

The animation of objects in a document SVG with Javascript can be made of various forms, such as:

  • changing the properties of GIFT (similar to Animation, down below)

  • modifying the vector transformations (e.g., through estates Transform or Matrix)

  • direct animation of internal properties (e.g., changing the vectors that form the path)

Access to object attributes can be done directly, however, to access SVG elements, one must use a namespace:

const svgNS = 'http://www.w3.org/2000/svg';

// Referência ao objeto SVG (sem o namespace)
svgRef = document.getElementById('svgImg01');

// Cria um caminho (usa namespace)
pathRef = document.createElementNS(svgNS, "path");

// Atributos são acessados sem o namespace
pathRef.setAttribute('id','cam');
pathRef.setAttribute('style', "fill:#000000");
pathRef.setAttribute('d', 'M0 0 Z');

// Adiciona o caminho criado ao documento SVG
svgRef.appendChild(pathRef);

Looping of the Animation

The simplest way to update objects during animation is to use the function setInterval or setTimeout.

The downside is that these functions do not have much accuracy (of time) to update the animation and may occur failures ("jumps") during execution.

An example of how to create the basic structure of the animation looping with setInterval:

var handleInterval = -1;

function renderizar()
{
    // Código da animação
}

// inicia o timer
function iniciaAnimacao()
{
    handleInterval = setInterval('renderizar();', 300);
}

// para o timer
function pausaAnimacao()
{
    clearInterval(handleInterval);
    handleInterval = -1;
}

Another way (with better accuracy and performance) to upgrade the animation is use an auxiliary looping and function requestAnimationFrame:

var handleFrame = -1;

// tempo que o último frame foi renderizado
var ultimoFrame = 0;

// tempo até a renderização do próximo frame
const numFrames = 30.0;

// Looping auxiliar
function loopingAnimacaoFrameComTempo(tempo)
{
    if ((tempo - ultimoFrame) > numFrames) {
        renderizar();
        ultimoFrame = tempo;
    };
    handleFrame = requestAnimationFrame(loopingAnimacaoFrameComTempo);
    return;
}

// inicia o looping
function iniciaAnimacao()
{
    ultimoFrame = performance.now() - numFrames + 1;
    handleFrame = requestAnimationFrame(loopingAnimacaoFrameComTempo);
}

// interrompe o looping
function pausaAnimacao()
{
    cancelAnimationFrame(handleFrame);
    hanldeFrame = -1;
}

As the function requestAnimationFrame awaits the next operation of repaint of device, it is possible to achieve higher speeds and at the same time maintain a "soft" update of frames.

The constant numFrames controls the speed of the animation. The lower the value, faster will be the animation.


Objects

In this example, the animation warps (randomly) the vectors of a polygon.

Create or change the properties of other objects (e.g., circles, rectangles), in addition to the path, follows the same logic and can be used for any type of animation (commercial graphics, banners, histograms, games, etc.).

Vectors are created by the function below and return in a string, which will be awarded to property d of the way created:

function cria_path_inicial(x, y, r, tess)
{
    var ponto_x = Math.cos(0.0)*r + x;
    var ponto_y = Math.sin(0.0)*r + y;
    var ret = 'M' + ponto_x + ' ' + ponto_y + ' ';

    for (var angulo=0.0; angulo<2.0*Math.PI; angulo+=tess) {
        ponto_x = Math.cos(angulo)*r + x;
        ponto_y = Math.sin(angulo)*r + y;
        ret += 'L' + ponto_x + ' ' + ponto_y + ' ';
    }
    return ret + 'Z';
}

and the function that deforms the polygon within a Cage:

// Pontos importantes nos comentários

function renderizar()
{
    var i = 0;
    var px = 0.0;
    var py = 0.0;

    // Obtém a lista de vetores do caminho
    var segmentos = pathRef.pathSegList;

    // Percorre a lista
    for (i=1; i<segmentos.numberOfItems; i++) {

        // Obtém uma referência ao vértice 'i' e as coordenadas do vértice
        var vertice = segmentos.getItem(i);
        px = vertice.x;
        py = vertice.y;

        dx = Math.random()*2;
        dy = Math.random()*2;
        if (Math.random() < 0.5) {
            px += (px+dx < 400) ? dx : -dx;
            py += (py+dy < 400) ? dy : -dy;
        } else {
            px -= (px-dx > 0) ? dx : -dx;
            py -= (py-dy > 0) ? dy : -dy;
        }

        // Atualiza os vértices
        vertice.x = px;
        vertice.y = py;
    }
    return;
}

The complexity in the implementation depends mainly on the objective of the animation, the algorithms that will be used, the number of objects, synchronization of movements, etc.

The SVG format pertains to the Javascript code statement within the document, therefore, there is also possibility to use this area to encode the animation.

The result below has been implemented with controls to start and pause the animation, reset the polygon and toggle the looping between setInterval and requestAnimationFrame:


Animação JS


Observing: The example in jsfiddle has been tested with browsers FireFox 43.0.4 64bit, Opera 31.0, Safari 9.0.3 and Internet Explorer 11, however, doesn’t work in the Google Chrome.


See running on jsfiddle



Animation

Animate the SVG object consists of changing its properties as a function of a time interval.

You can change these properties (without using Javascript), for example using:

Through CSS, you can create an animation by changing one or more properties in a time interval using, for example, commands:

  • @keyframes to define how and which properties will be changed.

  • animation to set, for example, the animation time or how many times it will be executed

When analyzing the image in the question link, the first strategy used to copy the animation, was to combine a scale operation with rotation, according to the code below:

#container {
  position: relative;
  float: left;
  width: 90mm;
  height: 90mm;
  left:20px;
  top:100px;
  background: rgb(240, 240, 255);
}

@keyframes animacao-escala-rotaciona {
  0%   { width:45mm; height: 45mm; top: 50%; left: 50%; }
  50%  { width:55mm; height: 55mm; top: 45%; left: 45%; }
  100% { width:45mm; height: 45mm; top: 50%; left: 50%; transform: rotate(360deg); }
}

#svg2 {
  position:absolute;
  top: 50%;
  left: 50%;
  width: 45mm;
  height: 45mm;
  margin: -23mm 0 0 -23mm;
  animation:
    animacao-escala-rotaciona 4s infinite running linear;
}

In charge keyframes, the steps (Steps) animation are defined in percentages of the total animation time.

Inside the code block after each percentage, are the properties that will be changed at each step.

In the object svg2, the attribute animation sets the animation time, the amount of repetitions (infinite) the status (stop or run) and the type of interpolation of time.


inserir a descrição da imagem aqui

See running on jsfiddle


Another possibility is to combine the two transformations directly in the attribute transform, with the code:

@keyframes animacao-escala {
  0%   { transform: scale(1.0) rotate(0deg); }
  50%  { transform: scale(1.8) rotate(180deg); }
  100% { transform: scale(1.0) rotate(360deg); }
}


See running on jsfiddle



Animation of Paths (paths)


For this type of animation, simply change the paths according to the animation time in the attribute d tag path.

The animation of the attribute d should be made with SMIL, because the CSS does not allow animation of this attribute.

In the code below, the attribute values (on the tag animate) stores the paths of each step of the animation, and the attribute d (on the tag path), the initial path:

<path
   d="m 288.8656,608.00072 a 44.166031 ...
   id="novanuvem2"
   >
   <animate
    id="path"
    xlink:href="#novanuvem2"
    attributeName="d"
    repeatCount="indefinite"
    values="
        m 288.8656,608.00072 a 44.166 ...
        m 325.36386,601.50838 a 42.18 ...
        m 352.99225,577.56713 a 42.18 ...
        m 365.39429,541.71227 a 42.18 ...
        m 358.90196,505.21401 a 44.16 ...
        m 334.96071,477.58562 a 44.16 ...
        m 299.10585,465.18357 a 44.16 ...
        m 262.60758,471.6759 a 42.188 ...
        m 234.97918,495.61715 a 42.18 ...
        m 222.57713,531.47202 a 42.18 ...
        m 229.06946,567.97029 a 44.16 ...
        m 253.01071,595.59869 a 44.16 ...
        m 288.8656,608.00072 a 44.166 ...
    dur="5s"/>
  </path>

An important point is that the attribute xlink:href="#novanuvem2" on the tag animate must correspond to the id tag path.


See running on jsfiddle



Completion

There are different and perhaps more efficient ways to implement this type of animation, but the goal of this answer is to offer a practical example of how to create animations with vector graphics.

When animating objects in SVG, either through tags CSS, SMIL or through Javascript, animation may display different behaviors or require specific syntax depending on the browser, so the tip is to consult and test the application in several browsers:

The advantage of SVG animation is that the image quality does not depend on the resolution of the device where it will be rendered (e.g., monitors, mobiles, etc.), because the image is formed by vectors and not bit map.



Below are other links that helped in the preparation of the answer:

Basic SVG path Tweening with SMIL

Keyframe Animation Syntax

How SVG Line Animation Works

A Guide to SVG Animations - SMIL

W3 - Animation

SVG Path Morphing

  • 4

    It would be interesting to have a reason -1 in this answer (if it is because of an error in the answer so it can be corrected and we all learn from it).

  • 4

    @Sergio unfortunately this kind of common sense is not part of our community. Gomiero, very nice your approach however I found that the mechanics that you used to describe the process was very tied to the use of graphical software and SVG allows the creation of composite shapes with handcode only, can describe a little about the process of Drawing?

  • @Felipeasuncion and Sergio: Thank you!! I did not put, because in the question, the animation is very simple. But I will update the answer as soon as I find something on the subject

  • @Sergio I believe it may be the Wikipedia phrase at the beginning of the answer. I really like animations, mainly 3D and the idea was to write the text using a humorous tone :)

  • 1

    I very much want to believe that whoever gave -1 really read and understood the whole answer. It costs nothing to clarify to the AR what it can improve on the question.

  • 2

    I think the -1 must have been for having created a very long response, having explained even the concepts of animation etc, which is absolutely unnecessary by the concept of the site... I think not only the -1, but the lack of +1’s tbm should be why... I would remove the chapter "Theory"

  • 1

    @Thanks a lot for the tip!! :-)

Show 2 more comments

5

Using only SVG maybe something like this is a good approach.

https://jsfiddle.net/wgzk3qze/

Of course, the animation that I did was not perfect, it was just to illustrate. I created 8 cases in animation but I think you can reduce the code to 4.

[PS] this already works in Chrome too: https://jsfiddle.net/khnsoynh/

<svg x="0px" y="0px" width="283.026px" height="214.477px" viewBox="0 0 283.026 214.477" enable-background="new 0 0 283.026 214.477">
  <path fill="#FFFFFF" stroke="#000000" stroke-width="10" stroke-miterlimit="10">

  <animate attributeName="d" dur="20000ms" repeatCount="indefinite"  values="M236.5,140.163
    c27.5,37.281-59.5,78.029-93.945,36.414C124.321,220.712,24.5,183.946,43,143.631c-44.5-0.433-18-105.773,38-85.832
    C59,4.045,221.593,3.622,203,55.197C262.5,35.257,286,135.394,236.5,140.163z;

    M205.254,179.176
    c-17,29.568-148.404,29.972-151.214-15.828C9.319,186.476,0,64.738,40.913,71.946c-18.9-41.207,93.852-61.207,107.1-38.207
    c36.752-38,159,20,98.851,67C297.423,120.643,238.23,204.821,205.254,179.176z;

    M90.72,175.919
    c-55.178,19.285-115.488-41.725-53.895-65.88c-65.323-12.787-10.907-82.788,48.762-69.814
    c0.641-31.206,156.551-12.623,127.037,26.648c79.56-15.428,80.186,98.593,3.851,85.554
    C245.988,194.152,97.778,210.631,90.72,175.919z;

    M47.013,165.738
    c-52.501-16.871-37.225-129,11-116c0-43.084,110-49.738,134-9c29.231-28.426,105.832,56.274,51,74c64.265,35.76-32.06,120.03-68,60
    C153.013,220.738,46.013,202.738,47.013,165.738z;

    M47.43,73.458
    c-27.5-37.281,59.5-78.029,93.945-36.414C159.609-7.091,259.43,29.675,240.93,69.99c44.5,0.433,18,105.773-38,85.832
    c22,53.754-140.593,54.177-122,2.602C21.43,178.364-2.07,78.227,47.43,73.458z;

    M105.42,28.169
    C115.013,12,212.013,15.571,214.013,54.738c42.794-18.885,77.734,79.958,37.435,96c28.872,29.477-84.834,76.648-107.615,26
    c-27.82,51-143.833-6-108.82-63C-17.929,88.663,60.013,12,105.42,28.169z;

    M190.986,40.122
    c55.688-19.871,116.554,42.993,54.393,67.882c65.926,13.175,11.007,85.303-49.212,71.935
    c-0.647,32.154-157.996,13.006-128.21-27.458c-80.294,15.897-80.926-101.588-3.887-88.153
    C34.285,21.335,183.863,4.355,190.986,40.122z;

    M236.013,80.738
    c46.55,18.449,40.876,101.678-13,83c-12,35.231-130,41.669-139,13c-30,28-91-69.5-40-85c-40-41,51-85,81.693-61.14
    C141.513,3.738,277.013,52.738,236.013,80.738z;

    M236.5,140.163
    c27.5,37.281-59.5,78.029-93.945,36.414C124.321,220.712,24.5,183.946,43,143.631c-44.5-0.433-18-105.773,38-85.832
    C59,4.045,221.593,3.622,203,55.197C262.5,35.257,286,135.394,236.5,140.163z" />

  </path>
</svg>
  • Gave run and didn’t work...

  • Ups, only tested in Firefox and Safari!

  • In fact Chrome doesn’t work! I’ll see why!

  • Okay, there is a bug in Chrome that affects the keyTimes parameter but we can supply the command and in this case it does not affect the https://jsfiddle.net/khnsoynhanimation/

  • @helderk as much as your example works, don’t just use the link to demonstrate the result. Elaborate your answer better and explain the solution directly in your reply. If the link goes off the air or is removed, your response will be invalidated.

  • @Celsomtrindade That’s right.

Show 1 more comment

2

I’m gonna give you a little more theoretical background from experience, maybe it’ll help you, come on.

From what I understand, you don’t exactly want to convert an animation that is being rendered into a <canvas> for svg, you want to create animation via Javascript, giving output to SVG right?

To get to the point, there are two well-known libs for this purpose, detail is that both are from the same author.

Raphaël.js

snap svg

Because it is worth using Snap.svg/Raphaël.js?

Both do basically the same thing, you write javascript, and they will output in SVG.

Raphaëljs, works from IE6 and Snap.svg from IE9, IE, you will have a very high marketshare coverage even using Snap.

Between the two, I recommend Snap because it’s more modern, addresses more new features, is simple to use, supports animation, is documented and has examples of how to use it. You can also load an external svg or Parsing an already loaded svg into the page, into the Snap and use it to manipulate svg, which gives you the advantage of importing vectors from Illustrator for example, instead of drawing them via javascript.

Well I hope it can help you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.