【问题标题】:Properly animating circle radius with CABasicAnimation使用 CABasicAnimation 正确设置圆半径动画
【发布时间】:2017-08-09 21:43:33
【问题描述】:

我想使用CABasicAnimation 扩大和缩小一个圆。我之前设计了一种干净有效的方法来使用sinUIView 类的drawRect 方法绘制动画,但不幸的是,您似乎无法动画或强制drawRectUIView.animate 方法中触发无论你做什么。因此,我不得不想出一个使用CABasicAnimation 的解决方法。结果有点工作,但动画很丑陋,看起来不正确。这是我的意思的说明:

在膨胀和收缩过程中会发生翘曲,并且在圆圈膨胀时右侧出现凹痕或空洞。这是负责为其设置动画的类:

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()
    }

}

我尝试调整开始和结束角度,希望它是路径没有重叠的一些伪影,但它没有改变任何东西。我不知道如何解决这个问题,它基于 Chadwick Wood 的answer 到一个类似的问题。

【问题讨论】:

  • 为什么你不使用 CGAffineTransform.scale 并让你的视图被圆角半径包围?

标签: ios animation swift3 cabasicanimation


【解决方案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")
    }

}

希望对你有帮助

【讨论】:

  • 谢谢,这比我目前的尝试好多了。它解决了我的问题。老实说,我对 CAAffineTransform 一无所知。我今天下午第一次尝试制作一些动画,我猜是在 CABasicAnimation 上挖的。
  • @Owatch 您的方法是有效的,但是您需要使用辅助函数来在每个时间空间中获得正确的路径来修改圆弧的半径,我已经这样做了,因为它对您当前的情况过于复杂需要,所以我认为这对您来说是一种更好的方法,我很高兴为您提供帮助,祝您编码愉快并致以最诚挚的问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 2014-07-19
  • 2015-01-02
  • 2014-04-24
  • 1970-01-01
相关资源
最近更新 更多