banner



Can You Move Grid Elements With Animations

Smoothly calculation, removing, resizing and reordering elements

A mutual misconception in Web Development is that the DOM is slow. The DOM, short for Document Object Model, is the construction of the Web Site which your code interacts with. If you were to enquire me whether the DOM is slow I would reply that, like nearly things in computer scientific discipline, it depends on the circumstances.

What makes changing the DOM ho-hum is once you have changed an element the browser has to mensurate the new size of each element, then has to redraw all of the elements that changed. This is always moderately expensive but mod browsers are smart about caching these calculations, invalidating as little of that cache as possible once a modify is made and only doing the calculations at the last possible moment. And so if yous make a modify to the page the browser won't mensurate the new sizes until yous request for information technology to measure them or it has to redraw the page for the next frame. If nothing has changed and then it does not need to remeasure, it can use the buried values.

In real terms what this ways is that when you have to change lots of the DOM'south layout in one go, yous tin can cheaply measure the size of elements if you measure out them all together, and you can cheaply make changes if yous do all your DOM changes together. Interleaving reads and writes is when the expense can become out of manus.

Therefore when doing large many element animations where performance is important information technology'due south important to accept all your measurements in one go earlier you start making changes. That is the secret sauce behind efficiently animative changes made to the DOM.

NB: Please call back it's important to respect user preferences for reduced motions, for some users lots of animation can make a site unusable and brand them sick. So always be prepared to plough it off similar using the case below.

          const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;          if (prefersReducedMotion !== truthful) {
// practice animation
}

The rest of this article is about building the blitheness for when the DOM changes. We will do it using the following method:

  1. Measure the position of all the things that will move. (reads)
  2. Perform all of your DOM changes (writes)
  3. Measure the new position of everything (reads)
  4. Apply inexpensive composite furnishings, such as transform , opacity or clip-path to place elements back at their previous size position.
  5. Create an animation which smoothly animates from the starting point back to the endpoint. The end bespeak in this case is what is already in the DOM.

In this the DOM needs to be recalculated at most twice, once before we take the first measurements and in one case after we accept made our changes and we demand to measure out how things accept inverse.

Before we cover this in depth, here is a folio where I exam this technique in different scenarios:

A gif of the demo.

We use the same technique for calculation elements and irresolute between different layout modes in each of the demos in the example page.

Measure all the things

Get-go, we need to know the original position of the elements that will alter. We are going to add an chemical element into parent so we will measure the position of all it'southward children.

          // Turn an assortment of elements into a map of elements to their
// respective bounding box
const boundingBoxMap = new Map(
Array.from(parent.children).map(
el => [ el, el.getBoundingClientRect() ]
)
);
// boundingBoxMap.get(parent.firstElementChild);
// DOMRect { ten: 8, y: 21.4, width: 606, height: 38, top: 21.4, right: 614, bottom: 59.iv, left: viii }

At present we can make whatever changes nosotros like, we tin can add together, remove and reorder elements. Change classes and styles.

Nosotros and then mensurate everything again using the same method as above.We now know the start and stop points of the animation.

The trick is to then make a new blitheness that starts at the old point, and animates to the new bespeak. We tin do this using some math.

To get how the position has inverse we will subtract the starting time position from the end position. This is the transform makes the element appear to exist back where it came from:

                      const            translateTransform = `interpret(${oldPos.x - newPos.10}px, ${oldPos.y - newPos.y}px)`;        

Animating size is a little trickier, we could scale the chemical element or nosotros could clip the chemical element, both are fast to do. Scaling it will look good on images, equally they often stretch to fill. For text the individual lines don't get larger or smaller so clipping will look better on text every bit information technology will maintain the text size.

When scaling size the math is a lot easier to do if you exercise all of the transformations from the peak left corner.

Either Calibration

(Make certain the transform origin is set to 0,0)

                      const            scaleTransform = `calibration(${oldPos.width/newPos.width},${oldPos.height/newPos.height})`;        

or Clip-Path:

                      const            heightDiff = (newPos.pinnacle - oldPos.elevation);
const widthDiff = (newPos.width - oldPos.width);
const clipPath = `inset(0px ${widthDiff}px ${heightDiff}px 0px)`;

Examples of the animation change betwixt scaling and clipping. Scale on elevation, clipping below.

Nosotros can then breathing these using the Web Blitheness API. Don't animate both scale and clip path just pick one to use.

This blitheness will animate it from the starting size & position we worked out to the final position and size. The final position and size is just a no-op since it needs to end up where it came from.

          el.breathing({
transformOrigin: ['0 0','0 0'],
transform: [
`${translateTransform} ${scaleTransform}`,
'scale(1)'
],
clipPath: [clipPath, 'inset(0px 0px 0px 0px)']
}, {
easing: 'ease-out',
duration: 500
});

Handling new Elements

Whatsoever elements which are new won't accept a starting position, so you should find a mode to animate them in nicely. For my demos I waited until the position/scale animation finished then I faded them in:

          el.animate({
opacity: ['0', '1']
}, {
easing: 'ease-out',
duration: 500,
delay: 500,
fill: 'backwards'
});

Tips

  • If the parent chemical element is likely to modify size do the same matter for its parent every bit well and so all information technology's siblings get animated appropriately.
  • If you are animating all of an element'due south children don't animate that element besides. It looks weird.
  • Clipping works best for text, scaling for images.
  • Salve your animations for user interactions, as that is when the user is likely to wait it.
  • Don't over-utilize animations they should be petty moments of joy otherwise they will go dull.

Using our library yourself

Since information technology's a pretty general case nosotros have made the library in the demo available on npm. It's pretty bare-bones and then if you need more features so please feel free to take inspiration from it to write your own or to fork it equally you lot need.

Source: https://medium.com/samsung-internet-dev/animating-dom-changes-33b031927e96

Posted by: herronoverniseents1972.blogspot.com

0 Response to "Can You Move Grid Elements With Animations"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel