Reputation: 6585
Could anyone suggest what is the best way to implement frame-based animation in svg, based on JPEG's?
One example which I've found is this:
<svg version="1.1" baseProfile="tiny" id="svg-root"
width="100%" height="100%" viewBox="0 0 480 360"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="320" height="240" xlink:href="test1.jpg">
<animate id='frame_0' attributeName='display' values='inline;none'
dur='0.5s' fill='freeze' begin="0s" repeatCount="indefinite"/>
</image>
<image width="320" height="240" xlink:href="test2.jpg">
<animate id='frame_1' attributeName='display' values='none;inline'
dur='0.5s' fill='freeze' begin="0.5s" repeatCount="indefinite" />
</image>
</svg>
It works for 2 frames, but doesn't really scale. I would like to have something which can handle 100 frames and more.
Upvotes: 3
Views: 7507
Reputation: 8415
https://michaelsboost.github.io/SVGAnimFrames/
You can easily use my library SVGAnimFrames for this. Simply by calling 1 line of code...
SVGAnimFrames("#bounce svg", "repeat", "40", "0");
Refer to the Github repo to learn how to use it.
Ideally your best bet is to use a spritesheet and animate frame by frame with that which minimizes unnecessary http requests.
Upvotes: 0
Reputation: 11
An alternative approach,
If your animation is working, but it's just a matter of too much production to get the files setup, you can use a template to generate your SVG.
Use something like Grunt.Js to read all the images in a directory and then, have an underscore template build the SVG frames the way you already have them setup from an array of the filepaths.
These code snippets might not work out of the box, but it's pretty close.
Here the grunt file grabs the files in the folder, check if they're images then pushes them to an array.
// gruntfile.js //
var fs = require('fs');
var path = require('path');
var _ = require("underscore");
grunt.registerTask('Build Animated SVG', function () {
var template = grunt.file.read("/path to SVG underscore template/"); //see SVG section below.
var frames = [];
var pathtoframes = "mypath";
var mySVG = "mysvg.svg";
fs.readdirSync(path.resolve(pathtoframes)).forEach(function (file) {
if (filetype == "svg" || filetype == "png" || filetype == "jpg" || filetype == "gif") {
var frame = {};
frame.src = pathtoframes + "/" + file;
frames.push(frame);
}
});
var compiledSVG = _.template(template, {frames:frames});
grunt.file.write(path.resolve(pathtoframes) + "/compiled_" + mySVG, compiledSVG);
});
This template will get read in by the grunt file, and underscore will loop through each file and write that into a big string. Grunt then saves that out as an SVG that you can load.
<!-- SVG underscore template -->
<svg version="1.1" baseProfile="tiny" id="svg-root"
width="100%" height="100%" viewBox="0 0 480 360"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<% _.each(frames, function(frame, index){ %>
<image width="320" height="240" xlink:href="<%= frame.src %>">
<animate
id='frame_<%= index %>'
attributeName='display'
values='none;inline'
dur='0.5s'
fill='freeze'
begin="0.5s"
repeatCount="indefinite"
/>
</image>
<% } %>
</svg>
Upvotes: 1
Reputation: 15371
It's much easier:
<svg version="1.1" baseProfile="tiny" id="svg-root"
width="100%" height="100%" viewBox="0 0 480 360"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="320" height="240" xlink:href="test1.jpg">
<animate attributeName="xlink:href"
values="test1.jpg;test2.jpg"
begin="0s" repeatCount="indefinite" dur="1s"/>
</image>
</svg>
Upvotes: 4