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/
Related
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.
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.
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.
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.
I'm using jQuery .scrollTop to scroll image within a div. It works great in Firefox - scrolling is very smooth and fast. In IE 8 scrolling is very slow and glitchy - image scrolls once in about a second - two seconds. Image size is on average between 2000 * 2000 and 4000 * 4000 pixels.
Is there a way to improve this for IE 8?
Performance in IE 7 is slightly better, but still not good enough.
Thank you
Edit: I believe that an issue is in how scrolling is implemented in IE 7 and 8. I have enabled both scroll bars (overflow-x and overflow-y), and I have tried scrolling an image using these scroll bars. Issue is exactly the same. I've tried running this on a fairly underpowered PC - pentium dual core few years old with 2 GB of RAM as well as Core i7 desktop with 2.8GHz CPU 1600Mhz RAM and the results are nearly identical. FireFox scrolls a lot faster, however its CPU usage on average is 10% higher than IE CPU usage. This leaves me puzzled...surely Microsoft would have addressed this issue by now?
Another thing that I have found slightly odd is that scrolling ran faster on a Core 2 Duo laptop. I'm wondering whether this has anything to do with graphics card drivers...does IE 7/8 even make a use of GPU?
Excuse me if any of this sounds silly, but I'm really interested in solving this problem...IE can't be that bad..
jQuery's .scrollTop() is notoriously slow in ie, and if the markup is even slightly complex or large, you'll never get it to perform well.
The solution is to not use the jQuery .scrollTop() function, but build your own based on the native properties .scrollHeight and .scrollTop.
The reason is the way ie computes offsets, which is the base of jquery's .scrollTop() slowness - you have to walk up the DOM tree and calculate offsets for every parent in ie.
jQuery does this the best it can, but you will always be able to do it faster since you know the markup in advance and can optimize this - you can even do the offset calculations in advance most of the time and just use a constant as modifier.
All that said, this might not be jQuery's fault - it can simply be a problem with ie's rendering pipeline - depending on how you made your marklup and styling of it, a scroll might force ie to completely rerender/repaint the page for every pixel you scroll, and that will slow it all down to a crawl.