'Pulsing Animation on layer
I'm making some custom type of loader for an app where I just simply make 4 circular layers inside my view and it all set and display fine. but when I apply pulsing animation scaling of all layers they disturb all my design and layer scaling fine but it's change it's center point. I wants all circular layers first scaling the layer and make small it's size and make it large then again identity and it should call infinity. but should not change it's center point.
here's I'm sharing my code
class ViewController: BaseViewController{
@IBOutlet weak var layerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
drawCircles()
}
func drawCircles(){
let width = layerView.bounds.width
let halfOfView = width / 2
let firstCirleLayer = UIBezierPath(arcCenter: CGPoint(x: halfOfView / 2, y: halfOfView), radius: halfOfView / 3.5, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
circleLayers(path: firstCirleLayer.cgPath, color: UIColor.purple)
let secondCirleLayer = UIBezierPath(arcCenter: CGPoint(x: halfOfView, y: halfOfView / 2), radius: halfOfView / 3.5, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
circleLayers(path: secondCirleLayer.cgPath, color: UIColor.yellow)
let thirdCirleLayer = UIBezierPath(arcCenter: CGPoint(x: width * 0.75, y: halfOfView), radius: halfOfView / 3.5, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
circleLayers(path: thirdCirleLayer.cgPath, color: UIColor.brown)
let fourthCirleLayer = UIBezierPath(arcCenter: CGPoint(x: halfOfView, y: width * 0.75), radius: halfOfView / 3.5, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
circleLayers(path: fourthCirleLayer.cgPath, color: UIColor.blue)
}
func circleLayers(path: CGPath, color: UIColor){
let layer = CAShapeLayer()
layer.path = path
layer.fillColor = color.cgColor
layerView.layer.addSublayer(layer)
let scaling = CABasicAnimation(keyPath: "transform.scale")
scaling.toValue = 1.2
scaling.duration = 0.3
scaling.autoreverses = true
scaling.repeatCount = .infinity
layer.add(scaling, forKey: nil)
}
}
Solution 1:[1]
To scale each circle from their center, you should set the frame
of each layer to the bezier path's bounding box. Then you can just set a constant origin of CGPoint(x: radius, y: radius)
for the bezier path's arcCenter
.
class ViewController: UIViewController {
@IBOutlet weak var layerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
drawCircles()
}
func drawCircles(){
let width = layerView.bounds.width
let halfOfView = width / 2
let radius = halfOfView / 3.5
let firstCenter = CGPoint(x: halfOfView / 2, y: halfOfView)
makeCircleLayer(center: firstCenter, radius: radius, color: .purple)
let secondCenter = CGPoint(x: halfOfView, y: halfOfView / 2)
makeCircleLayer(center: secondCenter, radius: radius, color: .yellow)
let thirdCenter = CGPoint(x: width * 0.75, y: halfOfView)
makeCircleLayer(center: thirdCenter, radius: radius, color: .brown)
let fourthCenter = CGPoint(x: halfOfView, y: width * 0.75)
makeCircleLayer(center: fourthCenter, radius: radius, color: .blue)
}
func makeCircleLayer(center: CGPoint, radius: CGFloat, color: UIColor) {
let layer = CAShapeLayer()
/// the frame is the actual frame/bounding box of the circle
layer.frame = CGRect(x: center.x - radius, y: center.y - radius, width: radius * 2, height: radius * 2)
/// path is relative to the frame
let path = UIBezierPath(arcCenter: CGPoint(x: radius, y: radius), radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
layer.path = path.cgPath
layer.fillColor = color.cgColor
layerView.layer.addSublayer(layer)
let scaling = CABasicAnimation(keyPath: "transform.scale")
scaling.toValue = 1.2
scaling.duration = 0.3
scaling.autoreverses = true
scaling.repeatCount = .infinity
layer.add(scaling, forKey: nil)
}
}
Result:
However, because your circles are just circles (not a complicated shape), you should just use UIView
's with a corner radius. The following code produces the same result, but is much cleaner.
class ViewController: UIViewController {
@IBOutlet weak var layerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
drawCircles()
}
func drawCircles() {
let width = layerView.bounds.width
let halfOfView = width / 2
let radius = halfOfView / 3.5
let firstCenter = CGPoint(x: halfOfView / 2, y: halfOfView)
makeCircleView(center: firstCenter, radius: radius, color: .purple)
let secondCenter = CGPoint(x: halfOfView, y: halfOfView / 2)
makeCircleView(center: secondCenter, radius: radius, color: .yellow)
let thirdCenter = CGPoint(x: width * 0.75, y: halfOfView)
makeCircleView(center: thirdCenter, radius: radius, color: .brown)
let fourthCenter = CGPoint(x: halfOfView, y: width * 0.75)
makeCircleView(center: fourthCenter, radius: radius, color: .blue)
}
func makeCircleView(center: CGPoint, radius: CGFloat, color: UIColor) {
let frame = CGRect(x: center.x - radius, y: center.y - radius, width: radius * 2, height: radius * 2)
let circleView = UIView(frame: frame)
circleView.backgroundColor = color
circleView.layer.cornerRadius = radius
layerView.addSubview(circleView)
UIView.animate(withDuration: 0.3, delay: 0, options: [.repeat, .autoreverse]) {
circleView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |