How to rotate a view in 3d by 360 degree? - iphone

I am developing an app in which i am rotating a view by 360 degree but i am not able to rotate it 360 degree.
It is getting rotated by 180 degree and after getting rotated it is coming back to it's original position..
animation = [CABasicAnimation animationWithKeyPath:#"transform"];
transform = CATransform3DMakeRotation(3.14f, 1.0f, 1.0f, 1.0f);
value = [NSValue valueWithCATransform3D:transform];
[animation setToValue:value];
[animation setAutoreverses:YES];
[animation setDuration:0.9];
[[rotatBall layer] addAnimation:animation forKey:#"180"]; //rotatBall is a view
In other words,it is making back and forth rotation.
How to rotate it continuously....
Kindly help...

That's a little bit tricky but you can find it in the docs.
To rotate it continuously you first need to set the toValue then set the animation repeat count to HUGH_VALF (defined in math.h).
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
transform = CATransform3DMakeRotation(1.0f, 1.0f, 1.0f, 1.0f);
fromValue = [NSValue valueWithCATransform3D:transform];
transform = CATransform3DMakeRotation(M_PI*2, 1.0f, 1.0f, 1.0f);
toValue = [NSValue valueWithCATransform3D:transform];
animation.fromValue = fromValue;
animation.toValue = toValue;
animation.duration = 0.9f;
animation.repeatCount = HUGE_VALF; // HUGE_VALF is defined in math.h so import it
[rotatBall.layer addAnimation:animation forKey:#"rotation"];

Your animation is reversing after it finishes because you set autoreverses to YES. That's what autoreverses does.
As for why you're rotating by 180 degrees instead of 360... how many radians is 360 degrees?

Related

Flipping two UIView using CATransform3D

I have created Visiting Card which has Front view & back View. When i tap on the front view it should flip the UIView & show the back side of the View.
Here is Code which I am trying:
CATransform3D transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
transform.m34 = 1.0/700.0;
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:#"transform"];
rotation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
rotation.toValue = [NSValue valueWithCATransform3D:transform];
rotation.duration = DURATION;
CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:#"position"];
translation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.imageview.center.x,[[self.imageview superview] center].y-45)];
translation.toValue = [NSValue valueWithCGPoint:CGPointMake(_frame.origin.x+_frame.size.width/2,
_frame.origin.y+_frame.size.height/2)];
translation.duration = DURATION;
CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:#"position"];
translation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.imageview.center.x,[[self.imageview superview] center].y-45)];
translation.toValue = [NSValue valueWithCGPoint:CGPointMake(_frame.origin.x+_frame.size.width/2,
_frame.origin.y+_frame.size.height/2)];
translation.duration = DURATION;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = #[ translation, rotation ];
group.duration = DURATION;
group.delegate = self;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
[layer addAnimation:group forKey:nil];
Above code works perfectly for single view. How to combine the 2nd view to get flipping from front & back effect.
Using Core Animation
You can add both front and back to a container view. The back view will have a 180 degree rotation around Y and the front will be just normal. Both layers will be single sided (by setting layer.doubleSided = NO;.
Then when you apply the rotation you would animate the rotation of the container view so that both front and back animate at the same time.
UIView transitions
Or you could just use the built in flip animation
transitionFromView:toView:duration:options:completion:
and pass either UIViewAnimationOptionTransitionFlipFromLeft or UIViewAnimationOptionTransitionFlipFromRight for the option.

How to programmatically rotate button by 360 Degrees in iPhone?

how the button can be rotated by 360 degree for duration of time 30 sec and after that the button stop rotation.
A 360 rotation animation is only a few lines of code with Core Animation.
CABasicAnimation *rotate =
[CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotate.byValue = #(M_PI*2); // Change to - angle for counter clockwise rotation
rotate.duration = 30.0;
[yourButton.layer addAnimation:rotate
forKey:#"myRotationAnimation"];
By using the byValue property you are doing a relative rotation of 360 degrees to whatever rotation was there before (compared to explicitly specifying the from and to values). This means that the above code will rotate the button 360 degrees even if it is already rotated. All the answers that explicitly specify an end transform are assuming that the button isn't already rotated.
The above example is as small as possible to do just what you asked for ("be rotated by 360 degree for duration of time 30 sec"). If you want to have more control you can optionally make the animation start and/or stop slowly by specifying a timing function
rotate.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
If you haven't already added QuarzCore.framework to your project you will need to do so. Also #import <QuartzCore/QuartzCore.h> in the top of your source file.
CATransform3D myRotationTransform = CATransform3DRotate(Yourbutton.layer.transform, -1, 0.0, 0.0, 1.0);
Yourbutton.layer.transform = myRotationTransform;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: -1];
animation.duration = 30;
animation.repeatCount = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[Yourbutton.layer addAnimation:animation forKey:#"MyAnimation"];
Should work as needed! don't forget to include quartz.framework!
Well I just used
Being self.buttonImageView the ImageView you need to rotate.
[UIView animateKeyframesWithDuration:0.5 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
self.buttonImageView.transform= CGAffineTransformMakeRotation(M_PI);
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
self.buttonImageView.transform= CGAffineTransformMakeRotation(-2* M_PI);
}];
} completion:^(BOOL finished) {
[self.map setCenterCoordinate:self.map.userLocation.location.coordinate animated:YES];
self.buttonImageView.transform= CGAffineTransformMakeRotation(2* M_PI);
}];
[UIView animateWithDuration:.30f animations:^{
btnGallery.transform = CGAffineTransformRotate(CGAffineTransformIdentity, -M_PI);
}];

How to move and rotate object in iphone

I am developing a small game in iphone... Game concept is place an object in top of the bar...Rotating a bar using accelerometer. When bar rotating , i need to move an object with respect to bar. How to implement this concept...Any examples or references?
Rotating both img:
barImg,objImg //UIImageView
barImg.transform = CGAffineTransformMakeRotation(Ypos);
objImg.transform=CGAffineTransformMakeRotation(Ypos);
So for rotating 360 Degree with animation:
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat:-M_PI * 2.0]; // full rotation*/ * rotations * duration ];
rotationAnimation.duration = 1;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = MAXFLOAT;
[rotatingTelIamgeview.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
you can play with toValue for changing the angle.
For moving an object:
CGPoint startPoint = CGPointMake(lvMessageInputBar.animationBubbleImageView.layer.frame.origin.x+lvMessageInputBar.animationBubbleImageView.layer.frame.size.width/2
, lvMessageInputBar.animationBubbleImageView.layer.frame.origin.y +lvMessageInputBar.animationBubbleImageView.layer.frame.size.height/2 );
CGPoint endPoint = CGPointMake(endPoint.origin.x+Endpoint.size.width/2, bubleRect.origin.y+bubleRect.size.height/2);
CGPoint middlePoint = // any point between start and end corrdinates
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y);
CGPathAddQuadCurveToPoint(path, NULL,middlePoint.x, middlePoint.y,endPoint.x,endPoint.y);
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.delegate = self;
pathAnimation.removedOnCompletion = NO;
pathAnimation.path = path;
[pathAnimation setCalculationMode:kCAAnimationCubic];
[pathAnimation setFillMode:kCAFillModeForwards];
pathAnimation.duration = 0.3;
[lvMessageInputBar.animationBubbleImageView.layer addAnimation:pathAnimation forKey:nil];
The above example moves the layer of the object over a path.but CGPathAddQuadCurveToPoint makes the path not diagonal rather circular path (curve).
you can use CGPathAddPath if you do not want this effect.
If you are new to iPhone I would start with layer tutorial to get the idea behind CALayer and then take a look CALayer animations
CALayers introduction:
https://www.raywenderlich.com/3096-calayers-tutorial-for-ios-introduction-to-calayers
CALayer Animation documentation of from Apple:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html
You can also watch Session 424 (Core Animation in Practice, Part 1) and 425 (Core Animation in Practice, Part 2) of WWDC 2010:
https://developer.apple.com/videos/archive/

The serrated(shake) image will be shown when rotating the image if i use CATransform3DMakeRotation

I have a problem with the image rotated.
The serrated(shake) image will be shown when rotating the image if i use CATransform3DMakeRotation(M_PI, 0, 0, -1.0) to make a animation with layer.
The backgroundView is added into another animation view (same as the backgroundView, but the direction is reverse).
The code is:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI , 0, 0, -1.0)];
animation.duration = 30;
animation.cumulative = YES;
animation.repeatCount = INT_MAX;
[backgroundView.layer addAnimation:animation forKey:#"animationOne"];
Thank you for your time.
The problem is fixed , to use the function can remove the serrate of image when rotating.
[self.layer setShouldRasterize:YES];

Why CABasicAnimation will send the layer's view to back and front?

There are two UIViews of similar size. UIView one (A) is originally on top of UIView two (B). When I try to perform a CABasicAnimation transform.rotation.y on A's layer:
CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
CGFloat startValue = 0.0;
CGFloat endValue = M_PI;
rotateAnimation.fromValue = [NSNumber numberWithDouble:startValue];
rotateAnimation.toValue = [NSNumber numberWithDouble:endValue];
rotateAnimation.duration = 5.0;
[CATransaction begin];
[imageA.layer addAnimation:rotateAnimation forKey:#"rotate"];
[CATransaction commit];
During the animation, the animating layer's UIView (A) will be:
sent back (A is suddenly behind B)
rotating ... passed second half of the animation
sent front (A is now on top of B again)
Is there a way to keep A on top of B for the whole animation period? Thanks!
UPDATE: project source is attached: FlipLayer.zip
The problem is a rotation around the Y axis will, in a true 3D compositing system, make layer A intersect with layer B, such that half of layer A should be visible and half should be behind layer B. CoreAnimation does not provide a true 3D compositing system. Instead it attempts to determine which layer is in front of which other layer, and renders it entirely without intersection. In your case, during the first half of the rotation CoreAnimation has decided that layer B is on top of layer A in the 3D space. The simplest solution is probably to set the zPosition of layer A to layer.bounds.size.width (default is 0) for the duration of the animation (or permanently, if it should always be on top).
If you want to set it only for the duration of the animation, you can add a second animation for the transform.translation.z key path. Here's your -flip method modified to use this:
- (IBAction)flip:(id)sender {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
CGFloat startValue = 0.0;
CGFloat endValue = M_PI;
animation.fromValue = [NSNumber numberWithDouble:startValue];
animation.toValue = [NSNumber numberWithDouble:endValue];
animation.duration = 5.0;
[imageOne.layer addAnimation:animation forKey:#"rotate"];
animation.keyPath = #"transform.translation.z";
animation.fromValue = [NSNumber numberWithFloat:imageOne.layer.bounds.size.width];
animation.toValue = animation.fromValue;
[imageOne.layer addAnimation:animation forKey:#"zPosition"];
}
Have you tried adding a [self.view bringSubviewToFront:imageA]; in your animation sequence?
You could try to translate on the z axis and bring A forward first. Perform the rotation and then set the z back to its starting value.
Also, you probably won't see any perspective on the rotation unless you set the .m34 property on the transform. Try something like this:
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0f / -300.0f;
transform = CATransform3DRotate(transform, 0.0f, M_PI, 0.0f);
CABasicAnimation *rotateAnimation = [CABasicAnimation
animationWithKeyPath:#"transform"];
rotateAnimation.fromValue = [NSValue
valueWithCATransform3D(CATransformIdentity)];
rotateAnimation.toValue = [NSValue valueWithCATransform3D(transform)];
rotateAnimation.duration = 5.0;
[imageA.layer addAnimation:rotateAnimation forKey:#"rotate"];
You transaction block is unnecessary.
Best Regards.