Mix CABasicAnimation with CGAffineTransform animation - ios

I need to rotate an UIImageView continuously. To do this I found this code :
if ([self.image.layer animationForKey:#"SpinAnimation"] == nil) {
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2 * M_PI];
animation.duration = 90.0f;
animation.repeatCount = INFINITY;
[self.image.layer addAnimation:animation forKey:#"SpinAnimation"];
}
Then, I need to make a transform translation on the image view, animating it. If I do this :
CGAffineTransform transform = self.image.transform;
transform = CGAffineTransformTranslate(transform, 0, 350);
[UIView animateWithDuration:1.0f animations:^{
[self.view layoutIfNeeded];
self.image.transform = transform;
} completion:^(BOOL finished) {
self.isMiddleViewOpened = YES;
}];
When the animation is performed, the image float all around the view before arriving to the end point of the translation.
Thanks ☺️
EDIT
I have issue because in my second transform I edit only the y value, but the image doesn't move only on y axis. If you try this code, you'll see the issue

There is no way to mix both animations, you can use Core animation to do all your animation stuff.
I use this in my splash screen to rotate four image blocks and combine them into one in the end.
The animation would like this:
Code for one image block: Top left block , I call it 00 block
- (void)addSplashScreenAnimationWithCompletion:(void (^)(BOOL finished))completionBlock
{
[self addSplashScreenAnimationWithBeginTime:0 andFillMode:kCAFillModeBoth andRemoveOnCompletion:NO completion:completionBlock];
}
- (void)addSplashScreenAnimationWithBeginTime:(CFTimeInterval)beginTime andFillMode:(NSString *)fillMode andRemoveOnCompletion:(BOOL)removedOnCompletion completion:(void (^)(BOOL finished))completionBlock
{
CAMediaTimingFunction *linearTiming = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
if (completionBlock)
{
CABasicAnimation *representativeAnimation = [CABasicAnimation animationWithKeyPath:#"not.a.real.key"];
representativeAnimation.duration = 8.500; //your duration
representativeAnimation.delegate = self;
[self.layer addAnimation:representativeAnimation forKey:#"SplashScreen"];
}
CAKeyframeAnimation *_00RotationAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.rotation.z"];
_00RotationAnimation.duration = 8.500;
_00RotationAnimation.values = #[#(0.000), #(18.829), #(18.829)];
_00RotationAnimation.keyTimes = #[#(0.000), #(0.353), #(1.000)];
_00RotationAnimation.timingFunctions = #[linearTiming, linearTiming];
_00RotationAnimation.beginTime = beginTime;
_00RotationAnimation.fillMode = fillMode;
_00RotationAnimation.removedOnCompletion = removedOnCompletion;
CAKeyframeAnimation *_00OpacityAnimation = [CAKeyframeAnimation animationWithKeyPath:#"opacity"];
_00OpacityAnimation.duration = 8.500;
_00OpacityAnimation.values = #[#(0.000), #(0.497), #(0.553), #(0.759), #(0.921), #(1.000), #(0.642), #(0.341), #(0.000), #(0.000)];
_00OpacityAnimation.keyTimes = #[#(0.000), #(0.059), #(0.118), #(0.176), #(0.235), #(0.353), #(0.471), #(0.647), #(0.765), #(1.000)];
_00OpacityAnimation.timingFunctions = #[linearTiming, linearTiming, linearTiming, linearTiming, linearTiming, linearTiming, linearTiming, linearTiming, linearTiming];
_00OpacityAnimation.beginTime = beginTime;
_00OpacityAnimation.fillMode = fillMode;
_00OpacityAnimation.removedOnCompletion = removedOnCompletion;
CAKeyframeAnimation *_00ScaleXAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale.x"];
_00ScaleXAnimation.duration = 8.500;
_00ScaleXAnimation.values = #[#(0.600), #(0.600), #(1.187), #(1.187)];
_00ScaleXAnimation.keyTimes = #[#(0.000), #(0.353), #(0.765), #(1.000)];
_00ScaleXAnimation.timingFunctions = #[linearTiming, linearTiming, linearTiming];
_00ScaleXAnimation.beginTime = beginTime;
_00ScaleXAnimation.fillMode = fillMode;
_00ScaleXAnimation.removedOnCompletion = removedOnCompletion;
CAKeyframeAnimation *_00ScaleYAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale.y"];
_00ScaleYAnimation.duration = 8.500;
_00ScaleYAnimation.values = #[#(0.688), #(0.688), #(1.359), #(1.359)];
_00ScaleYAnimation.keyTimes = #[#(0.000), #(0.353), #(0.765), #(1.000)];
_00ScaleYAnimation.timingFunctions = #[linearTiming, linearTiming, linearTiming];
_00ScaleYAnimation.beginTime = beginTime;
_00ScaleYAnimation.fillMode = fillMode;
_00ScaleYAnimation.removedOnCompletion = removedOnCompletion;
CAKeyframeAnimation *_00TranslationXAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.translation.x"];
_00TranslationXAnimation.duration = 8.500;
_00TranslationXAnimation.values = #[#(0.000), #(107.423), #(211.936), #(211.936)];
_00TranslationXAnimation.keyTimes = #[#(0.000), #(0.353), #(0.765), #(1.000)];
_00TranslationXAnimation.timingFunctions = #[linearTiming, linearTiming, linearTiming];
_00TranslationXAnimation.beginTime = beginTime;
_00TranslationXAnimation.fillMode = fillMode;
_00TranslationXAnimation.removedOnCompletion = removedOnCompletion;
CAKeyframeAnimation *_00TranslationYAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.translation.y"];
_00TranslationYAnimation.duration = 8.500;
_00TranslationYAnimation.values = #[#(0.000), #(390.498), #(476.237), #(476.237)];
_00TranslationYAnimation.keyTimes = #[#(0.000), #(0.353), #(0.765), #(1.000)];
_00TranslationYAnimation.timingFunctions = #[linearTiming, linearTiming, linearTiming];
_00TranslationYAnimation.beginTime = beginTime;
_00TranslationYAnimation.fillMode = fillMode;
_00TranslationYAnimation.removedOnCompletion = removedOnCompletion;
}
The above method contains series of animations like rotating, opacity changin,,scaling along x and y axis,translating along x and y axis.
You need to subclass the UIImageView or UIView and put the animation in there.
You can call the above method like:
//Here _splashView can be UIView or UIImageView
[_splashView addSplashScreenAnimationWithCompletion:^(BOOL finished) {
//Do your stuff after animation is completed
}];
You can use repeatCount for CAKeyFrameAnimation too, and you should give HUGE_VALF to get the infinity time rotation.

Related

Flickering in simple animation chain

I'm trying to animate a pulsting circle. But after the downward scale, there's something of a flickering effect. Any ideas to why that is? Here's my code so far:
- (instancetype)init
{
self = [super init];
if (self) {
if (!self.path) {
self.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:7 startAngle:0.0*(M_PI/180.0) endAngle:360.0*(M_PI/180.0) clockwise:YES].CGPath;
}
[self animateCircleUpward];
}
return self;
}
-(void)animateCircleUpward {
[CATransaction begin];
[CATransaction setCompletionBlock:^{[self animateCircleDownward];}];
CABasicAnimation * scaleUpwardAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale.xy"];
scaleUpwardAnimation.fromValue = #(0.7);
scaleUpwardAnimation.toValue = #(1.0);
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.fromValue = #(1.0);
opacityAnimation.toValue = #(0.6);
self.fillColor = [UIColor greenColor].CGColor;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
NSArray *animations = #[scaleUpwardAnimation, opacityAnimation];
animationGroup.duration = 0.4;
animationGroup.animations = animations;
[self addAnimation:animationGroup forKey:#"pulse"];
[CATransaction commit];
}
-(void)animateCircleDownward {
[CATransaction begin];
[CATransaction setCompletionBlock:^{[self animateCircleUpward];}];
CABasicAnimation * scaleDownwardAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale.xy"];
scaleDownwardAnimation.fromValue = #(1.0);
scaleDownwardAnimation.toValue = #(0.7);
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.fromValue = #(0.6);
opacityAnimation.toValue = #(1.0);
self.fillColor = [UIColor greenColor].CGColor;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
NSArray *animations = #[scaleDownwardAnimation, opacityAnimation];
animationGroup.duration = 0.4;
animationGroup.animations = animations;
[self addAnimation:animationGroup forKey:#"pulse"];
[CATransaction commit];
}
#end
Thanx in advance!
In regards to your actual question you likely need to set your CAAnimationGroup's fillMode property to kCAFillModeForward. The default value is kCAFillModeRemoved, so you are likely glimpsing the non-presentation layer between calls back and forth from your Down and Up methods.
That said, it appears that what you're trying to create is a cyclic animation through back and forth calls between your Up and Down methods via CATransaction's completionBlock. This seems an incredibly inefficient approach; why not try something more like:
-(void)scaleAndOpacityAnimations
{
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale.xy”];
scaleAnimation.fromValue = #(0.7f);
scaleAnimation.toValue = #(1.0f);
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#“opacity”];
opacityAnimation.fromValue = #(1.0f);
opacityAnimation.toValue = #(0.6f);
CAAnimationGroup *scaleAndOpacity = [CAAnimationGroup animation];
scaleAndOpacity.animations = #[scaleAnimation, opacityAnimation];
scaleAndOpacity.autoReverses = YES;
scaleAndOpacity.repeatCount = HUGE_VALF;
//OP had no value indicated for the duration in posted code, I’m including it here for completion
scaleAndOpacity.duration = 0.5f;
[self addAnimation:scaleAndOpacity forKey:#“pulse”];
}
Which will simply repeat infinitely many times without having to instantiate new CAAnimations on each cycle.

Mimic UIAlertController show animation

So I created my own custom UIView that looks like an alert, and now I want to add show and hide animations.
I want to mimic Apples default animations for the AlertController. The dismissal is an simple fade animation, however I'm not sure how to articulate the show animation, it's almost like a fade in mixed with a shrink.
Anyways if anybody know how to recreate it I'd really appreciate it.
This is my final result:
This gif is doing it no justice but it's very similar to UIAlertControllers animations.
-(void)alerterShowAnimation {
self.alpha = 0;
self.hidden = NO;
self.transform = CGAffineTransformMakeScale(1.2, 1.2);
[UIView animateWithDuration:0.3 animations:^{
self.alpha = 1.0f;
self.containerView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
}];
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.transform = CGAffineTransformIdentity;
} completion:nil];
}
Instead of UIView animation, try using the core animation.
I have created a simple UIView with grey background, and added the animation below:
- (void)addAlertPopUpAnimationWithBeginTime:(CFTimeInterval)beginTime andFillMode:(NSString *)fillMode andRemoveOnCompletion:(BOOL)removedOnCompletion completion:(void (^)(BOOL finished))completionBlock
{
CAMediaTimingFunction *linearTiming = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
if (completionBlock)
{
CABasicAnimation *representativeAnimation = [CABasicAnimation animationWithKeyPath:#"not.a.real.key"];
representativeAnimation.duration = 0.200;
representativeAnimation.delegate = self;
[self.layer addAnimation:representativeAnimation forKey:#"AlertPopUp"];
}
CAKeyframeAnimation *proPicOpacityAnimation = [CAKeyframeAnimation animationWithKeyPath:#"opacity"];
proPicOpacityAnimation.duration = 0.200;
proPicOpacityAnimation.values = #[#(0.000), #(0.525), #(1.000)];
proPicOpacityAnimation.keyTimes = #[#(0.000), #(0.500), #(1.000)];
proPicOpacityAnimation.timingFunctions = #[linearTiming, linearTiming];
proPicOpacityAnimation.beginTime = beginTime;
proPicOpacityAnimation.fillMode = fillMode;
proPicOpacityAnimation.removedOnCompletion = removedOnCompletion;
[[self layer] addAnimation:proPicOpacityAnimation forKey:#"alertPopUp_Opacity"];
CAKeyframeAnimation *proPicScaleXAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale.x"];
proPicScaleXAnimation.duration = 0.200;
proPicScaleXAnimation.values = #[#(0.304), #(0.345), #(0.300)];
proPicScaleXAnimation.keyTimes = #[#(0.000), #(0.500), #(1.000)];
proPicScaleXAnimation.timingFunctions = #[linearTiming, linearTiming];
proPicScaleXAnimation.beginTime = beginTime;
proPicScaleXAnimation.fillMode = fillMode;
proPicScaleXAnimation.removedOnCompletion = removedOnCompletion;
[[self layer] addAnimation:proPicScaleXAnimation forKey:#"alertPopUp_ScaleX"];
CAKeyframeAnimation *proPicScaleYAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale.y"];
proPicScaleYAnimation.duration = 0.200;
proPicScaleYAnimation.values = #[#(0.381), #(0.435), #(0.389)];
proPicScaleYAnimation.keyTimes = #[#(0.000), #(0.500), #(1.000)];
proPicScaleYAnimation.timingFunctions = #[linearTiming, linearTiming];
proPicScaleYAnimation.beginTime = beginTime;
proPicScaleYAnimation.fillMode = fillMode;
proPicScaleYAnimation.removedOnCompletion = removedOnCompletion;
[[self layer] addAnimation:proPicScaleYAnimation forKey:#"alertPopUp_ScaleY"];
CAKeyframeAnimation *proPicTranslationXAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.translation.x"];
proPicTranslationXAnimation.duration = 0.200;
proPicTranslationXAnimation.values = #[#(0.000), #(0.194), #(0.683)];
proPicTranslationXAnimation.keyTimes = #[#(0.000), #(0.500), #(1.000)];
proPicTranslationXAnimation.timingFunctions = #[linearTiming, linearTiming];
proPicTranslationXAnimation.beginTime = beginTime;
proPicTranslationXAnimation.fillMode = fillMode;
proPicTranslationXAnimation.removedOnCompletion = removedOnCompletion;
[[self layer] addAnimation:proPicTranslationXAnimation forKey:#"alertPopUp_TranslationX"];
CAKeyframeAnimation *proPicTranslationYAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.translation.y"];
proPicTranslationYAnimation.duration = 0.200;
proPicTranslationYAnimation.values = #[#(0.000), #(11.242), #(0.581)];
proPicTranslationYAnimation.keyTimes = #[#(0.000), #(0.500), #(1.000)];
proPicTranslationYAnimation.timingFunctions = #[linearTiming, linearTiming];
proPicTranslationYAnimation.beginTime = beginTime;
proPicTranslationYAnimation.fillMode = fillMode;
proPicTranslationYAnimation.removedOnCompletion = removedOnCompletion;
[[self layer] addAnimation:proPicTranslationYAnimation forKey:#"alertPopUp_TranslationY"];
}
- (void)addAlertPopUpAnimationWithCompletion:(void (^)(BOOL finished))completionBlock
{
[self addAlertPopUpAnimationWithBeginTime:0 andFillMode:kCAFillModeBoth andRemoveOnCompletion:NO completion:completionBlock];
}
When you want to add animations, call right after you add your view as subview:
You need to subclass the UIView and put the code in there.
Later you can call:
[_yourView addAlertPopUpAnimationWithCompletion:^(BOOL finished) {
//do your stuff after animation is finished
}];
The animation looks like this:

Can I rotate UIImage around the centre with animation?

I want to rotate image in circular animation. How can I do it in a simple way?
I know it is not difficult but I'm new to iOS.
Can anybody tell me right code ?
its my solution:
- (void)startAnimation
{
[UIView animateWithDuration:.4 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.loadingRingImageView setTransform:CGAffineTransformRotate(self.loadingRingImageView.transform, M_SQRT2)];
} completion:^(BOOL finished) {
if (finished)
{
[self startAnimation];
}
}];
}
[[self.<imageviewinstance> layer] addAnimation:[self rotationAnimation] forKey:nil];
Add the animation as above and the below is the animation code.
- (CABasicAnimation *)rotationAnimation
{
CABasicAnimation *rotAnim = [CABasicAnimation animationWithKeyPath:#"position"];
[rotAnim setFromValue:[NSValue valueWithCGPoint:CGPointMake(100.0, 400.0)]];
rotAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(300.0, 150.0)];
// rotAnim.duration = 5.0;
rotAnim.autoreverses = YES;
// rotAnim.repeatCount = HUGE_VAL;
rotAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
return rotAnim;
}
if the above is not worked use this
- (CABasicAnimation *)rotationAnimation
{
CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:#"transform.rotation" ];
move.delegate = self;
[move setFromValue:[NSNumber numberWithFloat:0]];
[move setToValue:[NSNumber numberWithFloat:50]];
[move setDuration:10.0f];
move.autoreverses = YES;
}
the answer of question i was wondering is ->
UIImageView *imageViewForAnimation = [[UIImageView alloc] initWithImage:imageToAnimate];
imageViewForAnimation.alpha = 1.0f;
CGRect imageFrame = imageViewForAnimation.frame;
//Your image frame.origin from where the animation need to get start
CGPoint viewOrigin = imageViewForAnimation.frame.origin;
viewOrigin.y = viewOrigin.y + imageFrame.size.height / 2.0f;
viewOrigin.x = viewOrigin.x + imageFrame.size.width / 2.0f;
imageViewForAnimation.frame = imageFrame;
imageViewForAnimation.layer.position = viewOrigin;
[self.view addSubview:imageViewForAnimation];
// Set up fade out effect
CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
[fadeOutAnimation setToValue:[NSNumber numberWithFloat:0.3]];
fadeOutAnimation.fillMode = kCAFillModeForwards;
fadeOutAnimation.removedOnCompletion = NO;
// Set up scaling
CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:#"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(40.0f, imageFrame.size.height * (40.0f / imageFrame.size.width))]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;
// Set up path movement
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
//Setting Endpoint of the animation
CGPoint endPoint = CGPointMake(480.0f - 30.0f, 40.0f);
//to end animation in last tab use
//CGPoint endPoint = CGPointMake( 320-40.0f, 480.0f);
CGMutablePathRef curvedPath = CGPathCreateMutable();
CGPathMoveToPoint(curvedPath, NULL, viewOrigin.x, viewOrigin.y);
CGPathAddCurveToPoint(curvedPath, NULL, endPoint.x, viewOrigin.y, endPoint.x, viewOrigin.y, endPoint.x, endPoint.y);
pathAnimation.path = curvedPath;
CGPathRelease(curvedPath);
CAAnimationGroup *group = [CAAnimationGroup animation];
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
[group setAnimations:[NSArray arrayWithObjects:fadeOutAnimation, pathAnimation, resizeAnimation, nil]];
group.duration = 0.7f;
group.delegate = self;
[group setValue:imageViewForAnimation forKey:#"imageViewBeingAnimated"];
[imageViewForAnimation.layer addAnimation:group forKey:#"savingAnimation"];

Two animations on one layer

I have a CALayer, and I want to show it and then hide.
CALayer *layerOne = [CALayer layer];
[layerOne addSublayer:textOne];
layerOne.frame = CGRectMake(0, 0, size.width, size.height);
[layerOne setMasksToBounds:YES];
layerOne.opacity = 0.0;
CABasicAnimation *animationOne = [CABasicAnimation animationWithKeyPath:#"opacity"];
[animationOne setDuration:0];
[animationOne setFromValue:[NSNumber numberWithFloat:0.0]];
[animationOne setToValue:[NSNumber numberWithFloat:1.0]];
[animationOne setBeginTime:3];
[animationOne setRemovedOnCompletion:NO];
[animationOne setFillMode:kCAFillModeForwards];
[layerOne addAnimation:animationOne forKey:#"animateOpacity"];
This code work successfully, layerOne appear after 3 seconds.
But I want to hide this layer, so I add this:
CABasicAnimation *animationTwo = [CABasicAnimation animationWithKeyPath:#"opacity"];
[animationTwo setDuration:0];
[animationTwo setFromValue:[NSNumber numberWithFloat:1.0]];
[animationTwo setToValue:[NSNumber numberWithFloat:0.0]];
[animationTwo setBeginTime:6];
[animationTwo setRemovedOnCompletion:NO];
[animationTwo setFillMode:kCAFillModeForwards];
[layerOne addAnimation:animationTwo forKey:#"animateOpacity"];
And it doesn't work. layerOne not appear after 3 seconds. Its just flashed in second 6 and disappear. Its seems like the second animation blocking the first one and only the second animation is going on.
What I do wrong?
Well, for one thing since the second animation has the same key, when you add it to the layer, the original animation will be removed. When the animation is removed, it's long-term effect (setting opacity = 1.0) will also be removed so the animation will be immediately hidden.
For something like this, the normal process to show the layer is:
// set the final result you want to persist forever
layerOne.opacity = 1.0;
// set up your animation here
CABasicAnimation *animationOne = [CABasicAnimation animationWithKeyPath:#"opacity"];
animationOne.fromValue = #(0.);
animationOne.toValue = #(1.);
animationOne.duration = 3.;
animationOne.beginTime = 0.;
animationOne.removedOnCompletion = true;
animationOne.fillMode = kCAFillModeRemove; // for clarity, this is the default
[layerOne addAnimation:animationOne forKey:#"animateOpacity"];
And then when you want to hide the layer just reverse the process:
// Set the final animation state
layerOne.opacity = 0.0;
// set up your animation here
CABasicAnimation *animationTwo = [CABasicAnimation animationWithKeyPath:#"opacity"];
animationTwo.fromValue = #(1.);
animationTwo.toValue = #(0.);
animationTwo.duration = 3.;
animationTwo.beginTime = 0.;
animationTwo.removedOnCompletion = true;
animationTwo.fillMode = kCAFillModeRemove; // for clarity, this is the default
[layerOne addAnimation:animationTwo forKey:#"animateOpacity"];
If you're wanting to run the whole process as a single event, you should put both animations into a single animation group:
// set up your animation here
CABasicAnimation *animationOne = [CABasicAnimation animationWithKeyPath:#"opacity"];
animationOne.fromValue = #(0.);
animationOne.toValue = #(1.);
animationOne.duration = 3.;
animationOne.beginTime = 0.;
animationOne.fillMode = kCAFillModeForwards;
// set up your animation here
CABasicAnimation *animationTwo = [CABasicAnimation animationWithKeyPath:#"opacity"];
animationTwo.fromValue = #(1.);
animationTwo.toValue = #(0.);
animationTwo.beginTime = 6.;
animationTwo.duration = 3.;
animationOne.fillMode = kCAFillModeForwards;
// set up the animation group
CAAnimationGroup* group = [CAAnimationGroup new];
group.beginTime = 0.;
group.duration = 9.;
group.animations = #[ animationOne, animationTwo ];
[layerOne addAnimation:group forKey:#"animateOpacity"];

CABasicAnimation how to get current angle of rotation

I have some problem with CABasicAnimation. It`s similar to that post: CABasicAnimation rotate returns to original position
So, i have uiimageview that rotate in touchMove. In touchEnd invoke method that do "animation of inertia" :
-(void)animationRotation: (float)beginValue
{
CABasicAnimation *anim;
anim = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
anim.duration = 0.5;
anim.repeatCount = 1;
anim.fillMode = kCAFillModeForwards;
anim.fromValue = [NSNumber numberWithFloat:beginValue];
[anim setDelegate:self];
anim.toValue = [NSNumber numberWithFloat:(360*M_PI/180 + beginValue)];
[appleView.layer addAnimation:anim forKey:#"transform"];
CGAffineTransform rot = CGAffineTransformMakeRotation(360*M_PI/180 + beginValue);
appleView.transform = rot;
}
This animation works fine, but if I invoke touchBegan before animationRotation ended, angle of rotation is beginValue. I need cath current angle of rotation. As an experiment, i declare method
-(vod) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
NSLog(#"Animation finished!");
}
and it's seems working. but I don't know how get that value of angle or CGAffineTransform for my UIImageView in animationDidStop.
It's even possible to do? Thanks.
you should use presentationLayer method to get layer properties during animation in flight.
so your code should be like this,
#define RADIANS_TO_DEGREES(__ANGLE__) ((__ANGLE__) / (float)M_PI * 180.0f)
-(void)animationRotation: (float)beginValue
{
CABasicAnimation *anim;
anim = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
anim.duration = 0.5;
anim.repeatCount = 1;
anim.fillMode = kCAFillModeForwards;
anim.fromValue = [NSNumber numberWithFloat:beginValue];
[anim setDelegate:self];
//get current layer angle during animation in flight
CALayer *currentLayer = (CALayer *)[appleView.layer presentationLayer];
float currentAngle = [(NSNumber *)[currentLayer valueForKeyPath:#"transform.rotation.z"] floatValue];
currentAngle = roundf(RADIANS_TO_DEGREES(currentAngle));
NSLog(#"current angle: %f",currentAngle);
anim.toValue = [NSNumber numberWithFloat:(360*M_PI/180 + beginValue)];
[appleView.layer addAnimation:anim forKey:#"transform"];
CGAffineTransform rot = CGAffineTransformMakeRotation(360*M_PI/180 + beginValue);
appleView.transform = rot;
}

Resources