Animations: CSS3 or GIF? - performance

I'm working on a client-side web app that is meant to run on an iPad 1.
Besides the fact, that the framework I'm using is slow-as-a-snail (not my choice), the app is making a lot of calls to the server. Right now i'm working on a "Loading..." screen. My question is:
Should I use CSS3 animations or simple GIF animations? Which one is faster?

In my experience on iPhones and iPod Touches (not iPads, but I take it they'll probably be about the same), GIFs are several orders of magnitude slower in animation than CSS animations, transitions, or what have you. I think their framerate is deliberately slowed, maybe to save battery life.

the app is making a lot of calls to the server
Using GIF animations would require another call to the server to fetch the image. If the implementation times are comparable, using CSS3 seems more appropriate; it would likely take fewer bytes, and ride along with your existing CSS file.
A more pragmatic answer is that it doesn't matter, for a simple animation the speed difference is negligable. And if your app already requires a loading screen, why worry about how long the loading screen takes to load?

Related

Best low level canvas library for making interactive animations?

I'm evaluating canvas libraries, and my needs are:
I want to make it easy to build nice looking buttons that move
around and on which I can easily capture events. Button drawing
helpers would be cool
I'll be building a system for others to use to create animated
scenes combining moving test, images, and sound. I won't ever be
drawing complex shapes myself, the most I might be drawing is
buttons around some text.
I do not want to be totally insulated from the low level machinery
of the per-frame drawing callback. Helped along sure, but
I'm going to be syncing with Web Audio API stuff and want to keep
access to super tight timing control
I'm comfortable with pretty low level scripting of animation, would rather not have it be something that changes Canvas into some
totally different paradigm, but not sure on this point
needs to work well for touch on iOs
I'd ideally like to be using one with good docs and a high truck number. The state of Canvas libs reminds me of the state of JS libs
10 years ago, and I'd rather not invest in something that doesn't
have an actual "team" behind it. Truck number == 1 worries me.
You flagged KineticJS, so I can say a little bit about how that would work.
1) It's a great tool for tracking shapes on a canvas, capturing clicks, and moving them around. It's easy to place an image on any shape, but I would use another program to make those images.
2) Even if you don't do a lot beyond buttons, KineticJS provides some nice features for manipulating the canvas, and I'm sure you'd use a lot of them in making tools for others.
3) KineticJS provides an animation object that repeatedly calls the draw() method for you. You define your draw method in order to create animations.
4) It's more of a wrapper around canvas. You work with a Stage and Layers, but there is still a lot of transparency to the canvas itself, and you can always do direct manipulation as well.
5) You can capture a broad range of events including "touch", "click", etc. It's easy to treat them the same when appropriate or differently if you need to. Furthermore, you can simply mark shapes as "draggable" and it handles all that appropriately.
6) Kinetic has had spectacular documentation and examples, but in looking now, the tutorials seem to be missing from http://kineticjs.com/ and I can't find them elsewhere. That's minorly worrisome, but the docs are still there and my guess is that they'll be back up soon since KineticJS is still under active development.
I'll weigh in on #1:
Nice looking buttons:
Hands-down...use Adobe Illustrator to create a set of button vector images (.svg).
If you need low level control over the button design at run-time then convert the Illustrator images to canvas drawing commands with this great plugin from Mike Swanson:
http://blog.mikeswanson.com/post/29634279264/ai2canvas.
The key here is that canvas will scale the vector button for you so you're always getting a professional, polished look both on a small mobile screen and a large desktop screen.
You could use canvas to build each part of a button from scratch, but don't reinvent the wheel.
A good animation library is Greensock. It also helps you build timelines (kind of like Flash timelines).
http://www.greensock.com/gsap-js/
As to canvas libraries, check out Stackoverflow's sister site that offers software recommendations:
http://softwarerecs.stackexchange.com
Good luck with your project!

Using SWF animation in Haxe/OpenFL applications

As great as Haxe got with NME/OpenFL the big problem transitioning from AS3 development are assets. As much as Haxe is similar to as3 and OpenFL tries to provide a familiar API the lack of SWF support scares away many developers.
My research on this topic led me to understand that current SWF is rather weak and buggy with many edits necessary to SWF file in order to run it in Haxe.
The question is how do you use SWF animation in OpenFL apps, or if you don't - whats the best solution you've found regarding rendering time, processor time and file size.
Having spent more time on the research and asking other developers I put together a small list of possible alternatives to using SWF assets for animation. Hopefully it will help other developers, who has a similar problem while the SWF animation support is weak.
NOTE: all methods were selected considering three factors important for me: availability on all platforms, performance and file-size of assets. Therefor not all possible methods were included.
Tested on: HTML5, Android, iOS
SWF animation is possible with Haxe/OpenFL, but there are few rules: no tweens - all animations are frame-by-frame. Vector art should be cached as bitmap, saved as bitmap or pre-rendered as bitmap sequence as on some platforms (e.g. neko) vector art is being transformed to raster with ugly bitten edges. Some bugs were reported if representing MovieClip's as graphics or vice versa, but I didn't notice any bugs on HTML5, Flash, iOS, Android releases. Nested animations sometimes might skip frames if looped (didn't see that either, maybe older release of NME/OpenFL did that). I'd say this is a fairly good way to animate content from the concern of file size and platform availability, but it's a headache to edit all the assets to meet requirements of Haxe support. And it's not fun to reuse these assets later, since they're all frame-by-frame animations and it's a mess.
Sprite sheet animations. Primary used for HTML5 targets due to higher rendering performance. This is directly from a openGL standard, so this method should apply for all openGL targets. The idea is to rather have one big file and save time on opening/loading multiple smaller files. The performance is good, works on all tested platforms, but the file size get's quickly out of hand and can be hardly used for animations where object size is changing in size - makes unnecessary large transparent space, rotating the image to best fit the space reduces rendering performance with editing the transformation matrix on run-time.
Frame sequence aka PNG sequence animation. Personal favorite. It works well and fast on all platforms, it's possible to pre-render the the animation (just like any other method above), transform to BitmapData array, stream-load etc. It does take a lot of disk space for the animations, but can be softened by loading the assets before using them (HTML5, SWF) and it doesn't really matter for mobile devices - as even 1-2GB apps are ok for the market. Large advantage that I found for myself is that this type of asset can be used for any other developing standard (C++, Java, cocos2d) and saved as Sprite sheet if needed (e.g. cocos2d, like HTML5 prefers Sprite sheets over anything else as written in the official book COCOS2DX by Roger Engelbert).With this flexibility, good performance is tolerable file size I prefer this method over any other method listed above.
Bone animation - PNG array + property list. Another approach is having separate images of an animated object and every image matrix data for every frame. That way with minimum disk space use it's possible to make thousands of animations. The downsides are: it's harder (not impossible) to have nested animations for more complex animations, constant matrix transformations limit number of active animations on the display list (horrible method for HTML5, other platforms held on well) and little reusability of assets. Usually it's the same good old SWF assets that were exported to this type, so it makes sense to edit the FLA rather then the bone animation itself.
Surely I've missed some great points, there are many ways to animate graphics and some might work for you better than others so feel free to leave comments and criticize, but I still hope this topic was helpful.
This question might be obsolete. I compiled a C++ app in Haxe/OpenFL just 5 minutes ago and had no trouble getting SWF animations (with tweens) to work.
Here's a gif recording:
https://imgflip.com/gif/7l02f
I had an asset called "library.swf" containing that animation, exported as class "Oluv"
This requires the "swf" library which is now free, and can be installed with "haxelib install swf"
In my example, I added this to my application.xml file:
<haxelib name="swf" />
<library id="oluvLib" path="assets/library.swf" type="swf"/>
Then put this in a standard OpenFL template project:
Assets.loadLibrary("oluvLib", swfAssetsLoaded);
private function swfAssetsLoaded(library:AssetLibrary):Void {
var oluv = Assets.getMovieClip("oluvLib:Oluv");
addChild(oluv);
oluv.x = (stage.stageWidth - oluv.width) / 2;
oluv.y = (stage.stageHeight - oluv.height) / 2;
}
Tweens do not seem to work on neko target, but they work fine in C++, and flash (of course).

What's the best way to cycle through a large number of fixed position images in WebKit efficiently?

I'm currently working on a little site for my family. One of the things I wanted to do was to make a basic 'making of' stop-motion video. I could assemble it and upload it to Vimeo or something but I thought it was a perfect opportunity to use nothing but HTML, CSS, and Javascript.
I've got everything styled and my JS is working, etc. except that it performs atrociously in Chrome and Safari. Interestingly, it works great in Firefox and I'm not supporting it yet in IE. I'm hoping for 8 to 12 frames per second, with music playing, which I haven't bothered trying yet due to this. Bad performance is anything less than that. Currently I'm getting roughly 3 fps in Firefox (acceptable, but not what I was looking for) and in Chrome and Safari I'm getting roughly .6795 fps.
When running the Chrome Profiler, I get the following (relevant) output.
99.96% 99.96% (program)
0.03% 0.03% (garbage collector)
0.01% 0.01% script.js:5:nextSlide
I've never used the Profiler before but I believe this is showing me that my JS is not what's hitting the performance so hard.
I've published a test page that documents the performance differences that you can visit with Chrome and Firefox.
I've also discovered that this seems to be related to the images cycled. Cycling different, simpler images seems to work just fine in both Chrome and Firefox, despite the fact that Chrome is still a little more power hungry than Firefox.
As further proof of at least this conclusion, though it's entirely unacceptable, is demonstrated here, after running the images through convert -compress JPEG -quality 1. They cycle much more efficiently, but of course the quality is terrible.
I have run these test pages in Chrome (16.0.912.63), Safari (5.1.2 (6534.52.7)), WebKit nightly (Version 5.1.2 (6534.52.7, r102985)), and Mobile Safari (latest as of 2011/12/28) and only Mobile Safari performs as well as FireFox. The desktop browsers were tested on a MacBook Pro.
2.7 GHz Intel Core i7
8 GB 1333 MHz DDR3
Interestingly, Mobile Safari on an iPad 2 performs as well as FireFox when rendering the test page. Though Mobile Safari is based on WebKit, in this instance it performs entirely different.
Decreasing the setTimeout call to 144 from 244 also seems to not do anything. I've arrived at 244 entirely arbitrarily at this point as it became clear early on that the timing of the display compared to the call didn't seem to correspond nearly directly. This leads me to believe that I'm rendering the slide show as quickly as I can on each browser.
So my question is, how can I make this performant in WebKit?
You can debug the page performance in Chrome using the Timeline tab under the Chrome developer tools. The problem with your script is that your repaint cycle is simply too expensive, it currently takes 1.35s to repaint every frame.
The bad performance has nothing to do with the quality of the jpeg images (although the image quality also affects the page render time). The problem is that you are updating the z-index which causes the Chrome to repaint all images instead of just the next frame (You have a O(n) image slider website!).
The browsers try to do the minimal possible actions in response to a change e.g.: changes to an elements color will cause only repaint of the element.
Changing the element z-index property is basically the same as removing a node from the tree and adding another node to it. This will cause layout and repaint of the element, its children and possibly siblings. My guess is that in Chrome, the siblings are being repainted too, this explains the horrible performance.
A way to fix this problem is to update the opacity property instead of the z-index. Unlike the z-index, the opacity does not modifies the DOM tree. It only tells the render to ignore that element. The element is still 'physically' present in the DOM. That means that only one element gets repainted and not all siblings and children.
This simple changes in your CSS should do the trick:
.making-of .slide#slide-top {
opacity: 1;
/* z-index: 5000; */
}
.making-of .slide {
position: fixed;
/* z-index: 4000; */
opacity: 0;
....
}
And this is the result, the repaint went from 1.35s to 1ms:
EDIT:
Here is a jsfiddle using the opacity solution, I also added CSS3 transitions (just for fun!)
http://jsfiddle.net/KN7Y5/3/
More info on how the browser rendering works:
http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/
I took a look at the code on your site and found two things that are limiting the speed.
1) In the JavaScript, you have a timeout of approximately 1/4 second (244 milliseconds). This means that your best-cast frame-rate is about 4 FPS (frames-per-second). This can be fixed by simply reducing the delay to match the frame rate that you actually want. I see that your most recent edit addresses this point, but I didn't want to ignore it since it is ultimately critical to achieving the higher frame-rates that you want.
2) You are using z-index to control which image is visible. In the general case, z-index handling allows for objects that have different sizes and positions to be ordered so that you can control which object is visible at locations where two or more objects overlap. In your case, all of the objects overlap perfectly, and the z-index approach works fine except for one major problem: browsers don't optimize z-index processing for this case and therefore they are actually processing every image on every frame. I verified this by creating a modified version of your demo which used twice as many images -- the FPS was reduced by nearly a factor of 2 (in other words, it took 4 times as long to display the entire set).
I hacked together an alternative approach that achieved a much higher FPS (60 or more) under both Chrome and Firefox. The gist of it was that I used the display property instead of manipulating z-index:
.making-of .slide#other {
display: none;
}
.making-of .slide#slide-top {
display: inline;
}
and the JavaScript:
function nextSlide() {
...
topSlide.id='other';
nextTopSlide.id='slide-top';
...
setTimeout(nextSlide, 1);
...
}
I made some changes in the HTML too, notably including id="other" in the tag for each image.
So why is WebKit so slow? As has been pointed out in other comments, the extra-poor performance that you are seeing on Webkit seems to be Mac specific. My best guess about this is that the Mac version of WebKit is not actually using the "turbo" version of libjpeg (despite the fact that it is listed in the credits). In your test, JPEG decompression could very well be the gating factor if it is actually decompressing every image on every frame (as is likely the case). Benchmarking of libjpeg-turbo has shown about a 5x improvement in decompression speed. This roughly matches the difference that you are seeing between Firefox and Chrome (3 FPS vs. 0.6795 FPS).
For more notes on libjpeg-turbo and how this hypothesis explains some of your other results, see my other answer.
Key in my experience is to keep as less as possible images in the DOM and in javascript arrays, so don't load all of the at once, keep it to a minimum. Also make sure you destroyed already used DOM elements as well as javascript objects holding images, manual garbage collection. This will improve performance.
Random guess: GPU acceleration. It is device-dependent, and there is a big race among browsers now.
You could try with a more recent Chrome like the canaries, http://tools.google.com/dlpage/chromesxs (it's 18.x now), just to get more data.
about:version in Chrome should give you version of WebKit.
Also, have you tried existing slideshow solutions like http://jquery.malsup.com/cycle/ ? I wonder if playing with the z-index is the bottleneck here... maybe having only 1-2 images displayed (all the rest using display:none) would help. This is again a guess.
The best way to achieve better performance when it comes to graphics is to compress them, but like you want, but keep
If you are using Linux, I have used JPEG compression tool http://linuxpoison.blogspot.com/2011/01/utility-to-optimize-compress-jpeg-files.html before. It doesn't hurt quality as much as the ImageMagick example you gave.
Also http://trimage.org/ has JPG support, and would be my first recommendation!
If you are on Windows, maybe something like this:
http://www.trans4mind.com/personal_development/convertImage/index.html
I have not tested the Windows method, and I'm not even sure it supports batch
Hope that helps!
P.S. For PNGs I use sometimes use http://pmt.sourceforge.net/pngcrush/ along with or without http://trimage.org/
There has been some relatively recent work on the JPEG image compression library that is used in many applications including browsers such as Firefox and Chrome. This new library achieves a significant speed increase by using special media-processing instructions available in modern CPUs. It may simply be that your version of Chrome doesn't use the new library.
Your question requests a way to fix your images, but that shouldn't be necessary -- after all, some other browsers work fine. Therefore, the fix should be in the browser (and browsers are constantly being improved).
You said that you improved Chrome's speed by dramatically reducing the quality or complexity of your images. This could be explained by the fact that for areas of very low detail, the JPEG decompression algorithm can bypass a lot of the work that it would normally need to perform. If an 8x8 tile of pixels can be reduced to a single color, then decompression of that tile becomes a very simple matter.
This Wikipedia article provides some additional info and sources. It says that Chrome version 11 has the new library. You can enter "chrome://credits" in your location bar and see if it references "libjpeg-turbo". "libjpeg" is the original library and "libjpeg-turbo" is the optimized version.
One other possibility is that libjpeg-turbo isn't supported in Webkit on the Mac (although I don't specifically know that). There is a hint as to why that might be the case posted here.
P.S. You may get better decompression speed by compressing with a different algorithm, such as PNG (although your compression ratios will likely suffer). On the other hand, maybe you should use HTML5 video, probably with the WebM format.
I tested it in opera and it ran slow as hell, i noticed that opera had queued 150+ images to download it could be worth a try to download ~20 at a time?
An alternative approach would be to render this content as a video - it is ideal for this kind of thing and can easily contain audio and subtitles. You can access each pixel from each frame using JavaScript if you want to get funky.

Should I use HTML5 Canvas or CSS3 Sprites to animate objects for a game?

I'm in the process of starting to build a strategy game (think warcraft) for the web. I've been doing research on HTML5 Canvas and CSS3 sprites and still can't decide which technology to use.
The game won't be completed for another 6 months.
Any advice would be appreciated.
As you probably hear so frequently... "It Depends..." ™
My suggestion would be consider the feel of the application you're after. If you are trying to build a very graphically rich, mostly-images application, then I would use Canvas. However if you are trying to animate some graphics, but have the page remain and behave more "Web-like", mixed with other HTML content, I'd give CSS3 a try.
Two additional points:
Currently, Canvas is better supported than CSS3 animation/sprites.
If you use Canvas you're going to be implementing your own render loop and animation code (or making use of a 3rd partly library). Your code create animation by compositing the various layers of each frame, applying movement, and repeating. You can't simply say "move this image a little to the right". You'll have to do that yourself.
The EA web game "Lords of Ultima", as dull as it is, is an excellent example of a WarCraft-styled (well, it's more city building as there are no visible units) overworld, with animations and everything, built on a pure HTML and CSS sprite base. It looks and performs well and I think the square block box-model nature of HTML suits that kind of tile based design, especially since a lot of the image processing (embed an <img> or a <div> with a background, change background-position for animation) and click/mouse handling is done for you in simple html.
If you do go canvas you have to manage that yourself which will greatly increase the complexity and dev time. You'll have more control of minor elements and improved performance, but then you'll also lose (if it's at all important), greater backwards compatibility with older browsers. So it depends on how complex your design is and what kind of performance you need.
Use Canvas. If you use CSS sprites to build a game, then you are going to make a lots of <div>'s which performs operations on the DOM, which may slow down and also have a lots of focus and compatibility problems.
It may pay off to trade the development time for performance on <canvas>, by the assumption of "A code will be maintained forever".
I think CSS3 sprite system takes more time to develop, because you need to handle browser compatibility.
Browsers like IE 8 (8 or 9?) are using GPU to accelerate graphics, which lets you get the free lunch of Moore's Law.
There's pros and cons to both. Currently, Canvas is better supported then is CSS3, but you said that your game won't be done for another 6 months, by then the support for CSS3 could be much much better. There's also a lot of other variables here, such as: What browser will the game be viewed on? How advanced are the graphics you need to animate? etc... I would say that canvas would be better for support of the current generation of browsers and for gaming graphics, however CSS3 would be quicker, but wouldn't even come close to the support or graphics handling. But it doesn't seem like your in a rush to get it done.
Basically:
Canvas: Graphics, current support in users browser
CSS3: Speed of development
Ether will work. But for now I would use Canvas. However, 6 months in the tech world is an eternity, things could be a lot different then.

Browser Repaint/Reflow performance: using CSS3 Gradients vs PNG Gradients

I am working at an app that causes lots of browser reflows. Performance is a key issue here. From the performance point of view Is it better to use a CSS3 gradient or an image gradient for some DOM elements? Does a page that uses CSS text shadows and gradients will have a slower reflow as a page that uses images to achieve those visual effects?
Also, are there any reflow tests out there I can use?
For drawing, CSS gradients and shadows do task the CPU more than images. Performance used to be pretty bad, these days they are acceptable. If you have a ton of gradients/shadows, you should just implement them and do the tests in your real-world setting. If you just have a few, I wouldn't worry about it.
It depends a lot on how the browser renders it, but for the most part those things will render slower. In addition, you'll have a less pixel-perfect display in older browsers. However, this also serves to segment your audience, as generally those with updated browsers also have updated computers. So, it's a trade-off that can work in your favor to essentially serve a stripped down version of your site to those that wouldn't be able to handle it. It's not guaranteed, but I've found it usually balances out pretty well.
Overall, real-world testing is the way to go. Build it, see if it works, and fix performance issues once you find them. I wouldn't hesitate just because there's a chance it might not work. If it works just fine and you don't try it, you'll never know!

Resources