Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transform animation bug in swift?

Here is two code for objective c and swift, both are the same. Using objective c it animate scale correctly, but in swift it just jump to final value, i think this is a bug, can someone test and verify it?

Objective C

    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(200, 200, 100, 100)];
    testView.backgroundColor = [UIColor greenColor];
    [self addSubview:testView];

    CAKeyframeAnimation * transformAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    transformAnim.values                = @[[NSValue valueWithCATransform3D:CATransform3DMakeRotation(3 * M_PI/180, 0, 0, -1)],
                                            [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(3 * M_PI/180, 0, 0, 1))],
                                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.5, 1.5, 1)],
                                            [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(-8 * M_PI/180, 0, 0, 1))]];
    transformAnim.keyTimes              = @[@0, @0.349, @0.618, @1];
    transformAnim.duration              = 1;
    [testView.layer addAnimation:transformAnim forKey:@"test"];

Swift

        let testView = UIView(frame: CGRectMake(200, 200, 100, 100))
        testView.backgroundColor = UIColor.greenColor()
        self.addSubview(testView)

        var transformAnim            = CAKeyframeAnimation(keyPath:"transform")
        transformAnim.values         = [NSValue(CATransform3D: CATransform3DMakeRotation(3 * CGFloat(M_PI/180), 0, 0, -1)),
            NSValue(CATransform3D: CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(3 * CGFloat(M_PI/180), 0, 0, 1))),
            NSValue(CATransform3D: CATransform3DMakeScale(1.5, 1.5, 1)),
            NSValue(CATransform3D: CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(-8 * CGFloat(M_PI/180), 0, 0, 1)))]
        transformAnim.keyTimes       = [0, 0.349, 0.618, 1]
        transformAnim.duration       = 1

        testView.layer.addAnimation(transformAnim, forKey: "transform")

This is objc anim, it works as intended

objc transform anim This is swift anim, scale transform just jump swift transform anim

like image 558
Wan Lutfi Wan Hatta Avatar asked Oct 03 '14 02:10

Wan Lutfi Wan Hatta


2 Answers

I tested your code in both Objective-C and Swift and the behavior was exactly the same in both languages (it looks like your first gif animation in both cases).

enter image description here

Here's how to confirm my results. Your code didn't make sense to me (add a view and animate it all in one move?) so I broke it up into two button methods, and I moved it into the view controller. So, here it is in Objective-C:

@interface ViewController ()
@property (nonatomic) UIView* testView;
@end

@implementation ViewController
- (IBAction) doButton1 {
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(200, 200, 100, 100)];
    testView.backgroundColor = [UIColor greenColor];
    [self.view addSubview:testView];
    self.testView = testView;
}
- (IBAction) doButton2 {
    CAKeyframeAnimation * transformAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    transformAnim.values                = @[[NSValue valueWithCATransform3D:CATransform3DMakeRotation(3 * M_PI/180, 0, 0, -1)],
                                            [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(3 * M_PI/180, 0, 0, 1))],
                                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.5, 1.5, 1)],
                                            [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(-8 * M_PI/180, 0, 0, 1))]];
    transformAnim.keyTimes              = @[@0, @0.349, @0.618, @1];
    transformAnim.duration              = 1;
    [self.testView.layer addAnimation:transformAnim forKey:@"test"];
}
@end

And here it is in Swift:

class ViewController: UIViewController {
    var testView : UIView!

    @IBAction func doButton1() {
        let testView = UIView(frame: CGRectMake(200, 200, 100, 100))
        testView.backgroundColor = UIColor.greenColor()
        self.view.addSubview(testView)
        self.testView = testView
    }
    @IBAction func doButton2() {
        var transformAnim            = CAKeyframeAnimation(keyPath:"transform")
        transformAnim.values         = [NSValue(CATransform3D: CATransform3DMakeRotation(3 * CGFloat(M_PI/180), 0, 0, -1)),
            NSValue(CATransform3D: CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(3 * CGFloat(M_PI/180), 0, 0, 1))),
            NSValue(CATransform3D: CATransform3DMakeScale(1.5, 1.5, 1)),
            NSValue(CATransform3D: CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(-8 * CGFloat(M_PI/180), 0, 0, 1)))]
        transformAnim.keyTimes       = [0, 0.349, 0.618, 1]
        transformAnim.duration       = 1
        self.testView.layer.addAnimation(transformAnim, forKey: "transform")
    }
}

Now, in either language, tap the first button (to add the view) and then the second button (to animate it).

like image 60
matt Avatar answered Nov 14 '22 10:11

matt


Make sure to put

 self.targetView.layoutIfNeeded()

Before calling the animation.

 testView.layer.transform = CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1),      CATransform3DMakeRotation(-8 * CGFloat(M_PI/180), 0, 0, 1))
    testView.layer.addAnimation(transformAnim, forKey: "transform")

It works fine

like image 43
user3677173 Avatar answered Nov 14 '22 09:11

user3677173