Swift:UIBezierPath 从中心开始的描边动画

13
我一直在使用Swift制作简单的UIBezierPath动画。该路径由创建带有彩色边框的圆角矩形组成。动画必须是绘制彩色边框。为此,我创建了一个CAShapeLayer,其中包含UIBezierPath(roundedRect:, cornerRadius: )
let layer = CAShapeLayer()
var viewPrueba = UIView()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    viewPrueba = UIView(frame: CGRectMake(self.view.frame.width/2-100, self.view.frame.height/2 - 100, 200, 200))
    self.view.addSubview(viewPrueba)
    let path = UIBezierPath(roundedRect: CGRectMake(0, 0, 200, 200), cornerRadius: 40.0)
    layer.path = path.CGPath
    layer.fillColor = UIColor.clearColor().CGColor
    layer.strokeColor = UIColor.blueColor().CGColor
    layer.strokeStart = 0.0
    layer.strokeEnd = 0.0
    layer.lineWidth = 4.0
    layer.lineJoin = kCALineJoinRound
    viewPrueba.layer.addSublayer(layer)
    let tapGR = UITapGestureRecognizer(target: self, action: #selector(ViewController.anim))
    self.view.addGestureRecognizer(tapGR)
}

func anim() {
    let anim1 = CABasicAnimation(keyPath: "strokeEnd")
    anim1.fromValue         = 0.0
    anim1.toValue           = 1.0
    anim1.duration          = 4.0
    anim1.repeatCount       = 0
    anim1.autoreverses      = false
    anim1.removedOnCompletion = false
    anim1.additive = true
    anim1.fillMode = kCAFillModeForwards
    self.layer.addAnimation(anim1, forKey: "strokeEnd")
}`

它运作良好。唯一的问题是动画从正方形的左上角开始,而不是顶部中心。我该怎么做?

我发现唯一能够实现这个目标的方法是使用圆形而不是矩形,但这不是我们想要的。

This is where the animation starts

谢谢

2个回答

17

CoreAnimate按照绘制UIBezierPath的相同顺序进行动画。
系统方法

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;     

返回一个从左上角开始绘制的UIBezierPath,这样你的动画就可以从左上角开始。
但是你也可以创建自己从顶部中心开始绘制的UIBezierPath:

func centerStartBezierPath(frame:CGRect,cornerRadius:CGFloat) -> UIBezierPath {
    let path = UIBezierPath()
    path.moveToPoint(CGPointMake(frame.width/2.0, 0))
    path.addLineToPoint(CGPointMake(frame.width-cornerRadius, 0))
    path.addArcWithCenter(CGPointMake(frame.width-cornerRadius, cornerRadius),
                          radius: cornerRadius,
                          startAngle: CGFloat(-M_PI/2),
                          endAngle: 0,
                          clockwise: true)
    path.addLineToPoint(CGPointMake(frame.width, frame.height-cornerRadius))
    path.addArcWithCenter(CGPointMake(frame.width-cornerRadius, frame.height-cornerRadius),
                          radius: cornerRadius,
                          startAngle: 0,
                          endAngle: CGFloat(M_PI/2),
                          clockwise: true)
    path.addLineToPoint(CGPointMake(cornerRadius, frame.height))
    path.addArcWithCenter(CGPointMake(cornerRadius, frame.height-cornerRadius),
                          radius: cornerRadius,
                          startAngle: CGFloat(M_PI/2),
                          endAngle: CGFloat(M_PI),
                          clockwise: true)
    path.addLineToPoint(CGPointMake(0, cornerRadius))
    path.addArcWithCenter(CGPointMake(cornerRadius, cornerRadius),
                          radius: cornerRadius,
                          startAngle: CGFloat(M_PI),
                          endAngle: CGFloat(M_PI*3/2),
                          clockwise: true)
    path.closePath()

    path.applyTransform(CGAffineTransformMakeTranslation(frame.origin.x, frame.origin.y))

    return path;
}    

它的工作原理如下:顶部中心开始动画
您还可以更改代码,并从任何您想要的位置开始。


非常好用!谢谢! :) - rulilg
做得很好。(投票)如果您解释一下它的工作原理,并包括不同线段、圆弧等的图表,并注明每个绘图步骤,那会很有帮助。(我通常画出外矩形,然后在角半径处嵌入内矩形,在低不透明度下绘制完整的角圆,有曲线的角在完全不透明度下绘制。 - Duncan C

3

在这三年间,Swift语法发生了很大的变化。以下是我原先接受的答案的更新版,但是适用于Swift 5.1+

private extension UIBezierPath {

    convenience init(roundedRectFromCenter frame: CGRect, cornerRadius: CGFloat) {
        self.init()

        move(to: CGPoint(x: frame.width / 2, y: 0))
        addLine(to: CGPoint(x: frame.width - cornerRadius, y: 0))
        addArc(
            withCenter: CGPoint(x: frame.width - cornerRadius, y: cornerRadius),
            radius: cornerRadius,
            startAngle: -.pi / 2,
            endAngle: 0,
            clockwise: true
        )
        addLine(to: CGPoint(x: frame.width, y: frame.height - cornerRadius))
        addArc(
            withCenter: CGPoint(x: frame.width - cornerRadius, y: frame.height - cornerRadius),
            radius: cornerRadius,
            startAngle: 0,
            endAngle: .pi / 2,
            clockwise: true
        )
        addLine(to: CGPoint(x: cornerRadius, y: frame.height))
        addArc(
            withCenter: CGPoint(x: cornerRadius, y: frame.height - cornerRadius),
            radius: cornerRadius,
            startAngle: .pi / 2,
            endAngle: .pi,
            clockwise: true
        )
        addLine(to: CGPoint(x: 0, y: cornerRadius))
        addArc(
            withCenter: CGPoint(x: cornerRadius, y: cornerRadius),
            radius: cornerRadius,
            startAngle: .pi,
            endAngle: .pi * 3 / 2,
            clockwise: true
        )

        close()
        apply(CGAffineTransform(
            translationX: frame.origin.x,
            y: frame.origin.y
        ))
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接