问题描述
我正在为一个应用程序制作一些自定义类型的加载器,我只是在我的视图中制作了 4 个圆形图层,并且所有设置和显示效果都很好。但是当我对所有图层应用脉冲动画缩放时,它们会干扰我所有的设计和图层缩放,但它改变了它的中心点。我希望所有圆形图层首先缩放图层并缩小其大小并使其变大然后再次标识它应该称为无穷大。但不应该改变它的中心点。
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),clockwise: true)
circleLayers(path: secondCirleLayer.cgPath,color: UIColor.yellow)
let thirdCirleLayer = UIBezierPath(arcCenter: CGPoint(x: width * 0.75,clockwise: true)
circleLayers(path: thirdCirleLayer.cgPath,color: UIColor.brown)
let fourthCirleLayer = UIBezierPath(arcCenter: CGPoint(x: halfOfView,y: width * 0.75),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)
}
}
解决方法
要从其中心缩放每个圆,您必须将每个图层的 frame
设置为贝塞尔曲线路径的边界框。并且因为框架已经代表了每个圆的位置,所以您可以为贝塞尔曲线路径的 CGPoint(x: radius,y: radius)
设置一个恒定的 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,color: .yellow)
let thirdCenter = CGPoint(x: width * 0.75,y: halfOfView)
makeCircleLayer(center: thirdCenter,color: .brown)
let fourthCenter = CGPoint(x: halfOfView,y: width * 0.75)
makeCircleLayer(center: fourthCenter,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),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)
}
}
结果:
但是,由于您的圆只是圆(不是复杂的形状),您应该只使用带有圆角半径的 UIView
。以下代码产生相同的结果,但更简洁。
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,y: halfOfView / 2)
makeCircleView(center: secondCenter,y: halfOfView)
makeCircleView(center: thirdCenter,y: width * 0.75)
makeCircleView(center: fourthCenter,color: .blue)
}
func makeCircleView(center: CGPoint,color: UIColor) {
let frame = CGRect(x: center.x - radius,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)
}
}
}