ios - 如何在动画开启时更改 CABasicAnimation 的 toValue/fromValue

标签 ios animation swift3 cabasicanimation

我正在尝试更改动画为 heartBeatAnimation 的 CABasicAnimation 的 toValue/fromValue 的值

let heartBeatAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
heartBeatAnimation.duration       = 0.75
heartBeatAnimation.repeatCount    = Float.infinity
heartBeatAnimation.autoreverses   = true
heartBeatAnimation.fromValue      = 1.0
heartBeatAnimation.toValue        = 1.15

当动画开启时,我在动画期间获取 transform.scale 的当前值:

let currentValue = someView.layer.presentation()?.value(forKeyPath: "transform.scale")
heartBeatAnimation.fromValue = currentValue
heartBeatAnimation.toValue   = currentValue

在我更改值后,heartBeatAnimation 不会更改其 toValue/fromValue 直到我删除动画然后再次添加!

有没有办法在动画播放时实时进行这些更改?!

最佳答案

您可以通过将模型层的当前比例更新为表示层的比例,然后通过更新 beginTime 属性读取动画,使动画看起来从未停止过,从而使其实时显示。这是一个例子。

import UIKit

class ViewController: UIViewController {


    var scale : CGFloat = 1.2

    var shapeLayer : CAShapeLayer!
    var button : UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        //add a shapelayer
        shapeLayer = CAShapeLayer()
        shapeLayer.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width/4, height: self.view.bounds.width/4)
        shapeLayer.position = self.view.center
        shapeLayer.path = drawStarPath(frame: shapeLayer.bounds).cgPath
        let color = UIColor(red: 0.989, green: 1.000, blue: 0.000, alpha: 1.000)
        shapeLayer.fillColor = color.cgColor
        self.view.layer.addSublayer(shapeLayer)


        //button for action
        button = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width - 20, height: 50))
        button.center = self.view.center
        button.center.y = self.view.bounds.height - 70
        button.addTarget(self, action: #selector(ViewController.pressed(sender:)), for: .touchUpInside)
        button.setTitle("Animate", for: .normal)
        button.setTitleColor(.blue, for: .normal)

        self.view.addSubview(button)

    }

@objc func pressed(sender:UIButton) {

     var isInterupted = false

        if let presentation = shapeLayer.presentation(){
            if let animScale = presentation.value(forKeyPath: "transform.scale.xy"){
                if let value = animScale as? CGFloat{
                    //set current animation spot
                    shapeLayer.transform = CATransform3DScale(CATransform3DIdentity, value, value, 1)
                    shapeLayer.removeAllAnimations()
                    scale += 0.2
                    isInterupted = true
                    print("The current toValue is \(scale)")

                }
            }
        }


        button.setTitle("Animating...", for: .normal)

        let heartBeatAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
        heartBeatAnimation.duration       = 0.5
        let beginTimeNeeded = (1/scale) * CGFloat(heartBeatAnimation.duration)
        heartBeatAnimation.repeatCount    = .greatestFiniteMagnitude
        heartBeatAnimation.autoreverses   = true
        heartBeatAnimation.fromValue      = 1.0
        heartBeatAnimation.toValue        = scale
        if isInterupted == true{
            heartBeatAnimation.beginTime = CFTimeInterval(beginTimeNeeded)
        }
        heartBeatAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        shapeLayer.add(heartBeatAnimation, forKey: "beatAnimation")
    }

    func drawStarPath(frame: CGRect = CGRect(x: 0, y: 0, width: 140, height: 140)) ->UIBezierPath{
        //// Star Drawing
        let starPath = UIBezierPath()
        starPath.move(to: CGPoint(x: frame.minX + 0.50000 * frame.width, y: frame.minY + 0.21071 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.60202 * frame.width, y: frame.minY + 0.35958 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.77513 * frame.width, y: frame.minY + 0.41061 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.66508 * frame.width, y: frame.minY + 0.55364 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.67004 * frame.width, y: frame.minY + 0.73404 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.50000 * frame.width, y: frame.minY + 0.67357 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.32996 * frame.width, y: frame.minY + 0.73404 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.33492 * frame.width, y: frame.minY + 0.55364 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.22487 * frame.width, y: frame.minY + 0.41061 * frame.height))
        starPath.addLine(to: CGPoint(x: frame.minX + 0.39798 * frame.width, y: frame.minY + 0.35958 * frame.height))
        return starPath
    }

}

我按下按钮为动画添加更多比例。 这是结果: Result

关于ios - 如何在动画开启时更改 CABasicAnimation 的 toValue/fromValue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45461010/

相关文章:

ios - 在 iPhone 和计算机(Mac 或 PC)之间传输数据的最快方式是什么?

ios - 如何在 xcode 6 中设置表格单元格颜色?

javascript - 在 google appmaker 中,无法使 requestAnimationFrame 工作

ios - 如何处理协议(protocol)功能覆盖的@available()?

ios - 使用按钮添加和删除 subview

ios - 为什么 nib 文件中的 UITableViewCell(加载并添加到堆栈)在 viewDidAppear 中为零,但在 viewDidLoad 中没问题?

ios - 在运行时在 objective-c 中获取类对象的大小

ios - 使用本地 url 通过 iOS 应用程序进行 ChromeCast 视频(错误)

animation - 是否可以使用 CSS3 动画制作类似星际争霸 2 的自动施法叠加层?

Java 2D 图形 : Animate Fractal tree