Jump to content
Search Community

"Combining Multi-Level Transformations into a Single Matrix: Efficient and Resource-Saving Approach?

themepunch test
Moderator Tag

Recommended Posts

Hi Guys,
 

I'm working on a feature that allows animating elements with multiple logical levels wrapped dynamically. Let's say we have 4 logical levels: "element, mask, loop, shift" which are wrapping each other logically like this: (shift ( loop ( mask ( element) ) ) ). Each level can set and animate x, y, z, rotationX, Y, Z, scaleX, Y, and skew X, Y.
 

Instead of creating complex DOM structures by wrapping elements within each other, I thought about using a ticker to combine different values into a matrix and apply the result on each tick to the "element" itself.
 

Here's a sample approach:
 

function createMatrix({ translate = { x: 0, y: 0, z: 0 }, rotate = { x: 0, y: 0, z: 0 }, scale = { x: 1, y: 1 }, skew = { x: 0, y: 0 }, origin = { x: 0, y: 0 }, perspective = 0 }) {
  const translationMatrix = new gsap.utils.Matrix3D().identity().appendTranslation(translate.x, translate.y, translate.z);
  const rotationXMatrix = new gsap.utils.Matrix3D().identity().appendRotation(rotate.x, 1, 0, 0);
  const rotationYMatrix = new gsap.utils.Matrix3D().identity().appendRotation(rotate.y, 0, 1, 0);
  const rotationZMatrix = new gsap.utils.Matrix3D().identity().appendRotation(rotate.z, 0, 0, 1);
  const scaleXMatrix = new gsap.utils.Matrix3D().identity().appendScale(scale.x, 1, 1);
  const scaleYMatrix = new gsap.utils.Matrix3D().identity().appendScale(1, scale.y, 1);
  const skewXMatrix = new gsap.utils.Matrix3D().identity().appendSkewX(skew.x);
  const skewYMatrix = new gsap.utils.Matrix3D().identity().appendSkewY(skew.y);

  // Transformation matrices for transform origin
  const originMatrix = new gsap.utils.Matrix3D().identity().appendTranslation(origin.x, origin.y, 0);
  const inverseOriginMatrix = new gsap.utils.Matrix3D().identity().appendTranslation(-origin.x, -origin.y, 0);

  // Transformation matrix for perspective
  const perspectiveMatrix = new gsap.utils.Matrix3D().identity().appendPerspective(perspective);

  // Multiply the matrices to get the combined transformation matrix
  const combinedMatrix = perspectiveMatrix.clone()
    .multiply(originMatrix)
    .multiply(rotationXMatrix)
    .multiply(rotationYMatrix)
    .multiply(rotationZMatrix)
    .multiply(scaleXMatrix)
    .multiply(scaleYMatrix)
    .multiply(skewXMatrix)
    .multiply(skewYMatrix)
    .multiply(translationMatrix)
    .multiply(inverseOriginMatrix);

  return combinedMatrix;
}

 

Before diving deep into this project, I wanted to get your thoughts and opinions. I will have dynamically created layers with parallel animations, ranging from 10 to 200 layers, based on the setup our clients build with the editor.

 

Do you think this is the right way to go for smoother, quicker rendering and efficient resource usage? Or would you recommend using wrapped containers and rendering each DOM container separately?

 

I'd appreciate any input and ideas on this!

 

Thanks a lot, and cheers from Cologne!

 

Link to comment
Share on other sites

I think it’s certainly worth testing. 4 matrices all multiplying on each tick for each element…I’m genuinely not sure that’ll be any more performant than the element wrapping but it very well might be. You may want to implement some caching of multiplied values and flag things as “dirty” when changed so that you’re limiting the multiplication to only stuff that needs it. Also, I certainly wouldn’t do all that stuff in a ticker that runs constantly (even when nothing is changing). Seems more appropriate to do in something like an onUpdate. Or you could still do checks in a ticker, but have a way of very quickly skipping things when there were no changes made since the last tick. 

 

Test, test, test. 

 

Good luck!

  • Like 1
Link to comment
Share on other sites

Hi Jack,


Thank you for your valuable insights and suggestions ! 


Caching multiplied values and flagging "dirty" properties is indeed the way i wanted to try. Using onUpdate instead of a constantly running  ticker seems to be a good idea.  Will keep you updated about my  progress. Maybe it is interesting for someone else also.

Wish you all the best ! Cheers ! Krisztian 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...