Home > database >  How to do linear transition and enlarge Animation By CAKeyframeAnimation?
How to do linear transition and enlarge Animation By CAKeyframeAnimation?

Time:09-15

I want to do a linear animation like this: move the rectangle slowly to center of Screen, and tripled its size while moving.

Here is my wrong code and demo, I can only do animation one by one, but I want to combine this two animation. Also, the end position is not right.

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        presentAnimation()
    }

    private lazy var rectView: UIView = {
        let view = UIView()
        view.backgroundColor = .yellow
        view.layer.borderColor = UIColor.blue.cgColor
        return view
    }()
}

extension ViewController {
    private func setupUI() {
        
        view.addSubview(rectView)
        rectView.snp.makeConstraints { 
            $0.left.equalToSuperview().inset(40)
            $0.top.equalToSuperview().inset(100)
            $0.width.equalTo(40)
            $0[![enter image description here][1]][1].height.equalTo(40)
        }
    }
    
    private func presentAnimation() {
        let testEnlarge = CABasicAnimation(keyPath: "transform.scale")
        testEnlarge.fromValue = 1
        testEnlarge.toValue = 3
        testEnlarge.beginTime = CACurrentMediaTime()   2
        testEnlarge.duration = 1
        testEnlarge.fillMode = .forwards
        testEnlarge.isRemovedOnCompletion = false
        
        let positionX = view.center.x - ((rectView.frame.width * 3)/2)
        let positionY = view.center.y - ((rectView.frame.height * 3)/2)
        
        let testTranslation = CAKeyframeAnimation(keyPath: "transform.translation")
        testTranslation.values = [CGPoint(x: positionX, y: positionY)]
        testTranslation.beginTime = CACurrentMediaTime()   2
        testEnlarge.duration = 1
        testEnlarge.fillMode = .forwards
        testTranslation.isRemovedOnCompletion = false
        
        CATransaction.begin()
        rectView.layer.add(testEnlarge, forKey: nil)
        rectView.layer.add(testTranslation, forKey: nil)
        CATransaction.commit()
    }
}
Here is my **wrong demo**:

enter image description here

CodePudding user response:

For your question, your code has two errors

First one: When you use CAKeyframeAnimation for translation, in values you must define list Array which contains startPoint -> endPoint.

// You must define start point is at the beginning (CGPointZero of view) to end is the destination point
testTranslation.values = [CGPointZero, CGPoint(x: positionX, y: positionY)]

Then after that your code will work OK but not good because of duplication and you can not control all animations like that.

Second error here is: When you want to combine two or more animations you should use CAAnimationGroup to combine then add into layer not adding once by once.

Code will be like this

private func presentAnimation() {
    let testEnlarge = CABasicAnimation(keyPath: "transform.scale")
    testEnlarge.fromValue = 1
    testEnlarge.toValue = 3
    testEnlarge.fillMode = .forwards
    
    let positionX = view.center.x - ((rectView.frame.width * 3)/2)
    let positionY = view.center.y - ((rectView.frame.height * 3)/2)
    
    let testTranslation = CAKeyframeAnimation(keyPath: "transform.translation")
    // you must define start point is at the beginning (CGPointZero of view) to end is the destination point
    testTranslation.values = [CGPointZero, CGPoint(x: positionX, y: positionY)]
    
    let sumAnimation = CAAnimationGroup()
    sumAnimation.animations = [testTranslation, testEnlarge]
    sumAnimation.duration = 1
    sumAnimation.beginTime = CACurrentMediaTime()   2
    
    CATransaction.begin()
    rectView.layer.add(sumAnimation, forKey: nil)
    CATransaction.commit()
}

You will have like the result you want Result

More over: you can use UIView.animate too.

  • Related