0

我正在尝试制作一个带有聊天“气泡”的应用程序,我需要为每个气泡状态之间的过渡设置动画。

extension UIView {
    func makeRoundedCorners(topLeftRad: Double, topRightRad: Double, bottomRightRad: Double, bottomLeftRad: Double) {
        let path = UIBezierPath(roundedRect: self.bounds, topLeftRadius: CGFloat(topLeftRad), topRightRadius: CGFloat(topRightRad), bottomRightRadius: CGFloat(bottomRightRad), bottomLeftRadius: CGFloat(bottomLeftRad))
        let maskLayer = CAShapeLayer()
        maskLayer.path = path.cgPath

        let animation = CABasicAnimation(keyPath: "path")
        animation.toValue = path.cgPath
        animation.duration = 1

        maskLayer.add(animation, forKey: "makeRoundedCorners")
        self.layer.mask = maskLayer
    }
}

extension UIBezierPath {
    convenience init(roundedRect rect: CGRect, topLeftRadius r1: CGFloat, topRightRadius r2: CGFloat, bottomRightRadius r3: CGFloat, bottomLeftRadius r4: CGFloat) {
        let left  = CGFloat(Double.pi)
        let up    = CGFloat(1.5*Double.pi)
        let down  = CGFloat(Double.pi / 2)
        let right = CGFloat(0.0)
        self.init()

        addArc(withCenter: CGPoint(x: rect.minX + r1, y: rect.minY + r1), radius: r1, startAngle: left,  endAngle: up,    clockwise: true)
        addArc(withCenter: CGPoint(x: rect.maxX - r2, y: rect.minY + r2), radius: r2, startAngle: up,    endAngle: right, clockwise: true)
        addArc(withCenter: CGPoint(x: rect.maxX - r3, y: rect.maxY - r3), radius: r3, startAngle: right, endAngle: down,  clockwise: true)
        addArc(withCenter: CGPoint(x: rect.minX + r4, y: rect.maxY - r4), radius: r4, startAngle: down,  endAngle: left,  clockwise: true)
        close()
    }
}

所以我写了一个自定义的 UIBeziePath Initializer,然后按照描述为 UIView 添加了一个扩展。

但是当我试图更新单元格的状态时,什么也没有发生,它只是立即绘制路径。我该怎么办?

我附上了一些图片以了解发生了什么

在此处输入图像描述 在此处输入图像描述

我弄错了,将初始路径替换为maskLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 5).cgPath

但是现在这件事正在发生

在此处输入图像描述

4

2 回答 2

1

动画立即发生的原因是相同的路径被分配maskLayer并用作toValue动画的路径。

let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath // same path used here...

let animation = CABasicAnimation(keyPath: "path")
animation.toValue = path.cgPath // ... as here
animation.duration = 1

maskLayer.add(animation, forKey: "makeRoundedCorners")
self.layer.mask = maskLayer

由于该路径是动画的预期最终值,因此您需要提供一个值来制作动画。

注意:如果两条路径具有不同数量的控制点或线段,则路径动画是“未定义的”。

于 2018-08-20T12:19:44.990 回答
1

您需要指定fromValue动画对象的属性。
这样,Core Animation 就知道如何在fromto值之间进行插值。

let animation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path))
animation.fromValue = UIBezierPath(…).path
animation.toValue = path.cgPath
animation.duration = 1

顺便说一句,如果你想用 生成带有漂亮圆角(又名松鼠)的矩形UIBezierPath,你可能需要检查我的 UIBezierPath 扩展

于 2018-08-20T12:19:31.047 回答