Sliders as Knobs
You’ve seen other apps rotate views, but you may have no idea how to do it yourself. Let me show you one way to rotate views. We’ll make a simple knob control you might be able to use in your apps. Download the example file. On the storyboard, I added an
UIImageView of a knob and a label.
ViewController.swift, I set this up to use touch methods for user interaction. Check my earlier tip on touch and the apple pencil on how to use these methods.
You do translations like rotations using the layer property of
layer is a
CALayer, and that has a property
transform. In the
touchesMoved method inside the braces, assign the
transform property of the layer:
There’s a couple of ways to do a transform, but I prefer using the 3d ones over others. Add the
CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: , z: CGFloat)
knob.layer.transform = CATransform3DMakeRotation(angle: CGFloat, x: CGFloat, y: , z: CGFloat)
It has four parameters. The first is the,
angle and I’ll put a variable named
angle there for the moment, and come back to it. Next, I have
z, which is the axes I’ll rotate through. To avoid a semester of Linear Algebra, I’ll keep this simple. If these values are zero you don’t rotate on that axis. If one, you rotate.
If you use the x-axis, which is a horizontal line on the device you’ll flip the knob. The vertical line is the y-axis, which also flips the knob. To rotate in the same plane you want the line extending toward the user, the z-Axis.
I’ll set the axis to z rotation on and keep x and y off.
CATransform3DMakeRotation(angle, 0, 0, 1)
Now back to
angle. Like most places in iOS, it is in radians. While most like to think in degrees, there’s a good reason for it to be radians: we can describe all points in the rotation as a number between zero and 2 times pi. Since I can multiply the pi in at the last minute, I can think of numbers only in a range of zero to two, which actually makes using the math a lot easier than 360.
Add a line above to set the angle.
let angle = theta * CGFloat.pi
theta as the constant I’ll multiply to pi.
To get a number to use for theta, I’ll use the x position of a touch on the device.
let currentPoint = touch.location(in: view)
To get this to a value between 2 and zero, I’ll divide this by the width of the view, then multiply that by two
let theta = 2.0 * currentPoint.x / view.frame.width
I’ll also print it to the label
label.text = String(format:"%02.3f pi",theta)
I’ll run this on an iPhone 8 simulator, which seems to handle animation better than an iPhone X. Dragging my mouse over the simulator which simulates touch makes the knob move. You’ll see that higher values rotate clockwise, lower ones counterclockwise.
I can also limit the angle by reducing the multiplier from 2 to some smaller number, say 1.5 for a three-quarter turn.
let theta = 1.5 * currentPoint.x / view.frame.width
I can also add a rotation offset. I’ll limit the knob counterclockwise 90 degrees which is subtracting 0.5
let angle = (theta - 0.5) * CGFloat.pi
Build and run. You get a 3/4 turn of the knob limited in different places. Since touch is not completely accurate even on the sides, you might not get a maximum value.
There’s more you can do with this, but this gives you a few ways to explore with rotating views.