Created
September 14, 2017 14:21
-
-
Save davidbjames/d53536746fad1b21bfc39487beae670e to your computer and use it in GitHub Desktop.
Transformable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public protocol Transformable : class { | |
func scaled(x:CGFloat, y:CGFloat, z:CGFloat?) | |
func rotated(_ radians:CGFloat, x:CGFloat?, y:CGFloat?, z:CGFloat?) | |
func translated(x:CGFloat, y:CGFloat, z:CGFloat?) | |
func resetScale() | |
func resetRotation() | |
func resetTranslation() | |
func resetAllTransforms() | |
} | |
public extension Transformable where Self:UIView { | |
func scaled(x:CGFloat, y:CGFloat, z:CGFloat? = nil) { | |
transform = transform.scaledBy(x: x, y: y) | |
} | |
func rotated(_ radians:CGFloat, x:CGFloat? = nil, y:CGFloat? = nil, z:CGFloat? = nil) { | |
transform = transform.rotated(by: radians) | |
} | |
func translated(x:CGFloat, y:CGFloat, z:CGFloat? = nil) { | |
transform = transform.translatedBy(x: x, y: y) | |
} | |
private var scaleDelta:CGAffineTransform { | |
let t = transform | |
let xScale = sqrt(t.a * t.a + t.c * t.c) | |
let yScale = sqrt(t.b * t.b + t.d * t.d) | |
return CGAffineTransform(scaleX: xScale, y: yScale) | |
} | |
private var rotationDelta:CGAffineTransform { | |
let rotation = CGFloat(atan2f(Float(transform.b), Float(transform.a))) | |
return CGAffineTransform(rotationAngle: rotation) | |
} | |
private var translationDelta:CGAffineTransform { | |
return CGAffineTransform(translationX: transform.tx, y: transform.ty) | |
} | |
func resetScale() { | |
transform = rotationDelta.concatenating(translationDelta) | |
} | |
func resetRotation() { | |
transform = scaleDelta.concatenating(translationDelta) | |
} | |
func resetTranslation() { | |
transform = scaleDelta.concatenating(rotationDelta) | |
} | |
func resetAllTransforms() { | |
transform = CGAffineTransform.identity | |
} | |
} | |
public extension Transformable where Self:CALayer { | |
func scaled(x:CGFloat, y:CGFloat, z:CGFloat?) { | |
transform = CATransform3DScale(transform, x, y, z ?? 0.0) | |
} | |
func rotated(_ radians:CGFloat, x:CGFloat?, y:CGFloat?, z:CGFloat?) { | |
transform = CATransform3DRotate(transform, radians, x ?? 1.0, y ?? 0.0, z ?? 0.0) | |
} | |
func translated(x:CGFloat, y:CGFloat, z:CGFloat?) { | |
transform = CATransform3DTranslate(transform, x, y, z ?? 0.0) | |
} | |
private var scaleDelta:CATransform3D? { | |
guard | |
let scaleX = value(forKeyPath: "transform.scale.x") as? CGFloat, | |
let scaleY = value(forKeyPath: "transform.scale.y") as? CGFloat, | |
let scaleZ = value(forKeyPath: "transform.scale.z") as? CGFloat | |
else { | |
return nil | |
} | |
return CATransform3DMakeScale(scaleX, scaleY, scaleZ) | |
} | |
private var rotationDelta:CATransform3D? { | |
guard | |
let angle = value(forKeyPath: "transform.rotation.angle") as? CGFloat, | |
let x = value(forKeyPath: "transform.rotation.x") as? CGFloat, | |
let y = value(forKeyPath: "transform.rotation.y") as? CGFloat, | |
let z = value(forKeyPath: "transform.rotation.z") as? CGFloat | |
else { | |
return nil | |
} | |
return CATransform3DMakeRotation(angle, x, y, z) | |
} | |
private var translationDelta:CATransform3D? { | |
guard | |
let x = value(forKeyPath: "transform.translation.x") as? CGFloat, | |
let y = value(forKeyPath: "transform.translation.y") as? CGFloat, | |
let z = value(forKeyPath: "transform.translation.z") as? CGFloat | |
else { | |
return nil | |
} | |
return CATransform3DMakeTranslation(x, y, z) | |
} | |
func resetScale() { | |
guard let rotation = rotationDelta, let translation = translationDelta else { | |
return | |
} | |
transform = CATransform3DConcat(rotation, translation) | |
} | |
func resetRotation() { | |
guard let scale = scaleDelta, let translation = translationDelta else { | |
return | |
} | |
transform = CATransform3DConcat(scale, translation) | |
} | |
func resetTranslation() { | |
guard let scale = scaleDelta, let rotation = rotationDelta else { | |
return | |
} | |
transform = CATransform3DConcat(scale, rotation) | |
} | |
func resetAllTransforms() { | |
transform = CATransform3DIdentity | |
} | |
} | |
extension UIView : Transformable {} | |
extension CALayer : Transformable {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment