【问题标题】:Changing color of a view when animation repeats动画重复时更改视图的颜色
【发布时间】:2015-11-14 17:21:05
【问题描述】:

我有一个模拟“脉冲”视图的动画,它首先将其转换为无限小(不可见),然后它又长回来了。

func addPulsing() {
    println("Added")
    let pulsing = CAKeyframeAnimation(keyPath: "transform.scale")

    pulsing.duration = 0.8

    pulsing.values = [1.0,0.0,1.0]
    pulsing.keyTimes = [0.0,0.4,0.8]

    pulsing.removedOnCompletion = false
    pulsing.repeatCount = HUGE
    pulsing.calculationMode = kCAAnimationPaced



    let layer = customView.layer
    layer.addAnimation(pulsing, forKey: "pulsing")
}

我想在每次动画重复时更改视图的颜色。我该怎么做 ?我尝试使用计时器,但它与动画不同步。

更新:

试图做这样的事情:

    UIView.animateKeyframesWithDuration(3.2, delay: 0, options: .CalculationModePaced | .Repeat, animations: { () -> Void in
        UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = transform
        })
        UIView.addKeyframeWithRelativeStartTime(0.4, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = identity
            self.customView.backgroundColor = self.colors[1]
        })
        UIView.addKeyframeWithRelativeStartTime(0.8, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = transform
        })
        UIView.addKeyframeWithRelativeStartTime(1.2, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = identity
            self.customView.backgroundColor = self.colors[2]
        })
        UIView.addKeyframeWithRelativeStartTime(1.6, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = transform
        })
        UIView.addKeyframeWithRelativeStartTime(2.0, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = identity
            self.customView.backgroundColor = self.colors[3]
        })
        UIView.addKeyframeWithRelativeStartTime(2.4, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = transform
        })
        UIView.addKeyframeWithRelativeStartTime(2.8, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = identity
            self.customView.backgroundColor = self.colors[0]
        })
    }, completion: nil)

仍然不能按需要工作。在细节上,动画都是跳跃和不流畅的,有些部分比需要的慢,有些太快了。我希望颜色在视图缩小到 0 比例时立即改变,然后它开始以新的背景颜色增长。

然后我尝试创建两个单独的动画。一种用于比例,一种用于颜色。我将颜色设置为离散的,以便立即更改颜色。所以我得到了:

    let transform = CGAffineTransformScale(customView.transform, 0, 0)
    let identity = CGAffineTransformIdentity

        UIView.animateKeyframesWithDuration(0.8, delay: 0, options: .CalculationModePaced | .Repeat, animations: { () -> Void in
        UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = transform
        })
        UIView.addKeyframeWithRelativeStartTime(0.4, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.transform = identity
        })
    }, completion: nil)


    UIView.animateKeyframesWithDuration(2.8, delay: 0, options: .CalculationModeDiscrete | .Repeat, animations: { () -> Void in
        UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.4, animations: { () -> Void in
            self.customView.backgroundColor = self.colors[1]
        })
        UIView.addKeyframeWithRelativeStartTime(0.4, relativeDuration: 0.8, animations: { () -> Void in
            self.customView.backgroundColor = self.colors[2]
        })
        UIView.addKeyframeWithRelativeStartTime(1.2, relativeDuration: 0.8, animations: { () -> Void in
            self.customView.backgroundColor = self.colors[3]
        })
        UIView.addKeyframeWithRelativeStartTime(2.0, relativeDuration: 0.8, animations: { () -> Void in
            self.customView.backgroundColor = self.colors[0]
        })
    }, completion: nil)

由于某种原因,它只是从颜色 1 跳转到颜色 0,而根本不会更改为颜色 2 和 3。甚至这种从 1 到 0 的转换也是不同步的。有什么想法吗?

【问题讨论】:

    标签: ios objective-c swift user-interface animation


    【解决方案1】:

    您可以添加一个创建随机 uicolors 的函数。

    func getRandomColor() -> UIColor{
    
            var randomRed:CGFloat = CGFloat(drand48())
    
            var randomGreen:CGFloat = CGFloat(drand48())
    
            var randomBlue:CGFloat = CGFloat(drand48())
    
            return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
    
        }
    

    并在你的函数中使用它

    func addPulsing() {
        println("Added")
        let pulsing = CAKeyframeAnimation(keyPath: "transform.scale")
    
        pulsing.duration = 0.8
    
        pulsing.values = [1.0,0.0,1.0]
        pulsing.keyTimes = [0.0,0.4,0.8]
    
        pulsing.removedOnCompletion = false
        pulsing.repeatCount = HUGE
        pulsing.calculationMode = kCAAnimationPaced
    
        //set background color
        customView.backgroundColor = getRandomColor()
        let layer = customView.layer
        layer.addAnimation(pulsing, forKey: "pulsing")
    }
    

    这里是source

    【讨论】:

    • 动画重复时如何改变视图的颜色?
    • 每次动画发生时你都调用这个方法吗?
    • 不,这个方法只创建一个动画,并添加到视图的图层中
    【解决方案2】:

    好的,这两个动画方法中的问题实际上是我整个方法中的问题是我不知道/注意到关键帧中的相对时间是在 0 和 1 之间的间隔中指定的,因此它们是持续时间的一小部分,而我认为它们是事情应该发生的“确切”时间。结果,我解决了这个问题,使用了两个动​​画并设置了正确的时间。

    【讨论】:

    • 代码?看看你是如何解决这个问题的。
    【解决方案3】:

    一种方法是为每个循环重新创建动画,然后在每个动画之后设置视图的颜色。

    // add the first animation
    func firstAnimation() {
        let pulsing = CAKeyframeAnimation(keyPath: "transform.scale")
        pulsing.delegate = self
    
        pulsing.duration = 0.4
        pulsing.values = [1.0,0.0]
        pulsing.keyTimes = [0.0,1.0]
    
        pulsing.calculationMode = kCAAnimationPaced
    
        let layer = customView.layer
        layer.addAnimation(pulsing, forKey: "pulsing")
    }
    
    // continous pulsing animation constructor
    func pulsingAnimation() -> CAAnimation {
        let pulsing = CAKeyframeAnimation(keyPath: "transform.scale")
        pulsing.delegate = self
    
        pulsing.duration = 0.8
    
        pulsing.values = [0.0,1.0,0.0] // invert the scale
        pulsing.keyTimes = [0.0,0.4,0.8]
    
        pulsing.calculationMode = kCAAnimationPaced
    }
    
    // then in the delegate, continue looping
    func animationDidStop(_ theAnimation: CAAnimation!, finished flag: Bool) {
        customView.backgroundColor = // a new color
        customView.layer.addAnimation(pulsingAnimation(), forKey: "pulsing")
    }
    

    【讨论】:

    • 这种方法的问题在于,animationDidStop 和 didStart 方法是在主线程上调用的,这通常会被 UI 内容阻塞。结果,使用这种方法动画会冻结,而它应该在其单独的线程上运行。
    • 如果我错了,请纠正我,但所有 UI 更改,包括动画,都应该在主线程上更新。话虽如此,您的动画在循环之间是否卡顿?
    • 没错,但是在我的情况下,主线程被大量的绘图和布局阻塞了 1-2 秒。因此,我需要找到一种方法,使该动画可重复且正确,而无需在主线程上运行我的代码。
    猜你喜欢
    • 2015-03-03
    • 1970-01-01
    • 2018-08-13
    • 2013-09-10
    • 2018-04-07
    • 2018-10-24
    • 1970-01-01
    • 2022-08-12
    • 1970-01-01
    相关资源
    最近更新 更多