Why are these particles slower with CSS3 GPU transforms? - javascript

Why does this example run slower when the position is set by translate3d(x,y,z)?
My guess is that every change to the CSS requires a recalculation of the style, which is less expensive when the element isn't being sent to the GPU. Is there a way to do the dynamic transitions that I need without recalculating the style?
I'm interested in running in a WebView on iOS and Android. Is CSS3 the only option for accessing the GPU? Is there a way to use the GPU to increase performance here?

A good way to use the GPU for accelerated drawing on mobile webviews is via the <Canvas> element. This similar example is able to move four times as many particles at a similar framerate:
Canvas Particles

Related

Jittery text during scaling animations with JavaScript

When using scaling to change the size of an HTML element containing text, the text jitters during the animation, but only if being animated with JavaScript libraries.
The jittering is most visible when the animation is slower and the text is smaller. I can't seem to figure out what causes it or how to get rid of it.
This jittering does not occur during CSS animations or animations using the fairly new JavaScript Web Animations API. It also doesn't seem to occur in some browsers. (On my iPhone)
To easily compare the different methods of animating the scaling of an element and how they appear, I made a CodePen for convenience. Before checking it out, note these points:
All the animations are using some form or imitation of the CSS property transform: scale(num); for the animation and have the same easing and duration so they can be compared more easily.
Although the jittering appears on macOS too, it is almost impossible to see on Macs with retina screens because of the high resolution.
The results I got are a reflection of the appearance of the animations on a Windows 10 machine in Google Chrome 59, although for me Microsoft Edge also showed the same results.
So my question is this: How can I prevent the text from jittering or becoming blurry when animating a scale property with JavaScript? How can I make the text in my JavaScript scale animations appear just as smooth as they do when using CSS?
You may be wondering why I don't just use CSS. The answer is because I'm frustrated with how limited CSS animation is. I would like to use advanced easing functions beyond the capabilities of a simple bezier curve (like Robert Penner's bounce and elastic functions), and use different easings on hover when the mouse enters and exits the element. This s completely my own opinion, but so far the only painless way I've found to do this is with JavaScript libraries. Besides their functionality relating to easing, most seem to offer many other capabilities which make animating much more effortless. If you know of a better way to get all the functionality I need please let me know!
What you are encountering are differences in a browser's layerizing strategy. You'll find that all the examples appear smooth in Firefox. That's because Firefox detects when script is changing a property that can animated using layers and creates a layer in response.
Although all browsers create layers when needed for declarative animations (CSS animations, CSS transitions, Web Animations API animations, and even SVG SMIL animations in some cases) not all browsers do it for Javascript animations. So, for those browsers you need to try to trick the browser into creating a layer (or, you could just file a bug on the browser, since it really should do this for you!).
Until recently, using will-change: transform was the recommended approach to get a browser to create a layer. However, Chrome changed its rendering strategy and now will-change: transform can produce very blurry results with scale animations in Chrome. Some people have succeeded in tricking Chrome to layerize at a higher resolution initially and then scaling their element down before animating. This is really unfortunate to have to do this and I can only encourage you to petition Chrome to fix this.
Also, the examples using "with HA" are not accurate. The CSS animation in (1) will also use hardware acceleration in every browser I know of--there's no need to add perspective in. Unfortunately, there is a lot of misleading information in this area (e.g. some articles claim animations can run on the GPU but that's simply not true). At the risk of self promotion, you might find an article I wrote on this last year helpful.

JQuery .animate Really Choppy in Chrome Extension

I have a JQuery .animate function.
It switches between two forms.
It toggles height and opacity.
When the two forms are the same height (and the popup does not resize) the animation is smooth. When the popup has to resize, the animation becomes choppy and a thick black border appears around the popup for a couple of seconds.
Is there anyway of smoothing the animation or should I switch to CSS for my animations?
Right now, the extension is that when a label is clicked a new form appears on top of the old one.
Most likely your jQuery animate function uses 2D animations. Look into using 3D translate and transform instead.
Why would 3D be faster than 2D you ask?
Because 3D gets accelerated and rendered using the GPU, 2D does not.
I did the same thing myself not long ago and the results are vastly superior.
It is 2017. You definitely should switch to CSS transitions.
1) Don't use jQuery in Chrome extensions. It's a browser standardisation framework and you're using it in a component that only works in one browser. Instead use advanced features (such as passive events) that Chrome supports but jQuery does not.
2) Avoid changing the height of elements where that will change the size/position of other elements (or the extension pop-up).
Instead use just opacity and transform CSS elements on an absolutely positioned element to ensure that the entire animation can be handled by the GPU without reflow.

Does CSS transition perform bettern than DOM animation?

I was running something which does number scrolling using ScrollerJS. It supports two modes : CSS transition and DOM animation. When I was using the DOM animation mode, I find sometimes the scrolling is not smoother than that of CSS transition.
So I am wondering whether CSS transition performs better than DOM animation generally? Is there any proof or testing that shows this?
CSS transition : CSS3 transition/transform property which transforms an element
DOM animation : Traditional DOM animation which changing the CSS top property continuously.
In short, yes. Doing it in CSS allows the browser to optimize it, e.g. using hardware acceleration.
If you manipulate the DOM, the browser generally has to re-render the content, which is usually slower.
DOM manipulation is typically used to support older browsers where CSS animation is not supported (or poorly implemented).
From http://scrollerjs.pixelstech.net/#about
If CSS transition is supported in a browser, CSS transition will be
the preferred option for animation.
If in old browsers where CSS transition is not supported. DOM
animation will be chosen automatically.
However, note that as usual, things are never completely straightforward, and no generalization is completely true... There are javascript animation libraries out there that can rival or sometimes even outperform CSS-based transitions/animations, and they are usually more flexible. Here's some light reading:
http://davidwalsh.name/css-js-animation
https://css-tricks.com/myth-busting-css-animations-vs-javascript/
This question isn't too hard to answer.
A DOM animation uses your CPU for it's calculations and since an animation is quite heavy on the CPU it'll sometimes 'lag' which is when you see artefacts on the screen.
CSS3 transitions however are able to use hardware acceleration which uses the GPU of your computer (if it has one ofc :D). Since your GPU is much stronger and better at doing things like animating, you'll barely notice any lag if any.
This question is not easy to answer because in different cases some kind of animation performs better than the other.
I think this article could be more than interesting if we are talking (seriously) about performance between CSS and DOM animations.
If you are going to work a lot with animations and you are worry about the performance I suggest to try a more professional library like GSAP, they also have a scroll plugin.

Zooming SVG is blury or pixelated, not sharp

vI know to some extent this is a known issue that has been asked here but never answered, but I'm hoping for some additional insight.
I have a simple SVG image in a div on a web page. I want to be able to zoom the image using pinch gestures and have the SVG render sharply. It doesn't need to be sharp during the zoom, but should be sharp after the gesture is complete.
I'm doing my testing on a Windows 8.1 computer with a touch monitor, on an iPad, and on an old Android Galaxy Tab. On the main computer, I'm using IE11 and Chrome. For handling touch gestures, I'm using Hammer.js. I'm doing the zooming by modifying the transform CSS using the jQuery css() function (I'm setting scale3d and translate3d).
IE11 on my computer works exactly like I would like it to. It keeps the SVG image sharp throughout the pinch zoom and the image is always sharp regardless of when I set the CSS.
Chrome on my computer always renders the SVG blocky when I am zoomed in using pinch zoom. It is blocky during the zoom and does not get sharp afterwards. If I add a call to zoom the image after the page (x13) is loaded, the image is sharp. If I use a setTimeout() call to reset the zoom and then rezoom the image after the pinch zoom ends, the image is sharp.
On the iPad and Android tablet, the SVG never renders sharply, regardless of when I zoom it in code.
Does anyone have any ideas of how to reliably end up with a sharp rendering of SVG after a pinch-zoom is completed? Does anyone have a better solution? Using the SVG viewBox to zoom and pan during the gesture does not provide good enough performance for our more complex SVG images. I'm thinking of attempting to use the hardware accelerated scale3d/translate3d during the gesture and then attempt to convert this to new SVG viewBox settings afterwards, but this is a challenge and I'm not sure panning will work correctly after this is done. Any pointers or ideas are greatly appreciated.
Having just tried to answer your other SVG Question I will have a try at this one.
Michael Mullany is spot on that GPU translations will never give you a sharp image. This is because the GPU just maps one array of pixels to a new one. Because it has no concept of lines or rectangles the resolution is set by the time the GPU gets the image. The CPU will always struggle to re-render in time for a smooth drag.
What happens to allow some browsers to produce a sharp image is they do clever manipulations like rendering more pixels than they need so some zooming can happen without loss of resolution. These however are completely inconsistent and just not possible to rely on.
The as I see it 'correct' solution is to translate and zoom with hardware accelerated transformations during a pinch or zoom and then to refresh the viewbox with no css transformation when the translation has finished.
Challenges to overcome are
The css transformation will use screen coordinates but the viewBox manipulation will use the SVG coordinate system.
There are browser inconsistencies in both screenCTM and device pixel ratio
limits so that people don't drag or zoom too far need to be calculated in both systems
Pinch centerpoints also need to be calculated in both
To improve performance further the css transforms will be wrapped into updating on the requestAnimationFrame loop.
My working solution is hammerhead2. I am concentrating on desktops and android mobiles first and it seams to be working for them. To simplify the problem zoom is always centered to the screen center. I do however thing this is currently one of the only solutions. Here is an example of it working.

iphone/ipad large canvas vs small canvas + div animation

Since I dont have either of these devices handy to test, which method would be faster on an iphone/ipad?
One large canvas (overlayed over a bg of the same size), that is cleared, and has new pixel data drawn to it each frame, at a certain position
or
A small canvas that updates each frame, contained in a div that is animated across a background
As it turns out iphone/ipad aren't even capable of running this small animation either way. I will have to look at alternative solutions for mobile/tablet devices.
Yes, I've found the iPhone too slow in all my canvas experiment.
Even moving a simple div around (CSS3 styled, no canvas) is barely accettable ( my test with the new motion API: http://www.omiod.com/i.htm )

Categories

Resources