Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用动画旋转图像,然后读取旋转_Ios_Swift_Animation_Cakeyframeanimation - Fatal编程技术网

Ios 使用动画旋转图像,然后读取旋转

Ios 使用动画旋转图像,然后读取旋转,ios,swift,animation,cakeyframeanimation,Ios,Swift,Animation,Cakeyframeanimation,我正在实现一个带有CAKeyframeAnimation的命运之轮,并尝试在动画停止后读取结果。但在这里我没有得到确定性的结果。 动画停止后是否无法读取旋转 这里是我的动画代码: let anim = CAKeyframeAnimation(keyPath: "transform.rotation.z") anim.duration = max(strength / 2, 1.0) anim.isCumulative = true anim.val

我正在实现一个带有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)
    }
let view = UIImageView()
view.transform = CGAffineTransform(rotationAngle: 0.02);

let x = view.value(forKeyPath: "layer.transform.rotation.z")
let a = acos(view.transform.a)
let b = asin(view.transform.b)
let c = atan2(view.transform.b, view.transform.a)

print(a)
print(b)
print(c)
print(x!)
为了完整起见,这里是我的全班

class WOFView: UIView, CAAnimationDelegate {

@IBOutlet weak var wheelImage: UIImageView!
private var history = [Dictionary<String, Any>]()
private var rotation: CGFloat = 0
private var startAngle: CGFloat = 0
private var circleRotationOffset: CGFloat = 0


override func touchesBegan(_ touches: Set<UITouch>, 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<UITouch>, 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<UITouch>, 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)
}
类WOFView:UIView,CAAnimationDelegate{
@ibimage:UIImageView!
私有变量历史=[Dictionary]()
私有变量旋转:CGFloat=0
私有变量startAngle:CGFloat=0
专用变量CirclerRotationOffset:CGFloat=0
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
super.touchesbeated(touches,with:event)
如果让接触点=接触.first?位置(in:self){
如果startAngle==0{
startAngle=atan2(self.frame.width-touchPoint.y,self.frame.height-touchPoint.x)
}
旋转=星缠结
if!touch(touch.first!),isInLeftHalfOf:wheelImage){
旋转=-旋转
}
history.removeAll()
}
}
覆盖功能触摸移动(touchs:Set,带有事件:UIEvent?){
super.touchesMoved(touches,with:event)
guard let touchPoint=触碰.first?位置(in:self)else{
返回
}
让dic=[“时间”:NSNumber(值:CFAbsoluteTimeGetCurrent()),
“点”:NSValue(cgPoint:接触点),
“旋转”:NSNumber(值:浮点(圆圈旋转偏移+旋转))]
历史。插入(dic,地址:0)
如果history.count==3{
history.removeLast()
}
旋转=atan2(self.frame.width-touchPoint.y,self.frame.height-touchPoint.x)-startAngle
if!touch(touch.first!),isInLeftHalfOf:wheelImage){
旋转=-旋转
}
wheelImage.transform=CGAffineTransform(旋转角度:圆形旋转偏移+旋转)
打印(“偏移量:\(圆圈旋转偏移量)”)
readImageOrientation()
}
覆盖函数touchesend(touchs:Set,带有事件:UIEvent?){
super.touchesend(触摸,带有:事件)
guard let touchPoint=触碰.first?位置(in:self)else{
返回
}
guard let lastObject=history.last else{
返回
}
guard let pointValue=lastObject[“point”]作为?CGPoint else{
返回
}
guard let timeValue=lastObject[“time”]作为?NSNumber else{
返回
}
guard let rotationValue=lastObject[“rotation”]作为?NSNumber else{
返回
}
让timeDif=CFAbsoluteTimeGetCurrent()-(timeValue.doubleValue)
CirclerRotationOffset=CirclerRotationOffset+旋转
设lastRotation=rotationValue.floatValue
设dist=sqrt(((pointValue.x-touchPoint.x)*(pointValue.x-touchPoint.x))+
((pointValue.y-touchPoint.y)*(pointValue.y-touchPoint.y)))
让强度=最大值(双倍(最小值(1.0,dist/80.0))*(时间差/0.25)*M_PI*2,0.3)*30
设p=圆旋转偏移量
设dif=CirclerRotationOffset-CGFloat(上次旋转)
var inc=dif>0
如果dif>3 | | dif<-3{
公司
}
if(公司){
CirclerRotationOffset+=CGFloat(强度)
}否则{
圆环旋转偏移量-=CGFloat(强度)
}
让anim=CAKeyframeAnimation(关键路径:“transform.rotation.z”)
动画持续时间=最大(强度/2,1.0)
anim.isCumulative=真
anim.values=[NSNumber(值:Float(p)),Float(circleRotationOffset)]
anim.keyTimes=[NSNumber(值:Float(0)),NSNumber(值:Float(1.0))]
anim.timingFunctions=[CAMediaTimingFunction(名称:kCAMediaTimingFunctionEaseOut)]
anim.isRemovedOnCompletion=false
anim.fillMode=kCAFillModeForwards
anim.delegate=self
wheelImage.layer.RemoveAllianimations()文件
wheelImage.layer.add(动画,福克斯:“旋转”)
}
func touch(utouch:UITouch,isInLeftHalfOf view:UIView)->Bool{
让位置查看=触摸位置(在:视图中)
返回位置inview.xBool{
让位置查看=触摸位置(在:视图中)
返回位置查看y
}

原始答案(关于转换的一般想法) 根据三维旋转矩阵的外观,我认为应该使用
acos()
而不是
atan2()

在这个Rz矩阵中,我们可以看到变换.a和变换.b将作为余弦θ给出。参考:

在没有测试的情况下,我非常确定一个简单的
acos(Double(wheelmeage.transform.a))
就足以让您实现θ旋转。编辑:这是错误的建议,用
acos
替换
atan2
意味着你必须检查你的答案是正余弦值还是负余弦值,这完全没有意义。要记住的另一件事是,如果对控制盘应用任何缩放,变换也会发生变化

如果我错了,您可以始终使用
强度
值来计算车轮旋转的时间,并从中找到角度。这将需要您了解
kCamediatimingFunctionaleaseout
是如何准确工作的,因此我建议您将动画更改为
let view = UIImageView()
view.transform = CGAffineTransform(rotationAngle: 0.02);

let x = view.value(forKeyPath: "layer.transform.rotation.z")
let a = acos(view.transform.a)
let b = asin(view.transform.b)
let c = atan2(view.transform.b, view.transform.a)

print(a)
print(b)
print(c)
print(x!)
0.0200000000000011
0.02
0.02
0.02