【发布时间】:2017-09-23 15:42:26
【问题描述】:
我想为我的自定义视图的背景颜色设置动画。
我的绘图代码很简单。 draw(in:) 方法被这样覆盖:
@IBDesignable
class SquareView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
let strokeWidth = self.width / 8
let path = UIBezierPath()
path.move(to: CGPoint(x: self.width - strokeWidth / 2, y: 0))
path.addLine(to: CGPoint(x: self.width - strokeWidth / 2, y: self.height - strokeWidth / 2))
path.addLine(to: CGPoint(x: 0, y: self.height - strokeWidth / 2))
self.backgroundColor?.darker().setStroke()
path.lineWidth = strokeWidth
path.stroke()
}
}
darker 方法只返回调用它的颜色的较暗版本。
当我将背景设置为蓝色时,它会绘制如下内容:
我想为其背景颜色设置动画,使其逐渐变为红色。这将是最终结果:
我第一次尝试:
UIView.animate(withDuration: 1) {
self.square.backgroundColor = .red
}
它只是瞬间将颜色变为红色,没有动画。
然后我研究并发现我需要使用CALayers。因此,我尝试分层绘制:
@IBDesignable
class SquareViewLayers: UIView {
dynamic var squareColor: UIColor = .blue {
didSet {
setNeedsDisplay()
}
}
func setupView() {
layer.backgroundColor = squareColor.cgColor
let sublayer = CAShapeLayer()
let path = UIBezierPath()
let strokeWidth = self.width / 8
path.move(to: CGPoint(x: self.width - strokeWidth / 2, y: 0))
path.addLine(to: CGPoint(x: self.width - strokeWidth / 2, y: self.height - strokeWidth / 2))
path.addLine(to: CGPoint(x: 0, y: self.height - strokeWidth / 2))
self.tintColor.darker().setStroke()
path.lineWidth = strokeWidth
sublayer.path = path.cgPath
sublayer.strokeColor = squareColor.darker().cgColor
sublayer.lineWidth = strokeWidth
sublayer.backgroundColor = UIColor.clear.cgColor
layer.addSublayer(sublayer)
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
}
但结果很糟糕
我使用此代码尝试对此进行动画处理:
let anim = CABasicAnimation(keyPath: "squareColor")
anim.fromValue = UIColor.blue
anim.toValue = UIColor.red
anim.duration = 1
square.layer.add(anim, forKey: nil)
什么都没有发生。
我很困惑。这样做的正确方法是什么?
编辑:
darker 方法来自一个名为 SwiftyColor 的可可豆荚。它是这样实现的:
// in an extension of UIColor
public func darker(amount: CGFloat = 0.25) -> UIColor {
return hueColor(withBrightnessAmount: 1 - amount)
}
private func hueColor(withBrightnessAmount amount: CGFloat) -> UIColor {
var hue: CGFloat = 0
var saturation: CGFloat = 0
var brightness: CGFloat = 0
var alpha: CGFloat = 0
if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
return UIColor(hue: hue, saturation: saturation,
brightness: brightness * amount,
alpha: alpha)
}
return self
}
【问题讨论】:
-
嗯,只有 3 个点的形状不可能是正方形。 move(to:..) 在不绘制的情况下移动光标,然后你有两个 addLine(to:...) 绘制两侧,你似乎至少缺少一侧,因此一个形状是闭合的,它形成一个正方形(前提是您的意图)。
-
至于动画颜色,您是在向您的视图指示它需要刷新自身,但没有任何东西将方形颜色绑定到图层背景颜色。
-
@ekscrypto 我的意图是绘制一个水平倒置的“L”形。你的意思是我应该画出倒“L”形的六个边并填充?
-
我对 L 形状不是 100% 确定,我还没有做足够多的 CALayer 动画来说明。你要么必须确保你的形状是封闭的,要么告诉它不要自动关闭路径;我无法回答。
标签: ios swift animation calayer