如何创建一个在swift中旋转CAShapeLayer的动画

时间:2016-03-12 06:56:45

标签: ios swift cashapelayer

这是我的代码: 导入UIKit

class circularLoaderView: UIView {

    let circlePathLayer = CAShapeLayer()
    let circleRadius: CGFloat = 20.0



    override init(frame: CGRect) {

        super.init(frame: frame)
        configure()

    }

    required init(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)!
        configure()
    }

    func configure() {


        circlePathLayer.frame = bounds
        circlePathLayer.lineWidth = 2
        circlePathLayer.fillColor = UIColor.clearColor().CGColor
        circlePathLayer.strokeColor = UIColor.redColor().CGColor

        layer.addSublayer(circlePathLayer)
        backgroundColor = UIColor.whiteColor()



    }

    func circleFrame() -> CGRect {
        var circleFrame = CGRect(x: 0, y: 0, width: 2*circleRadius, height: 2*circleRadius)
        circleFrame.origin.x = 20
        circleFrame.origin.y = 20


        return circleFrame
    }




     func circlePath() -> UIBezierPath {


        let startAngle = CGFloat(-M_PI_2)
        let endAngle = startAngle + CGFloat(M_PI * 2)



        return UIBezierPath(arcCenter: CGPoint(x: circleRadius, y: circleRadius), radius: circleRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true)


     }



    override func layoutSubviews() {
        super.layoutSubviews()

        circlePathLayer.frame = bounds
        circlePathLayer.path = circlePath().CGPath
        circlePathLayer.strokeEnd = 0.25


        circlePathLayer.addAnimation(rotationAnimation, forKey: "transform.rotation")


    }


    let rotationAnimation: CAAnimation = {
        let animation = CABasicAnimation(keyPath: "transform.rotation")
        animation.fromValue = 0
        animation.toValue = M_PI * 2
        animation.duration = 4


        animation.repeatCount = MAXFLOAT
        return animation
    }()


}

这是我创建CAShapeLayer的代码,它会旋转并因此加速加载器效果,但是当我添加rotationAnimation的动画时,它会围绕中心点旋转整个CAShapeLayer,而不是CAShapeLayer本身。为什么会这样?我该如何解决?谢谢

2 个答案:

答案 0 :(得分:0)

您应该像这样设置锚点:

layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)

答案 1 :(得分:0)

您的情况应适合大小的视图(宽度:40,高度:40)。

如果你想推广你的circularLoaderView也适用于其他尺寸,你需要

  1. 将半径指定为视图高度或宽度的一半(因为高度=宽度)。

    var circleRadius: CGFloat {
    
      return bounds.size.height/2
    
     }
    
  2. 同样,您的中心也应位于视图中心

    circleFrame.origin.x = bounds.size.height/2
    circleFrame.origin.y = bounds.size.height/2
    
  3. 以下是在 Swift 3

    中正常运行的修改后的代码
    class circularLoaderView: UIView {
    
        let circlePathLayer = CAShapeLayer()
        var circleRadius: CGFloat {
            return bounds.height/2
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            configure()
    
        }
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)!
            configure()
        }
    
        func configure() {
            circlePathLayer.frame = bounds
            circlePathLayer.lineWidth = 2
            circlePathLayer.fillColor = UIColor.clear.cgColor
            circlePathLayer.strokeColor = UIColor.red.cgColor
    
            layer.addSublayer(circlePathLayer)
            backgroundColor = UIColor.white
        }
    
        //This method is not being used
        /*func circleFrame() -> CGRect {
            var circleFrame = CGRect(x: circleRadius , y: circleRadius, width: 2*circleRadius, height: 2*circleRadius)
            circleFrame.origin.x = circleRadius
            circleFrame.origin.y = circleRadius
    
            return circleFrame
        }*/
    
        func circlePath() -> UIBezierPath {
            let startAngle = CGFloat(-Double.pi/2)
            let endAngle = startAngle + CGFloat(Double.pi * 2)
    
            return UIBezierPath(arcCenter: CGPoint(x: circleRadius, y: circleRadius), radius: circleRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
    
            circlePathLayer.frame = bounds
            circlePathLayer.path = circlePath().cgPath
            circlePathLayer.strokeEnd = 0.25
            circlePathLayer.add(rotationAnimation, forKey: "transform.rotation")
    
        }
    
        let rotationAnimation: CAAnimation = {
            let animation = CABasicAnimation(keyPath: "transform.rotation")
            animation.fromValue = 0
            animation.toValue = Double.pi * 2
            animation.duration = 4    
            animation.repeatCount = MAXFLOAT
    
            return animation
        }()
    }
    

    我知道这个问题已经发布了很长一段时间,但我希望这能解决一个正在寻找类似问题的人的问题。