JQuery .animate Really Choppy in Chrome Extension - javascript

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.

Related

Can I force the browser to rasterize elements before they become visible?

Call me crazy, but I'm working on a game using vanilla DOM and TypeScript. It's not action-heavy, but there are some animations going on, which are driven from JavaScript (too complex to do in CSS).
I'm already applying the common trick of translateZ(0) (called null transform hack or less accurately silver bullet) to pull animated elements into their own rendering layer, and I'm animating nothing besides compositor-only properties (transform and opacity). This works beautifully: during the game, everything feels buttery smooth, even on older mobile devices.
The problem is during the start of the game. At that moment, about 70 individually transformed and animated elements enter the page one by one over the space of a few seconds, by animating their opacity from 0 to nonzero. This is causing visible stutter during the animation.
My guess was that Chrome is being too clever here, and will only rasterize each element at the moment it first becomes visible. A quick check with the dev tools confirms this, as there's a lot of rasterization going on even during the animation:
I would prefer to rasterize all these elements once, before the animation starts, and only then trigger the animation. But how can I force rasterization of elements that aren't yet visible, without showing a flash of them to the user?
I'd be happy with a Chrome-only approach, but cross-browser would be even better.

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.

How do you move an SVG around a webpage without triggering slow redraws?

I'm using d3.js to draw a (multi)line graph (with quite a few data-points, 1600 to be exact) on an svg element.
This graph is in a container which has a transition on it.
On a certain event the container gets moved 400px to the top with a CSS3 transition which works fine in Chrome. When trying in Safari and Firefox I noticed that is was really slow. After some checks I can say with 99% certainty that the svg element gets redrawn during the transition (a lot) in Safari/Firefox (and possible other browsers, too).
Is there anyway to prevent the browser redrawing it constantly until the transition is finished? Or maybe other solutions that would make this fluent?
FYI: not drawing the chart in the SVG element makes the issue go away, so I'm certain the slowdown comes from the SVG element.
The simplified html code:
<div id="container" style="transition:margin 0.75s; -webkit-transition:margin 0.75s; ">
<svg id="simple_line" style='height:210px; width:100%;'/>
</div>
Generally speaking, using margin or any other CSS position value to make objects move around the screen is sub-optimum. Try using a transform/translation style to create the movement, which will tell the browser to use graphical optimization methods.
The idea is that a transform tells the browser to move around a block of rendered content, instead of re-calculating the whole layout. Results will still depend on the quality of the browser's implementation -- as you discovered, Chrome has good optimization either way, but this should reduce the browser-to-browser differences.

jquery masking image effect

I need to replicate this effect - http://4091.co.uk/test/mask-test.swf - using jquery/css.
I tried using this wonderful plugin - http://almogbaku.github.io/imageMask - but it needs to work in IE8 and maybe IE7 and so it was scrapped due to its use of the canvas element.
I have white divs currently, set at angles, animating in and out but it's incredibly time consuming - is there a plugin which creates this kind of effect or is there a method that would work in the IEs?
Here: http://modernizr.com/
Modernizr makes it work for every browser that doesn't support HTML5 or CSS3.

When resizing a div containing floats with javascript the floats don't reflow

I have a container div that holds about 20 more divs that float left. When I resize the parent div with a javascript animation using Tween.js the floats don't reflow to the new size unless I mouse over one of the divs.
It seems like something is preventing the page from refreshing.
I'm thinking maybe there is a way through javascript to force the display to update?
UPDATE:
I've put it on JS Fiddle:
http://jsfiddle.net/mattlundstrom/fNUhn/
Click any thumbnail to toggle the animation.
This version uses TweenLite to animate the "Left" CSS of the #project-container. Notice how you must move your mouse after the animation to get the container's contents to reflow.
I get this result in Safari 5+ OSX and Chrome 20+ OSX. Works as expected in Firefox 13.0 OSX.
UPDATE 2
Video of what I'm seeing:
http://f.cl.ly/items/1R1n2s0U3I3c1M3s2K0T/lundstrom_float_issue.mov
I was able to recreate your issue just as you said. It seems that it is an issue with webkit redrawing or measuring the elements after an animation or transition.
This isn't the best solution by any means, but for the time being at least it will work and hopefully what I found will help other people to be able to find out more.
If you add an onComplete to the animation, and trigger the .project mouseleave, it looks to work fine:
function completeAnimate(){
$('.project').trigger('mouseleave');
}
function contract(){
// PROJECTS CONTRACT RIGHT
TweenLite.to($('#projects-container'), .5, {css:{left:"300px", opacity:".5"}, ease:Expo.easeInOut, onComplete: completeAnimate});
}
So here is my jsfiddle which has a few tests and other animation tests so that you can see some of what I tried.
jQuery animate() and css keyframe animations have the same result as the Tween code you are using, HOWEVER, a straight style update works fine.
$('#projects-container').css('left','300px');
No issues with that at all, but of course, no animation either.
Some other things I noticed was that if you take out the .project event bindings, it still doesn't redraw correctly, however if you move you mouse it still doesn't. It simply stays that way.
I also tried forcing an element redraw using a few tricks you can usually use to force a redraw. I tried this oncomplete and at intervals after the animation begins, but had no luck with any of it.
You can also combine the two tweens into one with the properties on both, just an FYI.
Hopefully this will help someone find the true issue that's going on with the webkit transitions.

Categories

Resources