2

This is my code : import 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
    }()


}

This is my code which I create a CAShapeLayer which will rotate and thus craete a loader effect, but when I add the animation of rotationAnimation, it rotate the whole CAShapeLayer around a center point but not the CAShapeLayer itself. Why do this happen? How can I solve it? Thank you

dramasea
  • 3,370
  • 16
  • 49
  • 77

2 Answers2

0

You should set anchor point like this:

layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
Lumialxk
  • 6,239
  • 6
  • 24
  • 47
0

Your case shall work perfectly for the view with size(width: 40, height: 40).

If you want to generalise to have your circularLoaderView working for other sizes too, You need to

  1. Assign radius to half of the view's height or width(since height=width).

    var circleRadius: CGFloat {
    
      return bounds.size.height/2
    
     }
    
  2. Similarly, your center shall also be at the view's center that is

    circleFrame.origin.x = bounds.size.height/2
    circleFrame.origin.y = bounds.size.height/2
    

Below is the modified code that works appropriately in 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
    }()
}

I know this question was posted a long way back but I just hope this solves the issue of someone who is looking for the similar issue.

Ujwal Agrawal
  • 454
  • 7
  • 8