I want to rotate a needle when user input weight. The low value and high value is dynamically changed by user's height.
pointer.transform = CGAffineTransform(rotationAngle: CGFloat(weight / low * .pi / 3))
This code is working at under low side. But I don't know how to point low ~ high , over high
What you want to do is to convert weight
to a value between 0
and 1
to get a "progress" value. You can do this by using an inverseLerp
function, it would look something like this:
let progress = (weight - low) / (high - low)
This formula will return 0 when weight == low
and 1 when weight == high
.
Now you have to convert that into a rotation. Assuming that the image of your arrow is pointing up by default, we'll need to rotate in a range of [-pi / 2, pi / 2]
. pi
is half a rotation, so we're doing a quarter of a rotation to the left, and a quarter to the right.
A lerp
function turns a value in the range [0, 1]
, like the one we already have, into a value inside a range, which is just what we need. It looks like this:
let value = (1 - progress) * start + progress * end
Using actual values, it would look like this:
let angle = (1 - progress) * (-.pi / 2) + progress * (.pi / 2)
We now use that to transform our arrow view:
pointer.transform = CGAffineTransform(rotationAngle: angle)
Views will rotate by the center by default, because this is where their `anchorPoint is located by default. Since we want our view to rotate around the bottom middle of its frame, we can change it like this:
pointer.layer.anchorPoint = CGPoint(0.5, 1)
This should rotate our view like we want it to.
PS: I made a library called CGMath
that includes functions like this. You can check it out here.