Chapters

Hide chapters

iOS Animations by Tutorials

Seventh Edition · iOS 15 · Swift 5.5 · Xcode 13

Section IV: Layer Animations

Section 4: 9 chapters
Show chapters Hide chapters

26. Simple 3D Animations
Written by Marin Todorov

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

In this chapter you’ll get to try out your newfound knowledge about camera distance and perspective.

Once you set up your layer’s perspective, you can work on the layer’s transform as you usually would; but now you can rotate, translate and scale your layer in three dimensions.

The project for this chapter features a folding pull-out menu as popularized in many apps, such as Taasky:

Office Buddy is an office helper app for employees to access categorized information about day-to-day company life.

The starter project already has all the code to make the menu functional, but it only works in 2D. Your task is to bring the menu into the third dimension and give it life!

Creating 3D Transformations

Open the starter project for this chapter and build and run it to see what the initial version of the Office Buddy app looks like:

Tap the menu button to reveal the side menu; alternatively, you can swipe right to reveal the side menu.

As you can see, this app is as flat as they come. But armed with your new insight on 3D perspective, you’re going to add some depth to the menu.

Open ContainerViewController.swift; this controller displays both the menu view controller and the content view controller on the screen. It also handles pan gestures so the user can open and close the menu.

Your first task is to build a class method that creates the corresponding 3D transform for a given percentage of “openness” of the side menu.

Add the following method declaration to ContainerViewController.swift:

func menuTransform(percent: CGFloat) -> CATransform3D {

}

The above method accepts a single parameter of the current progress of the menu, which was calculated by the code in handleGesture(_:), and returns an instance of CATransform3D. You’re going to assign the result of this method directly to the menu layer’s transform property.

Add the following code to your new method:

var identity = CATransform3DIdentity
identity.m34 = -1.0 / 1000

This code might look a bit surprising; so far you’ve only used functions to create or modify transforms. This time, however, you’re modifying one of the class’ properties.

Note: Why is this property called m34? View and layer transforms are expressed as two-dimensional math matrices. In the case of a layer transform matrix, the element in the 3rd row at the 4th column sets your z-axis perspective. You can set this element directly to apply the desired perspective transform.

So you create a new CATransform3D struct and you set its m34 property to -1.0/1000… why would you choose that value?

Okay, I’ll back up a little. To enable 3D transforms on a layer you need to set m34 to -1.0 / [camera distance]. Since you read through the introduction for this section (you did read it, right?), you have some understanding of how the camera distance affects the scene perspective.

But why are you using 1000 for the camera distance? The distance is expressed in points between the camera and the front of the scene. As to what value to use, the truth is that you need to try different values and see what looks good for your particular animation.

Working with Camera Distance

For UI elements in an average app you can consult the following reference for some guidelines on an appropriate camera distance:

let remainingPercent = 1.0 - percent
let angle = remainingPercent * .pi * -0.5
let rotationTransform = CATransform3DRotate(
  identity, angle, 0.0, 1.0, 0.0)

let translationTransform = CATransform3DMakeTranslation(
    menuWidth * percent, 0, 0)
return CATransform3DConcat(
  rotationTransform, translationTransform)
menuViewController.view.frame.origin.x =
  menuWidth * CGFloat(percent) - menuWidth
menuViewController.view.layer.transform =
  menuTransform(percent: percent)

Moving the Layer’s Anchor Point

By default, the anchor point of a layer has an x coordinate of 0.5, meaning it is in the center. You need to set the x of the anchor point to 1.0 to make the menu rotate around its right edge like a hinge, as shown below:

menuViewController.view.frame = CGRect(
  x: -menuWidth, y: 0, 
  width: menuWidth, height: view.frame.height)
menuViewController.view.layer.anchorPoint.x = 1.0

Creating Perspective Through Shading

Shading lends a lot of realism to 3D animations; to that end, you will rotate the menu out of the “shadow” of the left side of the content view controller.

menuViewController.view.alpha = CGFloat(max(0.2, percent))

setMenu(toPercent: 0.0)

Rasterizing for Efficiency

There’s one last task to make your animation “perfect”. If you stare at the menu long enough while you pan back and forth you’ll notice the borders of the menu items look pixelated.

// Improve the look of the opening menu
menuViewController.view.layer.shouldRasterize = true
menuViewController.view.layer.rasterizationScale =
  UIScreen.main.scale

self.menuViewController.view.layer.shouldRasterize = false

Key Points

  • The .m34 value of a CATransform3D is important as it gives perspective to your 3D transforms.
  • The anchor point of a layer sets the point around which your transforms take place.

Challenges

Challenge 1: Create Your Own 3D Animation

For this challenge you are going to create a 3D rotation animation for the menu button. As the user pans the button will rotate alongside the menu view controller.

let centerVC = centerViewController.viewControllers.first as? CenterViewController

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now