我正在用CAKeyframeAnimation实现一个财富之轮,并在动画停止后尝试读取结果.但在这里,我没有得到确定性的结果.动画停止后是否无法读取旋转?
这是我的动画代码:
let anim = CAKeyframeAnimation(keyPath: "transform.rotation.z") anim.duration = max(strength / 2, 1.0) anim.isCumulative = true anim.values = [NSNumber(value: Float(p)), Float(circleRotationOffset)] anim.keyTimes = [NSNumber(value: Float(0)),NSNumber(value: Float(1.0))] anim.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)] anim.isRemovedOnCompletion = false anim.fillMode = kCAFillModeForwards anim.delegate = self wheelImage.layer.removeAllAnimations() wheelImage.layer.add(anim, forKey: "rotate")
在这里我如何阅读轮换:
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { readImageOrientation() } func readImageOrientation(){ let radians:Double = atan2( Double(wheelImage.transform.b), Double(wheelImage.transform.a)) let degrees:CGFloat = CGFloat(radians) * (CGFloat(180) / CGFloat(M_PI)) sectionForDegrees(degree: degrees) }
为了完整起见,我完整的课程.
class WOFView: UIView, CAAnimationDelegate { @IBOutlet weak var wheelImage: UIImageView! private var history = [Dictionary]() private var rotation: CGFloat = 0 private var startAngle: CGFloat = 0 private var circleRotationOffset: CGFloat = 0 override func touchesBegan(_ touches: Set , with event: UIEvent?) { super.touchesBegan(touches, with: event) if let touchPoint = touches.first?.location(in: self){ if startAngle == 0{ startAngle = atan2(self.frame.width - touchPoint.y, self.frame.height - touchPoint.x) } rotation = startAngle if !touch(touches.first!, isInLeftHalfOf: wheelImage) { rotation = -rotation } history.removeAll() } } override func touchesMoved(_ touches: Set , with event: UIEvent?) { super.touchesMoved(touches, with: event) guard let touchPoint = touches.first?.location(in: self) else { return } let dic = ["time" : NSNumber(value: CFAbsoluteTimeGetCurrent()), "point": NSValue(cgPoint: touchPoint), "rotation": NSNumber(value: Float(circleRotationOffset + rotation))] history.insert(dic, at: 0) if history.count == 3{ history.removeLast() } rotation = atan2(self.frame.width - touchPoint.y, self.frame.height - touchPoint.x) - startAngle if !touch(touches.first!, isInLeftHalfOf: wheelImage) { rotation = -rotation } wheelImage.transform = CGAffineTransform(rotationAngle: circleRotationOffset + rotation) print("offset: \(circleRotationOffset)") readImageOrientation() } override func touchesEnded(_ touches: Set , with event: UIEvent?) { super.touchesEnded(touches, with: event) guard let touchPoint = touches.first?.location(in: self) else { return } guard let lastObject = history.last else{ return } guard let pointValue = lastObject["point"] as? CGPoint else{ return } guard let timeValue = lastObject["time"] as? NSNumber else { return } guard let rotationValue = lastObject["rotation"] as? NSNumber else { return } let timeDif = CFAbsoluteTimeGetCurrent() - (timeValue.doubleValue) circleRotationOffset = circleRotationOffset + rotation let lastRotation = rotationValue.floatValue let dist = sqrt(((pointValue.x - touchPoint.x) * (pointValue.x - touchPoint.x)) + ((pointValue.y - touchPoint.y) * (pointValue.y - touchPoint.y))) let strength = max(Double(min(1.0, dist / 80.0)) * (timeDif / 0.25) * M_PI * 2, 0.3) * 30 let p = circleRotationOffset let dif = circleRotationOffset - CGFloat(lastRotation) var inc = dif > 0 if dif > 3 || dif < -3{ inc = !inc } if (inc){ circleRotationOffset += CGFloat(strength) }else{ circleRotationOffset -= CGFloat(strength) } let anim = CAKeyframeAnimation(keyPath: "transform.rotation.z") anim.duration = max(strength / 2, 1.0) anim.isCumulative = true anim.values = [NSNumber(value: Float(p)), Float(circleRotationOffset)] anim.keyTimes = [NSNumber(value: Float(0)),NSNumber(value: Float(1.0))] anim.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)] anim.isRemovedOnCompletion = false anim.fillMode = kCAFillModeForwards anim.delegate = self wheelImage.layer.removeAllAnimations() wheelImage.layer.add(anim, forKey: "rotate") } func touch(_ touch:UITouch, isInLeftHalfOf view: UIView) -> Bool { let positionInView = touch.location(in: view) return positionInView.x < view.frame.midX } func touch(_ touch:UITouch, isInUpperHalfOf view: UIView) -> Bool { let positionInView = touch.location(in: view) return positionInView.y < view.frame.midY } func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { readImageOrientation() } func readImageOrientation(){ let radians:Double = acos(Double(wheelImage.transform.a)) let degrees:CGFloat = CGFloat(radians) * (CGFloat(180) / CGFloat(M_PI)) sectionForDegrees(degree: degrees) } func sectionForDegrees(degree: CGFloat){ var result = "not defined" switch degree{ case 0 ... 90: result = "3 \(degree)" case 90.1...180: result = "2 \(degree)" case 181.1...270: result = "1 \(degree)" case 270.1...360: result = "4 \(degree)" default: result = "not defined: \(degree)" } print(result) }
}