Skip to content

Instantly share code, notes, and snippets.

@arronhunt
Created February 17, 2017 21:48
Show Gist options
  • Save arronhunt/805c18b2aef2076aafd56d9113d33d67 to your computer and use it in GitHub Desktop.
Save arronhunt/805c18b2aef2076aafd56d9113d33d67 to your computer and use it in GitHub Desktop.
Modulation function in Swift
// let value = Modulate(1, from: [0, 10], to: [0, 20], true);
// print(value);
// Returns 2
func Modulate(_ input: Float, from: [Float], to: [Float], limit: Bool) -> Float {
let result = to[0] + (((input - from[0]) / (from[1] - from[0])) * (to[1] - to[0]));
if (limit) {
if (to[0] < to[1]) {
if (result < to[0]) { return to[0] }
if (result > to[1]) { return to[1] }
}
else {
if (result > to[0]) { return to[0] }
if (result < to[1]) { return to[1] }
}
}
return result
}
@RayPS
Copy link

RayPS commented Jul 16, 2018

I noticed this is actually the same way how FramerJS does.
But this can be more simplified in Swift.
To deal with UIView animations like CGAffineTransform better use CGFloat instead.

extension CGFloat {
    func modulate(from: [CGFloat], to: [CGFloat], limit: Bool) -> CGFloat {
        let result = to[0] + (((self - from[0]) / (from[1] - from[0])) * (to[1] - to[0]))
        return limit ? [[result, to.min()!].max()!, to.max()!].min()! : result
    }
}



CGFloat(5.0).modulate(from: [0, 10], to: [0, 100], limit: true)       // 50
CGFloat(20.0).modulate(from: [0, 10], to: [0, 100], limit: true)      // 100
CGFloat(15.0).modulate(from: [10, 20], to: [20, 40], limit: true)     // 30
CGFloat(75.0).modulate(from: [100, 50], to: [200, 100], limit: true)  // 150
CGFloat(200.0).modulate(from: [100, 0], to: [200, 100], limit: false) // 300

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment