CATransform3D - understanding the transform values

2019-06-05 17:29发布

问题:

The picture shows a simple UIView after applying the following transform:

- (CATransform3D) transformForOpenedMenu
{
  CATransform3D transform = CATransform3DIdentity;
  transform.m34 = -1.0 /450;
  transform = CATransform3DRotate(transform, D2R(40), 0, 1, 0);
  transform = CATransform3DTranslate(transform, 210, 150, -500);
  return transform;
}

I'm trying to make the distances highlighted with black to have equal length. Could you please help me understand the logic behind the values and calculations?

Cheers

UPD Sept 13

Looks like removing 3DTranslate keeps distances equal. I see I can use layer's frame property to reposition rotated view to the bottom left of the screen. Not yet sure, but this might actually work.

回答1:

The .m34 value you are setting is best set on the sublayerTransform of the containing view rather than the view you are transforming.

I don't fully understand the maths behind affine transforms so I made this project which allows me to play around with the transform values to achieve the effect I want. You can plug in the values from your code above and see what it looks like, though note that there is already a perspective value applied using the sublayerTransform property mentioned above.

For your specific case, I think you want to adjust the anchor point of the layer to (0.0,0.5) and apply the rotation transform only. This assumes you want the menu to swing back like a door, with the hinges on the left edge.



回答2:

The problem you're seeing is caused by your CATransform3DTranslate call. You're essentially setting the Y Axis off center, and hence seeing a different perspective view of the frame.

Think of it this way;

You're standing in the center of a long narrow field stretching off into the horizon. The edge of the field appears as if it is converges to a center point somewhere off in the distance. The angle of each edge to the converging point will appear equal if you are at the center of the field. If, on the other hand, you move either to the left or the right, the angles change and one will seem greater than the other (inversely opposite of course).

This is essentially what is happening with your view; As your converging points are to the right, changing the Y axis away from 0 will have the same effect as moving to the left or right in my example above. You're no longer looking at the parallel lines from the center.

so in your code above Setting the ty in CATransform3DTranslate to 0 Should fix your problem I.E.

   transform = CATransform3DTranslate(transform, 210, 0, -500);

You may also need to alter the tz and tx Value to make it fit.



回答3:

OK, so what eventually solved my question is this:

  • 3D transform on Y axis to swing the view like a door transform = CATransform3DRotate(transform, D2R(40), 0, 1, 0);
  • set Z anchor point on a layer, to move it back targetView.layer.anchorPointZ = 850;
  • adjust layer position so that the view is located slightly to the bottom left of the parent view:

    newPosition.x += 135 * positionDirection; newPosition.y += 70 * positionDirection;

This sequence adjusts position without CATransform3DTranslate and keeps the 'swinged' effect not distorted.

Thanks everybody!