2017-08-09 240 views
0

我想用CABasicAnimation擴大和收縮一個圓。我以前設計一個乾淨而有效的方式來繪製使用sinUIView類的drawRect方法的動畫,但不幸的是,似乎你不能動畫或力drawRectUIView.animate方法火焰不管你做什麼。因此,我不得不提出一個使用CABasicAnimation的解決方法。作品的結果類型,但動畫是醜陋的,看起來不正確。下面是我的意思的說明:用CABasicAnimation正確動畫圓弧半徑

enter image description here

翹曲的膨脹和收縮過程中發生,而且似乎是在右側的凹痕或空腔當圓正在擴大。這裏的類,負責製作動畫:

struct PathConfig { 
    var arcCenter: CGPoint 
    var radius: CGFloat 
    let startAngle: CGFloat = 0.0 
    let endAngle: CGFloat = CGFloat(2 * M_PI) 
} 

class RGSStandbyIndicatorView: UIView { 

    // MARK: - Variables & Constants 

    /// The drawing layer. 
    var shapeLayer: CAShapeLayer! 

    // MARK: - Class Methods 

    /// Animation function. 
    func animate(period: CFTimeInterval) { 
     let p: PathConfig = PathConfig(arcCenter: CGPoint(x: frame.width/2, y: frame.height/2) , radius: 17.5) 
     let b: UIBezierPath = UIBezierPath(arcCenter: p.arcCenter, radius: p.radius, startAngle: p.startAngle, endAngle: p.endAngle, clockwise: true) 
     let a: CABasicAnimation = CABasicAnimation(keyPath: "path") 

     a.fromValue = shapeLayer.path 
     a.toValue = b.cgPath 
     a.autoreverses = true 
     a.duration = period 
     a.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     a.repeatCount = HUGE 
     shapeLayer.add(a, forKey: "animateRadius") 
    } 

    /// Initializes and returns a CAShapeLayer with the given draw path and fill color. 
    private class func shapeLayerForPath(_ path: CGPath, with fillColor: CGColor) -> CAShapeLayer { 
     let shapeLayer: CAShapeLayer = CAShapeLayer() 
     shapeLayer.path = path 
     shapeLayer.fillColor = fillColor 
     return shapeLayer 
    } 

    /// Configures the UIView 
    private func setup() { 

     // Init config, path. 
     let cfg: PathConfig = PathConfig(arcCenter: CGPoint(x: frame.width/2, y: frame.height/2) , radius: 0.0) 
     let path: UIBezierPath = UIBezierPath(arcCenter: cfg.arcCenter, radius: cfg.radius, startAngle: cfg.startAngle, endAngle: cfg.endAngle, clockwise: true) 

     // Init CAShapeLayer 
     shapeLayer = RGSStandbyIndicatorView.shapeLayerForPath(path.cgPath, with: UIColor.white.cgColor) 

     layer.addSublayer(shapeLayer) 
    } 

    // MARK: Class Method Overrides 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     setup() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     setup() 
    } 

} 

我試着調整的開始和結束的角度希望是沒有重疊的路徑的一些假象,但它並沒有改變任何東西。我不知道如何解決這個問題,它基於查德威克伍德的answer類似的問題。

+0

爲什麼你請勿使用CGAffineTransform.scale,使您的觀點通過圓角半徑圓角? –

回答

1

使用此UIView子類

class RadioAnimationView: UIView { 

    var animatableLayer : CAShapeLayer? 

    override func awakeFromNib() { 
     super.awakeFromNib() 
     self.layer.cornerRadius = self.bounds.height/2 

     self.animatableLayer = CAShapeLayer() 
     self.animatableLayer?.fillColor = self.backgroundColor?.cgColor 
     self.animatableLayer?.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.layer.cornerRadius).cgPath 
     self.animatableLayer?.frame = self.bounds 
     self.animatableLayer?.cornerRadius = self.bounds.height/2 
     self.animatableLayer?.masksToBounds = true 
     self.layer.addSublayer(self.animatableLayer!) 
     self.startAnimation() 
    } 


    func startAnimation() 
    { 
     let layerAnimation = CABasicAnimation(keyPath: "transform.scale") 
     layerAnimation.fromValue = 1 
     layerAnimation.toValue = 3 
     layerAnimation.isAdditive = false 
     layerAnimation.duration = CFTimeInterval(2) 
     layerAnimation.fillMode = kCAFillModeForwards 
     layerAnimation.isRemovedOnCompletion = true 
     layerAnimation.repeatCount = .infinity 
     layerAnimation.autoreverses = true 

     self.animatableLayer?.add(layerAnimation, forKey: "growingAnimation") 
    } 

} 

希望這有助於你

+0

謝謝,這比我目前的嘗試要好很多。它解決了我的問題。我老實說對CAAffineTransform一無所知。我一直試圖在今天下午第一次完成一些動畫,並在CABasicAnimation中猜測。 – Micrified

+0

@Owatch你的方法是有效的,但你需要使用一個輔助函數來獲取的時間modifiying圓弧的半徑每一個空間正確的路徑,我已經buf絕對它對複雜,當前需要做之前,所以我認爲這是一個爲您提供更好的方法,我很樂意爲您提供幫助,愉快的編碼和最誠摯的問候 –