Animating multiple DIV elements with JS and DOM results in low frame rates

Introduction

I just started programming with javascript, and now I am working on this project of my hobby. It is assumed that the site will display pages filled with product images that can be "tinted" on the left or right. Each "page" containing about 24 medium-sized images on one page almost completely fills the entire screen. When the user chooses to view the next page, he needs to click on the left (for example) so that the new page (dynamically loaded via the AJAX script) slides into the view.

Problem

This requires my javascript to β€œslide” across two of these pages synchronously across the width of the screen. This results in a very low frame rate. Firefox and Opera are a little behind, Chrome is especially bad: 1 frame of animation takes approx. 100 milliseconds, which makes the animation very β€œlagged”.

I do not use jQuery and do not want to use it or any other library to "do my job." At least for now, I don’t know for sure that what I'm trying to do cannot be done with a couple lines of self-written code.

So far, I realized that a specific way to manipulate the DOM causes a performance hit. The procedure looks like this:

function slide() { this.t = new Date().getTime() - this.msBase; if( this.t > this.msDura ) { this.callB.call(this.ref,this.nFrames); return false; } //calculating the displacement of both elements this.pxProg = this.tRatio * this.t; this.eA.style.left = ( this.pxBaseA + this.pxProg ) + 'px'; this.eB.style.left = (this.pxBaseB + this.pxProg) + 'px'; if ( bRequestAnimationStatus ) requestAnimationFrame( slide.bind(this) ); else window.setTimeout( slide.bind(this), 16 ); this.nFrames++; } //starting an animation slide.call({ eA: theMiddlePage, eB: neighboorPage, callB: theCallback, msBase: new Date().getTime(), msDura: 400, tRatio: ((0-pxScreenWidth)/400), nFrames: 0, ref: myObject, pxBaseA: theMiddlePage.offsetLeft, pxBaseB: neighboorPage.offsetLeft }); 

Question

I noticed that when I let the AJAX script upload fewer images to each page, the animation becomes much faster. Separate images seem to create more overhead than I expected.

Is there any other way to do this?

+6
source share
1 answer

JAVASCRIPT SOLUTION

Well, there are two possibilities for you to try to speed it up.

First of all, when you change the style of an element, you force the browser to reset the page. This is called repainting. Some changes also lead to recalculation of page geometry. This is called reflow. Re-melting always causes a redraw immediately after it. I think, why you experience worse performance with a lot of elements, is that each update of each of them causes at least redrawing. What is usually recommended when modifying several styles in one element is to either do them all at once, adding or removing a class, or hiding an element, do your manipulations and then show it, which means only two copies (for example , and, possibly, recounts).

It seems that in this particular case, you are probably already doing a great job, as you process each element only once per iteration.

Secondly, requestAnimationFrame () is good for creating animations on a canvas element, but it seems to have some tricky performance for DOM elements. Open your page in the Chrome profiler to see exactly where it freezes. Try just using setTimeout () to make sure it is. Again, the profiler will tell you where the hangs are. requestAnimationFrame () should be better, but confirm it. I used to have unpleasant consequences.

REAL SOLUTION

Do not do this in JavaScript, if you can avoid it at all. Use CSS transitions and translation to animate using a JavaScript function registered as an onTransitionEnd event handler for each animated element. Providing the browser with this material is almost always faster from the start than any JS code anyone can write.

The only catch is that CSS3 animations are only supported by new browsers. For your own edification, do it like this. For real practical applications, delegate to the library. A good library will do this initially, if possible, and will return to a better way to do this in JS for older browsers.

A good read link regarding this material: http://www.html5rocks.com/en/tutorials/speed/html5/

+1
source

All Articles