How to Create Animated Series of Images Html
How to Create Animated Series of Images Html
This article was peer reviewed by Giulio Mainardi. Thanks to all of SitePoint's peer reviewers for making SitePoint content the best information technology can exist!
Imagine your designer asked you to implement a cute frame by frame animation for the awesome project you've been working on. Every bit the front-cease dev on the project, not only is it upward to you lot to come with a working animation, but also to deliver a silky smooth, performant and maintainable frame by frame animation that works groovy beyond unlike browsers, both on desktop and mobile.
This tutorial shows you the diverse ways yous tin can create this blazon of animation with HTML, CSS, and JavaScript, while improving on each iteration to achieve the best result for your projection.
What Is a Frame by Frame Blitheness?
According to this definition past Adobe, a frame past frame animation:
… changes the contents of the Stage in every frame. Information technology is best suited to complex animation in which an image changes in every frame instead of simply moving across the Stage.
In other words, the subject area of the animation is represented in a set of images. Each image in the set occupies an blitheness frame, and the rate of change with which each frame replaces the next produces the illusion of motility in the image.
I volition demonstrate the whole workflow as you'll be working on this great blinking centre blitheness from Zeiss website.
This is the gear up of images you'll exist using to build the blitheness frames:
And here's the terminal outcome:
For this tutorial, I've chosen to use SVG images because they are not bad at scaling with unlike screen sizes for responsive spider web design. However, if for any reason you lot don't desire to use SVG graphics, you lot tin create spider web animations with PNG, JPEG, and GIF prototype formats or use HTML5 Sail. I will share my thoughts on these alternatives at the cease of the article.
For simplicity'south sake, in this tutorial you lot'll exist using the jQuery library and have Autoprefixer up and running, therefore the code will be gratuitous of browser-specific CSS prefixes.
At present, permit'southward practice some coding!
1 — Frame past Frame Animation by Irresolute the Image's Source
The offset option is straightforward plenty, and that's one reason why I like it.
In your HTML document, create an img
element, which acts as container for the images, one at a fourth dimension, every bit each animation frame is replaced by the next:
<img class = "eye-animation" src = "/images/Middle-1.svg" alt = "blinking center animation" />
The CSS:
.eye-animation { width : 300 px ; }
The next stride is to supplant the existing image with the side by side one over a menstruum of time dynamically, so every bit to create the illusion of movement.
Y'all could do information technology with setTimeout
but it's better to use requestAnimationFrame
. Doing so has some advantages from the indicate of view of performance. For example:
- The quality of other animations on the screen won't be affected
- The browser will finish the blitheness if users navigate to another tab.
Here's the jQuery code:
const $element = $ ( '.eye-animation' ) ; const imagePath = '/images' ; const totalFrames = 18 ; const animationDuration = 1300 ; const timePerFrame = animationDuration / totalFrames; permit timeWhenLastUpdate; let timeFromLastUpdate; let frameNumber = 1 ; function stride ( startTime ) { if ( !timeWhenLastUpdate) timeWhenLastUpdate = startTime; timeFromLastUpdate = startTime - timeWhenLastUpdate; if (timeFromLastUpdate > timePerFrame) { $element. attr ( 'src' , imagePath + ` /Eye- ${frameNumber} .svg ` ) ; timeWhenLastUpdate = startTime; if (frameNumber >= totalFrames) { frameNumber = i ; } else { frameNumber = frameNumber + ane ; } } requestAnimationFrame (step) ; }
When the page loads, yous phone call requestAnimationFrame
for the first time and laissez passer the step
function to it, together with the blitheness'due south startTime
parameter built into the requestAnimationFrame
function.
At each footstep the code checks how much time has passed from the last image source update and, if it'due south longer than the required fourth dimension per frame, then it refreshes the image.
Because y'all're building an infinite animation, the code above checks if information technology'south got to the last frame and if so, it resets the frameNumber
to 1; if not, it increases the frameNumber
past 1.
Images should have the aforementioned name structure made of an increasing number serial and the aforementioned location (e.chiliad., images/Eye-i.svg, images/Eye-2.svg, images/Eye-3.svg, etc.) and then that the code can easily iterate through them.
Finally, call requestAnimationFrame
once more to continue the whole process.
It looks good. However, if you try this y'all'll see information technology won't work because when the blitheness starts, just the first image gets loaded. The reason for this is that the browser knows nothing about the images you want to display until the lawmaking updates the epitome element's src
aspect in the middle of the animation loop. For a smooth animation, you need to preload the images before the loop starts.
There are unlike ways you can practise this. Here's the one I similar all-time. It consists in appending hidden div
s and setting their background-image
belongings to point to the required images.
The jQuery code:
$ ( document ) . set ( ( ) => { for ( var i = 1 ; i < totalFrames + one ; i++ ) { $ ( 'body' ) . append ( ` <div id="preload-image- ${i} " style="background-image: url(' ${imagePath} /Heart- ${i} .svg');"></div> ` ) ; } } ) ;
Here's the full working demo on CodePen:
Run across the Pen Frame by frame-animation-1-source by SitePoint (@SitePoint) on CodePen.
Beneath I've listed some pros and cons to this approach.
Cons:
- With
HTTP v1.1
, having to load multiple images tin can significantly increase folio load time on the get-go visit - The animation can exist janky on mobile devices. That'due south because the browser has to perform a repaint each fourth dimension the image element'due south
src
attribute is updated (please check out Paul Lewis' weblog post for the details).
Pros:
- Declarative — the code but iterates through the set of images
- The image is fixed in one place — no jumping back and along is visible (you lot'll see why this is important beneath).
2 — Frame past Frame Animation past Changing the Image'south Opacity
To avoid browser repaints, you could change the images' opacity instead of irresolute their source.
You could render all the images with opacity: 0
at page load and so ready opacity: 1
for exactly when you want to evidence that frame.
That would amend rendering performance, but you'll still have to preload all the images up front (which could be tricky if you lot have other images on the page equally well and don't want to wait for all of them to load). Besides, considering of multiple images, you'll even so accept a longer first-fourth dimension page load elapsing.
Here'southward the full code:
You can avoid HTML code duplication by leveraging the capabilities of template engines such equally Pug, Twig, React, Angular etc., or by but appending the div
south using JavaScript as you did in the previous case.
three — Frame by Frame Animation by Changing the Sprite's Position
The usual workaround to forestall having to download multiple images consists in using an image sprite .
And then, permit's do that.
Put all your images in one sprite by creating a line of frames that preserves the images' order, i.due east., the beginning epitome volition be the leftmost and the terminal epitome will be the rightmost. Then, using CSS animations, move the sprite left to right frame by frame.
The HTML:
<div course = "centre-animation" > </div >
The CSS:
.center-blitheness { width : 300 px ; peak : 300 px ; background-image : url ( '/images/blinking-heart-sprite.svg' ) ; background-size : 1800 % , 100 % ; background-position : left; background-echo :no-repeat; animation-proper name : eye-fill; animation-duration : 1.3 s ; animation-timing-function : steps ( 17 ) ; animation-iteration-count : infinite; } @keyframes eye-make full { from { groundwork-position : left; } to { groundwork-position : right; } }
The code to a higher place sets the background-size
belongings depending on the number of frames — considering there are 18 frames, it sets it to 1800%
.
The initial background-position
is left
then that at the beginning of the animation, the first image is shown.
Then, with keyframes animation, the lawmaking gradually changes the position of the background to right
over the time set up in the animation-duration
property (1.3s
in the example in a higher place).
The animation-timing-office
property allows you to build a step by stride animation which ensures users won't see one-half of one frame and half of the following frame both at the same time. This introduction to CSS sprite canvass animation by Chris Mabry is a perfect explanation of how this approach works.
And you don't need JavaScript. Yay!
Cons:
- It requires a browser repaint each time the sprite'southward position changes, which can lead to janky animation on mobile
- If the prototype'south width in pixels has many digits after the decimal point, the paradigm can wobble left and correct during the animation (though rounding the image's size to 2 digits subsequently the decimal signal should be plenty to ready the trouble):
Pros:
- No JavaScript
- Only i image to load, which is good for first-time page load performance.
4 — Frame by Frame Animation by Moving the Sprite with Transform
Same every bit previously, you're now going to upgrade the solution implemented above in such a way equally to avert a browser repaint. You will do this by changing but the transform
property of the chemical element rather than its background-position
.
For this purpose, put the div
you lot want to animate inside a wrapper. This enables you to translate the position of the whole HTML element instead of its groundwork.
Next, position this div
admittedly inside the wrapper and get-go animating it with the help of the translateX
property.
The weird -94.44444444%
comes from having 18 slides and moving the image only 17 slides from the first one (17 / 18 * 100%).
The HTML:
<div class = "center-animation__wrapper" > <div class = "centre-animation" > </div > </div >
The Sass lawmaking (feel free to use CSS, if you prefer):
.eye-blitheness { width : 1800%; pinnacle : 100%; background-paradigm : url ( '/images/blinking-eye-sprite.svg' ) ; background-size : 100%, 100%; background-repeat : no-repeat; blitheness-name : eye-fill; blitheness-duration : 1.3s; animation-timing-office : steps(17); blitheness-iteration-count : infinite; position : accented; left : 0; top : 0; &__wrapper { overflow : hidden; position : relative; width : 300px; height : 300px; } } @keyframes eye-make full { from { transform : translateX(0); } to { transform : translateX(-94.44444444%); } }
It definitely looks improve now!
However, at that place is one bug in IE, which doesn't allow for the employ of percentage values for the translate
holding
inside animations. caniuse.com provides an instance and explanation for that within the known issues tab:
IE10 and IE11 on Windows 7 have a bug where translate transform values are always interpreted every bit pixels when used in animations.
Every bit fallback, you'll need to detect the browser using JavaScript and provide a separate blitheness for this specific case.
transform: translate3d(0, 0, 0)
beneath tells the browser to movement the element into a separate compositing layer, which improves rendering performance.
Hither'due south the JavaScript code:
var isIE = / Edge\/\d. / i . test ( navigator . userAgent ) || / trident / i . examination ( navigator . userAgent ) ; if (_this. isIE ) { $ ( 'html' ) . addClass ( 'ie' ) ; }
And the Sass code:
// fallback for IE .ie { .center-animation { transform : translate3d(0, 0, 0); animation-proper name : eye-fill-ie; } } @keyframes eye-fill-ie { from { left : 0; } to { left : -1700%; } }
Have a play with the code in the live demo below:
Cons:
- Exist aware of image quaking if sizes are also precise
- It doesn't piece of work in IE, though a fallback is bachelor.
Pros:
- Only ane prototype to load, which is skillful for first-time page load performance
- No janky blitheness on mobile because no repaints are involved!
Using Inline SVG for Your Frame by Frame Animation
1 possible improvement would be inlining the SVG paradigm (i.e., dumping the SVG code straight into your HTML page) instead of pointing to it as an external resources.
Typically, external resource are cached by the browser. This way, on a repeated visit the browser uses the locally cached version of the file instead of making a new request to the server.
However, if the probability of the page being revisited is depression (say, a landing page), so it makes sense to use inline SVG, because doing so reduces the number of requests to the server and decreases the start-fourth dimension folio load time.
Sprite-Transform Has the Best Rendering Performance
To be 100% sure well-nigh performance, I created a functioning examination for all four dissimilar approaches and this is the outcome I got using Chrome:
if yous want to play with it, you can reproduce the tests using any other browser of your choice on jsPerf.com.
5 – Why Non GIF for Frame past Frame Animation on the Web?
If the ability to scale with unlike screen sizes is not a requirement, and so a GIF file could be an option too. Simply together with scalability, y'all'll besides lose the ability to command the animation period like finish, reverse, or combine it with other animations. And you lot unremarkably stop up increasing the size of the asset, which affects performance.
If you desire to deep dive into the reasons why SVG is preferable to GIF, and so cheque out Sara Soueidan's excellent article on the topic.
6 – Why Non Canvas for Frame by Frame Animation?
If yous have a small screen and multiple animated objects at i time, Canvass would be an first-class choice. Performance is fabulous, merely this arroyo comes with several drawbacks:
- In Canvas, y'all can't use inline assets, which ways this might non be the best selection for one-fourth dimension visited pages
- Canvas API knowledge is required to build such a solution, which adds to the application maintenance costs
- No support for DOM events — then, for case, y'all couldn't practise something with the DOM exterior of the
canvass
element in one case the animation is finished.
There are a few more than arguments for and confronting Canvas over SVG, simply if yous make up one's mind to get with Canvas, then caput over to William Malone'due south tutorial on this topic, which does an outstanding task at explaining how you tin can achieve the best results.
Conclusion
Nowadays, you have plenty of options for implementing frame by frame spider web blitheness. This is generally a practiced affair, simply having to choose what works all-time could be confusing. The points beneath will assistance you lot make the right decision:
- Utilize SVG over GIF/PNG/JPEG if you intendance almost scalability and responsiveness
- Animate the
opacity
andtransform
properties if you care about rendering functioning - Employ sprites and inline SVG over multiple external assets if you intendance about first-fourth dimension folio load operation
- Use sprites over inline SVG if y'all care about folio load performance during repeated page visits
- Use whatever solution you and your team feel comfortable with, if it keeps your code more readable and decreases maintenance costs inside the squad.
Which method exercise you go for to create your frame past frame web animations? Let me know in the comments.
How to Create Animated Series of Images Html
Source: https://www.sitepoint.com/frame-by-frame-animation-css-javascript/
Коментарі
Дописати коментар