0
votes

I've been playing around with 3D transformations for parallax scrolling effects and I'm trying to understand how to do plane to plane projections. I've searched around but the matrix math involved is a bit hard to grasp without clear examples.

Given a layout with multiple panels, I would like to get the transformation matrix to move each panel onto a new arbitrary plane while maintaining the original un-transformed perspective.

To illustrate this problem, here is a plunker that performs Z transformations on 3 different divs along with scaling and translating to achieve the plane projection. I have them appear to align at a specific scroll point as if there was no transformation using scale and X,Y translations.

transform: translateZ(60px) scale(0.4) translateX(-270px) translateY(258px);

https://plnkr.co/edit/UddWeLAWTQgkcpYMRP9q

I have achieved this example with trial and error doing manual scale, translateX and translateY to shift the div back after the translateZ pulls it out of place. However I would like to understand the better way to calculate the transformation matrix since my divs are not a fixed size which changes the values required.

1

1 Answers

1
votes

I ended up using information in this article to help find my solution, which involves triangle math instead of using a full transformation matrix.

Here's a plunker showing the solution in action:

https://plnkr.co/edit/W5GTbViN0O8gnkCmxV5W?p=preview

function translateLayer( obj, y, newZ )
{
    var containerWidth = jQuery('.parallax').width();
    var x = ( obj.position().left 
              + parseInt(obj.css('marginLeft'), 10)
            ) - (containerWidth/2);
    var z = 100;

    var n = z - newZ;
    var scale = 1 - (newZ / z);
    var newX = (n / z) * x;
    var newY = (n / z) * y;
    var transX = 0 - (x - newX);
    var transY = (y - newY);

    obj.css( {
      'transform-origin': '0% 0%', 
      'transform': 'translate3d('+transX+'px, '+transY+'px, '+newZ+'px) 
                    scale('+scale+')'
    } );
}

obj is the jQuery object to be translated.

y is the vertical distance from your chosen center origin to the top left corner, positive values move up the axis and negative values down. Since browser coordinate systems use an origin at the top left some calculations are required to get this value. It is up to you to choose where your origin will be, however this solution assumes that it is horizontally centered. When the scroll reaches your chosen origin point the layers will sync to the original layout position. In the example below I chose an origin at the very center of the 3-block layout.

newZ is the new depth value desired for the object. Positive values move it closer to the viewer, negative values away. In this function I have hard-coded the maximum z value as 100, which also must be defined in a parent element's css using perspective: perspective: 100px