使用 UIViewPropertyAnimator 为 UILabel textColor 属性 设置动画
Animating UILabel textColor property with UIViewPropertyAnimator
我有一个看似简单的问题,但我还没有找到解决方案。
我使用 UIViewPropertyAnimator
和滑块手动调整动画师的 fractionComplete
属性.
为带有标签的视图设置动画
在我制作动画的视图中,我有一个 UILabel,我想制作它的动画 textColor
。
我发现 SO answers 建议像这样为 textColor
设置动画:
UIView.transition(with: yourLabel, duration: 0.3, options: .transitionCrossDissolve, animations: {
self.yourLabel.textColor = .red
}, completion: nil)
但是,对我来说这不起作用,因为我希望动画根据我为动画师设置的 fractionComplete
继续。
如评论中所述,textColor
属性 无法设置动画。
但是,有一种称为颜色插值的技术,这可能是一个很好的解决方法。
您可以在this thread中找到多种解决方法,不过,我也为您提供一个解决方案:
extension UIColor {
var components: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
let components = self.cgColor.components!
switch components.count == 2 {
case true :
return (r: components[0], g: components[0], b: components[0], a: components[1])
case false:
return (r: components[0], g: components[1], b: components[2], a: components[3])
}
}
static func interpolate(from fromColor: UIColor, to toColor: UIColor, with progress: CGFloat) -> UIColor {
let fromComponents = fromColor.components
let toComponents = toColor.components
let r = (1 - progress) * fromComponents.r + progress * toComponents.r
let g = (1 - progress) * fromComponents.g + progress * toComponents.g
let b = (1 - progress) * fromComponents.b + progress * toComponents.b
let a = (1 - progress) * fromComponents.a + progress * toComponents.a
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
然后,您所要做的就是在滑块值更改时调用的函数中执行以下操作:
@objc func sliderChanged(_ sender: UISlider) {
animator.fractionComplete = CGFloat(sender.value)
yourLabel.textColor = UIColor.interpolate(from: fromColor, to: toColor, with: sender.value)
}
您没有为 textColor
设置动画,而是在每次调用 sliderChanged
时将其更改为不同的颜色,但这种变化看起来是渐进的,不会从您的起始颜色跳到您的第二个颜色,所以我认为它应该达到你想要的结果。
我有一个看似简单的问题,但我还没有找到解决方案。
我使用 UIViewPropertyAnimator
和滑块手动调整动画师的 fractionComplete
属性.
在我制作动画的视图中,我有一个 UILabel,我想制作它的动画 textColor
。
我发现 SO answers 建议像这样为 textColor
设置动画:
UIView.transition(with: yourLabel, duration: 0.3, options: .transitionCrossDissolve, animations: {
self.yourLabel.textColor = .red
}, completion: nil)
但是,对我来说这不起作用,因为我希望动画根据我为动画师设置的 fractionComplete
继续。
如评论中所述,textColor
属性 无法设置动画。
但是,有一种称为颜色插值的技术,这可能是一个很好的解决方法。
您可以在this thread中找到多种解决方法,不过,我也为您提供一个解决方案:
extension UIColor {
var components: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
let components = self.cgColor.components!
switch components.count == 2 {
case true :
return (r: components[0], g: components[0], b: components[0], a: components[1])
case false:
return (r: components[0], g: components[1], b: components[2], a: components[3])
}
}
static func interpolate(from fromColor: UIColor, to toColor: UIColor, with progress: CGFloat) -> UIColor {
let fromComponents = fromColor.components
let toComponents = toColor.components
let r = (1 - progress) * fromComponents.r + progress * toComponents.r
let g = (1 - progress) * fromComponents.g + progress * toComponents.g
let b = (1 - progress) * fromComponents.b + progress * toComponents.b
let a = (1 - progress) * fromComponents.a + progress * toComponents.a
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
然后,您所要做的就是在滑块值更改时调用的函数中执行以下操作:
@objc func sliderChanged(_ sender: UISlider) {
animator.fractionComplete = CGFloat(sender.value)
yourLabel.textColor = UIColor.interpolate(from: fromColor, to: toColor, with: sender.value)
}
您没有为 textColor
设置动画,而是在每次调用 sliderChanged
时将其更改为不同的颜色,但这种变化看起来是渐进的,不会从您的起始颜色跳到您的第二个颜色,所以我认为它应该达到你想要的结果。