I have noticed that when angular updates a page by adding a lot of elements even CSS animations stop running. I created a stackblitz here https://stackblitz.com/edit/angular-fefvpa to highlight the issue. When you hit the "Add Elements" button, the red square stops moving for about half a second. What can I do to circumvent that?
One solution i can think of that might help you is to use transform: translateX in the animation instead of left.
your anim would look like
#keyframes mymove {
from {transform: translateX(0)}
to {transform: translateX(400px)}
}
You can also add transform:translateZ(0) to the #box itself
The animation will use less ' GPU ' and by adding transform:translateZ(0) you will also make the browser use more GPU for that animation. So it might run smoother.
I tested it on my pc and it doesn't ' freeze ' anymore when adding items.
You can't really avoid that.
You're appending a thousand children, which is a rather important process.
This kind of operation should be done in small chunks, something like this.
Javascript is a monothread script language, which means most of the operations are blocking. When you do them one by one, then sure, it's pretty. But when you run a thousand operations at the same time (well, one after the other without any break), you face this kind of issues. Especially with DOM manipulation.
Related
Are there any in-browser optimizations for off-screen infinitely-running CSS animations (infinite animations which are applied to Elements that are present/displayed within the Document, just not in-view at a certain time)?
For the sake of a more straight-forward discussion, I will refer to CSS animations that involve only composition: using only transforms and/or opacity.
If we have a CSS animation, that has animation-timing-function: infinite;, how is it handled if the animated element is not actually on the screen / in-view?
There are some known scenarios regarding animations, which are irrelevant to this use case:
The animation will pause if the browser tab is pushed into the background. MDN
The animation is ignored if the element is removed from the Document, with something like display: none; (can't find a quotable source atm);
If the element is simply 'beyond the scroll', and the user can reach it at anytime, during the time the element is off-screen :
Does the animation run as normal, and has the same consumption, regardless if the element is visible or not?
Does it run as normal, but because it is not painted, the process itself becomes less expensive? - would make more sense.
Is the animation paused entirely? - would assume not, as the browser must know what the 'current progress' would have been at the moment the element needs to be painted again.
Or are there any other in-browser processes which optimize this, when these conditions are met?
Any documented answer, or any redirect to some resource, which could shed some light on the matter would be greatly appreciated.
This discussion would be relevant in determining if : manually removing infinite animations (for elements that are off-screen) would be a thing to consider, to achieve better performance.
TLDR
As long as the properties we want to animate do not trigger reflow/repaint, the animation can be optimized by the browser, which means better performance.
See off main thread animation.
So I'm working on this app in electron, and I noticed when I move the app over to my second monitor it seems to lag. Curious what might be causing this- I opened up the dev console, and sure enough- my animations drop from a very comfortable 100-150 fps, to a consistent sub 50 fps. The animation is a height transition, which is poorly handled by the browser, but even this doesn't explain the massive performance drop I see by simply dragging the window over to my second monitor.
I'm considering rethinking the way I handle the animation, to mimic the current look of it using only transforms, but it would be nice to know what's causing the stuttering and lag, since the lag doesn't appear to be specific to my height transition. After digging around for a bit in search of an answer, I'm no closer to anything that might be called a solution. I'm not posting any code with this because none of the animations are handled with JS. It just plain and simple CSS- nothing crazy about it.
To me this seems like it more of an underlying issue with electron itself, or perhaps something strange the OS does.
I wish to implement flow indicators on the links of my D3 graph, as in this block.
The block uses stroke-dashoffset keyframe CSS animation to achieve the flow, and while it looks good, CPU usage sits at almost 100.
I read that you can trick some browsers into triggering GPU acceleration by including certain CSS properties, but other sources indicated that this no longer works, and certainly I couldn't see any benefit when trying to add transform: translateZ(0); (for example).
I have been investigating other options, and I tried to implement a moving marker along a line, in this style. For only one marker performance is better, but when I added multiple performance was worse.
Is there another, more performant option for animating a marker down an SVG path?
Failing another approach, I will try adding controls to stop / start the animation, but that would be a last resort.
Thanks in advance!
It seems indeed that animating the stroke-dashoffset attribute causes a lot of calculations. The original example causes a CPU usage at around 50% when I open it in Firefox.
There's another approach that seems to give better results: manually increment the stroke-dashoffset and loop that using setInterval. Here's a proof of concept:
http://bl.ocks.org/kmandov/raw/a87de2dd49a21be9f95c/
Here's how I update the dashoffset:
var lines = d3.selectAll('.flowline');
var offset = 1;
setInterval(function() {
lines.style('stroke-dashoffset', offset);
offset += 1;
}, 50);
I know that it doesn't look very good but it (surprisingly) performs a lot better than relying on css animations or transitions. In Firefox I now get CPU usage at about 15%.
I can imagine that this approach won't perform very well if you have a lot of links, because the update will take too long. But maybe it's a viable hack for simpler use cases where you animate linearly a fixed amount of links.
I want to compose two separate CSS keyframe animations to make an image vibrate and rotate (see http://jsfiddle.net/3zAeZ/). The problem I believe I'm running into is: I'm setting the transform attribute in both keyframe rules, therefore one rule is clobbering the other.
I know this works using top & left instead of translate, but the keyframes rule will be much easier to reuse in the future if I do a transform (for example, in case I ever need to position the image differently).
I'm stumped. Can I do this? Is there a better way I should be doing it?
You can use multiple transforms like
transform: rotate(1337deg) scale(1.5) translate(6em, 300px);
Now I realize that you need two different animation durations as well.
So the best I can come up with is using two elements http://jsfiddle.net/3zAeZ/1/
I am building an iOS Safari touch-based app and find CSS transitions and transforms work great.
But I have two things I can't seem to achieve using just JavaScript and CSS.
Usually I want the element to translate with a duration of 0.2s. But in code I occasionally want to instantly translate (initial positioning). If I update the duration to 0 or remove the transition style entirely, it doesn't seem to have an effect (acts as if the 0.2s is immutable)
When zooming I want to update the transform-origin property. This also does not seem to work, and seems stuck at my original stylesheet-set value. Specifically I am trying to do this on the gesturestart and gestureend events
Hopefully there is an approach to making this work. Maybe setTimeout async processing?
Update:
I have a js fiddle example to better illustrate my problem in #1, and it turns out that setTimeout fixes it, but it's a strange solution that I'd be interested in improving:
http://jsfiddle.net/w9E7t/
It seems like I'm unable to do these steps synchronously:
set appropriate classes for an instant transition
apply transition style
reset classes to their default (with transition) state
You can accomplish this by using two CSS classes, one which sets the timing-duration to 0s and the other which sets it to 200ms and then applying the classes programmatically in JS. Take a look at this JSFiddle for an example.
One of Web development's best practices is to separate your document's parts into structure/content (HTML), presentation (CSS), and interaction/behavior (JS). In the example above, the presentation of the content (a timed translation) stays defined in CSS while JS is used only to respond to an interaction (a MouseClick event).
You should be able to change an element's transform-origin using the WebkitTransformOrigin style property in JS. Here is an example JSFiddle. I tested this on my iPhone4 and it correctly logged the new transform-origins in the console. Again, this can also be achieved by using JS only to listen for the gesture events and updating the element's class, while keeping the style rules of the class defined in your presentation logic (CSS).
Note well: In my examples, I am updating the element's .className. Since it is possible that your elements already have many classes, you may need to implement addClass/removeClass functions to properly set the correct classes, several examples of which can found on the Web.
Update:
Sorry for the delay... There are two ways you can approach this problem and the first you have already discovered.
Another way to handle switching back the class name is to use the webkitTransitionEnd property. This fires whenever a transition on the element finishes. It would look like this:
document.getElementById('puck').addEventListener('webkitTransitionEnd', function() {
puck
.removeClass('without_transition')
.addClass('with_transition')
}, false);
Unfortunately, when the transition-duration property is set to 0, this event is not fired :( I'm not sure if that is by design or a bug, but that's just how it's currently implemented (though I'm guessing it's by design since at this point the browser is not really doing a transition but rather just applying the transformation). The workaround in this approach is to set the transition-duration to 1ms (which will essentially look instant).
While the setTimeout approach looks hackish, many mobile framework groups use it throughout their code since the function will fire after the transition that occurs from switching classes (similar to transitionEnd). Take a look at Sencha Touch and you will find it numerous times.
I've forked your JSfiddle to show my example here.