Raphael SVG animations choppy in some browsers - javascript

I have an SVG object that I am adding to my page using Raphael. With roughly 175 paths in 6 sets I suspect it counts as complex.
I am animating each of the 6 sets using the .animate function
function anim(direction, duration){
return Raphael.animation({transform: "r"+direction+"360 250 250"}, duration).repeat("Infinity");
}
IG.sets.white_outer.animate(anim("",100000)); // 2 paths
IG.sets.grey_outer.animate(anim("-",100000)); // 25 paths
IG.sets.grey_inner.animate(anim("",100000)); // 25 paths
$(window).load(function(){
IG.sets.BLUE.animate({transform: "r0 250 250"}, 4000, ">"); // 32 paths
IG.sets.RED.animate({transform: "r0 250 250"}, 3000, ">"); // 29 paths
IG.sets.GREEN.animate({transform: "r0 250 250"}, 2000, ">"); // 24 paths
}
the problem is that in some browsers, this is very choppy looking.
It's smooth as butter on Mac (tested: FF, Chrome, Safari). It's also lovely on Windows in Chrome, but when I load up windows FF, Safari or IE8 the animations are choppy and a bit stuttering.
It even looks great on a an iPad!
I'd love to be able to make them all look great... so I'm trying to figure out what's costing all the power in FF and Safari (and at the end of the day, hopefully whatever override I manage brings up a fix for IE8 as well).
From the other questions I've seen about choppy animation on Raphael, I see mention of "getting into the guts" to add a timeout to the animate function... (as seen in raphael-min.js)
cz= window.requestAnimationFrame||
window.webkitRequestAnimationFrame||
window.mozRequestAnimationFrame||
window.oRequestAnimationFrame||
window.msRequestAnimationFrame||
function(a){setTimeout(a,16)}, /* there is a function here that animates */
Though it looks like in FF for example RequestAnimationFrame gives a smoother performance than setTimeout. (I tested this by deleting the mozRequestAnimationFrame condition and reloading, tried various intervals for the timeout)
Is there something else I might be missing that might help improve the cross browser frame rates of my animations?
Note for example image is at its default 500x500 and the rotation is happening around the image center (point 250x250) however the Image is being displayed on page at 1000x1000 (with viewport doing the scaling at page load.
Is it possible that if I have the designer resize the image to a 1000x1000 canvas and I display at full size from the start that I'll have a boost? Maybe a "smoother ride"? I'm not sure what factors effect SVG animation and performance.

You should look into Element.animateWith (http://raphaeljs.com/reference.html#Element.animateWith). It has a feature that lets you sync one animation with another animation so that everything is updated in lock step. The choppiness can't helped if the browser or device is slow, but syncing animations should make it look better.

Related

How to tell the browser to do the javascript manipulated webpage scaling before any content starts to show up?

I am building a website for me and I care about performance, speed, user experience and a lot more. When I started I didn't know much and I made an initial design using adobe xd. Then using webexport plugin I got a html file that has 2k+ lines of codes for scale to fit any screen and proportional resize of everything. I think I made a 1080p standard artboard but somehow it was way too big like 3554px by 2216px. So the webpage is now that big and scaling is running on it. I don't think it's too big for a browser to handle. Things were good before chrome 97 or 96 update. After that chrome and any browser running on chromium just can't scale my webpage fast enough to fit the screen. I see big divs getting smaller and it takes kinda like 500 ms to settle with decent setup. A lot of variables can affect the performance like if the machine(pc) and network is slow the scaling takes couple of seconds which is too much.
Is there any way to hint the browser to do the scaling first then make the page visible? The older version of chrome was doing it right. I can make the page visible after 600 ms using setTimeout function but doesn't seem what I want.
CSS
will-change: transform;
Tried this but it has bad effect like blurry text on my content. I don't know why it's pushing the browser to it's limit sometimes, maybe I can better optimize my page but these browsers should be more powerful (safari is the worst - can even render the webpage)
This is the home page
https://elomymelo.com/
You should see big page fitting inside the screen and it'll probable take 200 ms pretty fast
proportional resize on window also works
This is a heavy article page
https://elomymelo.com/oneplus%20nord%20review.html
I tried to hide the scaling effect in this page but not satisfied because browsers mess up sometimes. I need the javascript scaling done much faster like visitors will not see that weird transition.

NW/Node Webkit - Image decodes even if it is already visible

I am currently working on a JavaScript(pure js) based game. The game contains 5 large sprite sheets(e.g. 2861 × 768 and 4096 × 4864). When the game starts, all 5 sprite sheets are preloaded to canvas elements. Three of those 5 sprites represent together one animation, where each sprite contains 75 frames. When one sprite ends with its animation, I hide it and display the next sprite. When the second sprite finishes animating, I hide it and display the third/last one.
When the second or third sprite is about to be displayed, a small delay of 0.5 s - 1 s happens. The image is being decoded.
It is not something that happens just the first time, it is something that happens always. And that animation repeats every 5 minutes, and the small delay happens always.
The reason why I'm using canvas elements for preloading is that I thought WebKit would just throw away decoded images for some time being unused and that the canvas element would prevent WebKit from deleting it from memory. But that does not work.
I've tried almost every optimization I'm aware of. I have even refactored all my CSS by removing descendant selectors etc.
The renderer I'm using to draw those animations is built by myself and it is working perfect, so that could not be the problem, since it is working very well in Firefox.
EDIT [2016/03/04]:
I made a mode with canvas and the result is even worse. It laggs a lot. And the delay remains the same. Only in NW, the problem does not persist in Chrome neither in Firefox.
Canvas mode - Lags:
Default(HTML) mode - Works perfect:
Codepen: My renderer http://codepen.io/anon/pen/JXPWXX
Note: If i hide those other elements with opacity:0.2 rather than opacity:0, the problem does not happen. But, I can not hide them like that since they remain still visible. They shouldn't be visible. If I add opacity:0.01 it is not visible and the problem does not happen in Chrome, but still persists in NW.
In NW, when I swtich from opacity:0.2 to opacity:1, an image decode is being processed. The same thing does not happen in Chrome browser.
I am using the following version:
nw.js v0.12.3
io.js v1.2.0
Chromium 41.0.2272.76
commit hash: 591068b-b48a69e-27b6800-459755a-2bdc251-1764a45
The three image sprites are 14.4MB, 14.9MB and 15.5MB size. Each sprite contains 75 frames.
Why could this be happening and how can I prevent it?
Try to switch to google-chrome directly since the new nw version is probably released 19.04.2016. After that NW will hopefully keep up with every Chromium release.
You should not have the same problems in Chrome.
Given that keeping Webkit thinking the image is still displayed makes the problem disappear (as your opacity experiment shows), I'd move it nearly completely out of the visible area, with only a single transparent row overlapping with the viewport (using overflow hidden).
Note that an unpacked 4000x4000 sprite sheet will use 64 Megabytes of RAM (4 bytes (=RGBA) per pixel), so perhaps it might be better to make sure the next image gets "warmed up" a bit ahead of time, without keeping all of them unpacked all the time?
I'd recommend using idata = ctx.getImageData(0, 0, canvas.width, canvas.height) to retrieve the data array from the canvases, then ctx.putImageData(idata, 0, 0) to switch between sprites, rather than hiding the canvases.

KineticJS: animation performance in Firefox vs Chrome

I'm running an animation using Kineticjs using the Animation module. Now I noticed there quite a big performance difference between Chrome and Firefox. Looking at the framerate I found the following results.
Chrome Firefox
avg: 50 50
min: 33 20
max: 56 75
As you can see, the variability of the framerate for FireFox is a lot bigger. The animation in Chrome is smooth (at least smooth enough), but the animation in Firefox is choppy every second or so, this happens when the framerate is very high or low.
Especially the high framerate spikes seem to ruin the appearance of a smooth animation.
Has anybody else experienced this behaviour? And is there a way to smooth the framerate out a bit more in Firefox?
This could be due to browser tab architecture differences, such as the fact that currently Google Chrome uses a separate process for each tab, so slow or bad code in one tab is far less able to affect code in another tab. With Firefox tabs are run in the same process, so slow code on one tab can affect other tabs.
This could also be due to browser performance differences, meaning the implementation of DOM and Javascript APIs that you are using.
is there a way to smooth the framerate out a bit more in Firefox?
You should try to find some causes for the difference in the framerate, process of elimination is probably the best path.
Try using the browsers with only one tab, and go through the list of apis used to see if there are performance differences for those.

Reading Chrome Frame Rate results in DevTools

As far as I know the white (empty) bar represents idle time.
I know I should focus so that the application would run (at best) > 60fps and at least >30fps
This is my bar:
As you can see, I'm repainting on scroll ( changing the background position of an image ).
The middle line marks 60fps in this case, and if you pay attention closely, there is a top line (which is 30fps).
I've compared my results with others out there, and it seems that I have rather large idle times. Is that okay ? I know that paint, javascript and anything else is bad, but what purpose does displaying idle times serve ? Should I attempt to get rid of it, if so, what should I watch out for ?
Also, there is a spike every now and then because of "Image Decode", is there anything I can do about it ?
Image Decode
You can reduce the size of the image, which will make the decodes shorter. You can also trick the browser into doing these decodes earlier, perhaps at a time when there's no activity and therefore won't hurt your FPS.
I would also kill these big images temporarily to see if that moves you from 30fps to 60fps.
Scroll handler
You should minimize the amount of work you're doing in your scroll handler. At most you should be grabbing one scroll metric from the DOM and a timestamp perhaps. Then do your adjustments to style in a requestAnimationFrame loop: http://www.hesslerdesign.com/blog/javascript/optimizing-javascript-performance-handling-coordinate-updates/
Heavy paints
background-position isn't optimized well in WebKit or Blink, especially for this sort of usecase. I would put the image into a div and just slide its position using a transform: translate(x,y) (and promote it to its own layer if possible.) If sucessful, you won't repaint the entire screen on every scroll.
30 FPS Aint bad
A solid 30FPS actually looks better than something that's jumping between 60 and 45 all the time. Curious.. Are you in Canary or on a retina screen?
In general, you're doing pretty okay on your hardware, but I would try to reduce those image decodes. And you can go further with the above if you want.

smooth animation only in firefox 4

It seems that the following setup on jsfiddle only runs smooth in firefox 4.
http://jsfiddle.net/ynytc/39/
Im wondering why?
I thought maybe because of the hardware acceleration in firefox 4,
but without it still runs smooth.
So maybe someone knows why?
edit: compared to chrome,safari,ie8
You're animating over a 10 second period a change in size of only 20 pixels. That means that there's going to be only one integral dimension change every 1/2 second, which is exactly what I see in Chrome. The size of the image can't be set to fractions of a pixel (in all browsers). Firefox 4 seems to allow that, however; that's the only thing I can imagine anyway.
If you change your fiddle like this you'll see that Chrome is running the animation as fast as you could want it to, but the image only shifts when there's a whole integer change in the property value (width and height).
This is an interesting side effect that I hadn't encountered before.
It seems that other browsers can't apply subpixel scaling, so you only have 20 pixels to spread in 10 seconds, coming to a glorius 2 frames per second. The workaround for this would be to apply CSS transitions (if you don't need to support IE).
See example with CSS transitions here:
http://jsfiddle.net/nKfdB/

Categories

Resources