【问题标题】:Swift: UIBezierPath Stroke Animation from CenterSwift:来自中心的 UIBezierPath 笔画动画
【发布时间】:2016-04-25 12:01:20
【问题描述】:

我一直在用 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")
}`

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

为了实现这一点,我发现的唯一方法是使用圆形而不是矩形,这不是我们想要的。

谢谢

【问题讨论】:

    标签: ios swift animation uibezierpath stroke


    【解决方案1】:

    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;
    }    
    

    它的工作原理是这样的:
    您还可以更改代码,并从您想要的任何点开始。

    【讨论】:

    • 像魅力一样工作!谢谢! :)
    • 做得很好。 (已投票)如果您解释它是如何工作的,甚至包括一个包含不同线段、圆弧等的图表,并注释每个绘图步骤,这将有所帮助。 (我通常画出外部矩形,然后绘制一个由圆角半径插入的内部矩形,并以低不透明度绘制完整的角圆,以完全不透明度绘制弯曲的角。
    【解决方案2】:

    在这三年中,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
            ))
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-21
      • 2021-02-02
      • 1970-01-01
      • 1970-01-01
      • 2023-02-26
      相关资源
      最近更新 更多