iosswiftcgaffinetransform

How rotate a needle in semicircle?


This is What I want 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


Solution

  • 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.