David DelMonte David DelMonte - 3 months ago 23
Swift Question

Animate a circle from the center in Swift

I have a circle that I'm animating. It works except that the drawing is from the top left.. Can I animate it from the center? If so, any help would be appreciated..

My code for drawing the circle is:

class CircleView: UIView {

override func draw(_ rect: CGRect)
{
let prefs: UserDefaults = UserDefaults.standard
lineWidthFloat = prefs.value(forKey: "lineWidth") as! Float
let circleSize = Double(lineWidthFloat * 100)
let context = UIGraphicsGetCurrentContext()
context!.setLineWidth(10.0)
context!.setFillColor(UIColor.black.cgColor)
let rect = CGRect(x: 20, y: 20, width: circleSize, height: circleSize)
context!.addEllipse(inRect: rect)
context!.fillPath()
}

}


Thanks!

Answer

here's a sample code

ViewController.swift

import UIKit

class ViewController: UIViewController {

var circle = CircleView()
var button = UIButton()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    circle = CircleView(frame: CGRect(x: 40, y: 50, width: 40, height: 60))
    circle.backgroundColor = UIColor.clearColor()
    view.addSubview(circle)

    let button = UIButton(frame: CGRect(x: 20, y: 150, width: 80, height: 40))
    button.setTitle("Animate", forState: .Normal)
    button.setTitleColor(UIColor.blueColor(), forState: .Normal)
    button.setTitleColor(UIColor.blueColor().colorWithAlphaComponent(0.3), forState: .Highlighted)
    button.addTarget(self, action: #selector(ViewController.animateCircle), forControlEvents: .TouchUpInside)
    view.addSubview(button)
}

func animateCircle() {
    circle.resizeCircleWithPulseAinmation(30, duration: 1.5)
}
}

CircleView.swift

import UIKit

class CircleView: UIView {

var circle = UIView()
var isAnimating = false

override func drawRect(rect: CGRect)
{
    super.drawRect(rect)

    resetCircle()
    addSubview(circle)
}

func resetCircle() {

    var rectSide: CGFloat = 0
    if (frame.size.width > frame.size.height) {
        rectSide = frame.size.height
    } else {
        rectSide = frame.size.width
    }

    let circleRect = CGRect(x: (frame.size.width-rectSide)/2, y: (frame.size.height-rectSide)/2, width: rectSide, height: rectSide)
    circle = UIView(frame: circleRect)
    circle.backgroundColor = UIColor.yellowColor()
    circle.layer.cornerRadius = rectSide/2
    circle.layer.borderWidth = 2.0
    circle.layer.borderColor = UIColor.redColor().CGColor
}

func circlePulseAinmation(summand: CGFloat, duration: NSTimeInterval, completionBlock:()->()) {

    UIView.animateWithDuration(duration, delay: 0,  options: .CurveEaseInOut, animations: {

        self.frame.origin.x -= summand/2
        self.frame.origin.y -= summand/2

        self.frame.size.height += summand
        self.frame.size.width += summand


        self.circle.frame.size.height += summand
        self.circle.frame.size.width += summand


    }) { _ in
       completionBlock()
    }

    let animation = CABasicAnimation(keyPath:"cornerRadius")
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    animation.fromValue = circle.layer.cornerRadius
    animation.toValue =  circle.frame.size.width/2
    animation.duration = duration
    circle.layer.cornerRadius = self.circle.frame.size.width/2
    circle.layer.addAnimation(animation,forKey:"cornerRadius")

}

func resizeCircleWithPulseAinmation(summand: CGFloat,  duration: NSTimeInterval) {
    if (!isAnimating) {
        isAnimating = true

        circlePulseAinmation(summand, duration:duration, completionBlock: {
            self.circlePulseAinmation((-1)*summand, duration:duration, completionBlock: {self.isAnimating = false})
        })
    }
}
}