Sway Animation in iOS - ios

I was wondering if it's possible to do some sort of sway animation in iOS. For example, a sway animation would be like a store sign blowing in the wind. think westerns. I would like to do this kind of animation when a button is pressed. I'm going for a western kind of feel and that would really put it over the top. Thanks in advance if you know how to do something like this.

In order to do this you have to do a couple of things beforehand such as setting the layer anchor point to (0.5,0.0). like the following:
swaybtn.layer.anchorPoint = CGPointMake(0.5, 0.0);
And then make a function that gets called when the button is tapped which starts the backwards sway animation, another which sways forward, and a last one that moves back to the original position. The degrees you specify is how far the sway will go and the second number in the rotationAndPerspectiveTransform is the direction the sway will go.
The functions are as follow:
-(void)sway:(id)sender{
CGFloat degrees = 50.0;
CALayer *layer;
layer = swaybtn.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(moveForward)];
rotationAndPerspectiveTransform.m34 = 1.0 / -400;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degrees * M_PI / 180.0f, -1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
}
-(void)moveForward{
CALayer *layer;
layer = swaybtn.layer;
CGFloat degrees = 50.0;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
[UIView beginAnimations:#"swayforward" context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(moveBack)];
rotationAndPerspectiveTransform.m34 = 1.0 / -400;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degrees * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
}
-(void)moveBack{
CALayer *layer;
layer = swaybtn.layer;
CGFloat degrees = 50.0;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
[UIView beginAnimations:#"moveback" context:NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
rotationAndPerspectiveTransform.m34 = 1.0 / -400;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, degrees * M_PI / 180.0f, 0.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
}
And there you go. You should have an animation that sways an object back and forth just like a hanging sign.

Related

UIView to UIImage conversion not working correctly

I am trying to get a screenshot of a UIView which is rotated. This is my code
-(void)rotateImage:(int)radian
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformRotate(self.baseImageView.transform, M_PI/2 * radian);
self.baseImageView.transform = transform;
}
-(NSData *)getData
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO,0.0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return UIImageJPEGRepresentation(img, 1.0);
}
Screenshot is created successfully, but after that all the viewcontrollers i present is presented from top left and views bounce & misbehave. However if i create screen shot without rotating the image everything is fine. I am stuck with it any help is appreciated.
Note : i already tried modifying UIGraphicsBeginImageContextWithOptions parameters . My project does not use ARC.
It turns out that the animation was not handled properly.I ended up doing this to solve the problem.
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
CGAffineTransform transform = CGAffineTransformRotate(self.baseImageView.transform, M_PI/2 * radian);
self.baseImageView.transform = transform;
} completion:nil];

Move image 90 degree using Bezier curve

I am new to iOS please some one help me to move image using Bezier curve along 90 degree path. I had searched but my doubt is not clear yet, So please help me.
I had tried this code but I would like to use Bezier curve.
- (void)startApp {
UIImageView *imageToMove =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"man.jpg"]];
imageToMove.frame = CGRectMake(10, 10, 100, 100);
[self.view addSubview:imageToMove];
// Move the image
[self moveImage:imageToMove
duration:1.0
curve:UIViewAnimationCurveLinear
x:70.0
y:70.0];
}
- (void)moveImage:(UIImageView *)image
duration:(NSTimeInterval)duration
curve:(int)curve
x:(CGFloat)x
y:(CGFloat)y {
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
You can rotate (transform) view using CABasicAnimation also. I have done some calculation for that.
- (void) rotateAnimation {
CABasicAnimation *topAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
topAnimation.autoreverses = NO;
topAnimation.duration = 0.8;
topAnimation.repeatDuration = 0;
topAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DPerspect(CATransform3DMakeRotation(M_PI, 1, 0, 0), CGPointMake(0, 0), 400)];
[image.layer addAnimation:topAnimation forKey:nil];
}
And supporting methods for that rotation are below:
CATransform3D CATransform3DMakePerspective(CGPoint center, float disZ)
{
CATransform3D transToCenter = CATransform3DMakeTranslation(-center.x, -center.y, 0);
CATransform3D transBack = CATransform3DMakeTranslation(center.x, center.y, 0);
CATransform3D scale = CATransform3DIdentity;
scale.m34 = -1.0f/disZ;
return CATransform3DConcat(CATransform3DConcat(transToCenter, scale), transBack);
}
CATransform3D CATransform3DPerspect(CATransform3D t, CGPoint center, float disZ)
{
return CATransform3DConcat(t, CATransform3DMakePerspective(center, disZ));
}
About rotation is on X-axis (horizontal) on respective layer. You can change axis value to Y and Z from below line in rotateAnimation.
CATransform3DMakeRotation(M_PI, 1, 0, 0), CGPointMake(0, 0), 400)]
By changing 1, 0, 0 values to 0, 1, 0 in above code will change rotation on Y axis and similarly for Z axis. Replace values and have look for rotation you like.
Here is my UIImageView with IBOutlet named drawPad.
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150)
radius:100
startAngle:0
endAngle:(22.0f/7.0f)
clockwise:YES];
UIGraphicsBeginImageContext(self.view.frame.size);
path.lineCapStyle = kCGLineCapRound;
path.lineWidth = 10.0f;
[[UIColor blackColor] setStroke];
[path stroke];
self.drawpad.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

CATransform3D breaks UIView into two parts before animation

I have a problem with CATransform3D.
When I try to do a Y axis rotation, the UIView breaks into two parts before animation starts.
An image is worth a thousand words...
Here's the code:
CATransform3D _3Dt = CATransform3DMakeRotation(2.0 * M_PI, 0.0, 1.0, 0.0);
[UIView animateWithDuration:2.0
animations:^{
view.layer.transform = _3Dt;
}];
Any idea?
Thanks!
Solved!
The problem was the layer.zPosition
Here's is the final code:
view.layer.zPosition = CGRectGetWidth(view.bounds);
CATransform3D _3Dt = CATransform3DMakeRotation(2.0 * M_PI, 0.0, 1.0, 0.0);
[UIView animateWithDuration:2.0
animations:^{
view.layer.transform = _3Dt;
}];
Thanks!

Rotating UIImageView more than 180 degrees using animations on iOS

Im trying to animate a moving meter by rotating it more than 180 degrees, but it wont work. Im using CGAffineTransform to rotate the meter, which uses a net result to make the rotation. This means that i cannot choose CW or CCW rotation when using this function. How can I modified this code to make it rotate 4 radians. Currently the rotation is transformed to a net result, making the rotation minimal.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGAffineTransform transform = CGAffineTransformMakeRotation(4);
self.meter.transform = transform;
[UIView commitAnimations];
EDIT:
From the answers i managed to get it working by doing this
[UIView animateWithDuration:1.5 animations:^{
CABasicAnimation *fullRotation;
fullRotation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
fullRotation.fromValue = [NSNumber numberWithFloat:0];
fullRotation.toValue = [NSNumber numberWithFloat:((330*M_PI)/180)];
fullRotation.duration = 2.0f;
fullRotation.repeatCount = 1;
fullRotation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
fullRotation.fillMode = kCAFillModeForwards;
fullRotation.removedOnCompletion = NO;
// add animation in your view
[self.meter.layer addAnimation:fullRotation forKey:#"330"];
[self performSelector:#selector(stopRotate:) withObject:self.meter afterDelay:2.0];
}];
//Add This in header prefix
#define MAXFLOAT 0x1.fffffep+127f
// add For rotation
[UIView animateWithDuration:1.5 animations:^{
CABasicAnimation *fullRotation;
fullRotation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
fullRotation.fromValue = [NSNumber numberWithFloat:0];
fullRotation.toValue = [NSNumber numberWithFloat:(2*M_PI))];
fullRotation.duration =1.0f;
fullRotation.repeatCount = MAXFLOAT;
// add animation in your view
[yourView.layer addAnimation:fullRotation forKey:#"360"];
[self performSelector:#selector(stopRotate:) withObject:yourView afterDelay:1.0];
}];
And Add this code to stop rotation From view
-(void)stopRotate :(UIView *)yourView
{
[yourView.layer removeAnimationForKey:#"360"];
}
Try this, just change the basic properties to match your requirements:
CATransform3D rotationTransform = CATransform3DMakeRotation(((4) * (180.0 / M_PI)), 0, 0, 1.0);
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
rotationAnimation.toValue = [NSValue valueWithCATransform3D:rotationTransform];
rotationAnimation.duration = 0.6f;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1;
//Add this two lines
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.removedOnCompletion = NO;
[self.meter.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
Let me know is it works for you.
You need to convert the radian to degree using the following macro:
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
and pass the value to the function:
-(UIImage*)rotateImage:(UIImage*)img forAngle:(CGFloat)degree {
UIView *rotatedViewBox = [[UIView alloc]initWithFrame:CGRectMake(0, 0, img.size.width, img.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(degree);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, rotatedSize.width, rotatedSize.height);
CGContextRotateCTM(context, radian);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(-img.size.width, -img.size.height, img.size.width, img.size.height), img.CGImage);
UIImage *returnImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returnImg;
}

CATransform3D around all axis

I'm trying to create a kind of 'flip' animation that rotates a UIView 180 degrees around each axis, however, I am having trouble getting the desired effect. Here's what I've got so far:
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CATransform3D tX= CATransform3DIdentity;
tX.m34 = 1.0 / -500;
CATransform3D tY= CATransform3DIdentity;
tY.m34 = 1.0 / -500;
CATransform3D tZ= CATransform3DIdentity;
tZ.m34 = 1.0 / -500;
tX = CATransform3DRotate(tX, M_PI, 1.0f, 0.0f, 0.0f);
tY = CATransform3DRotate(tY, M_PI, 0.0f, 1.0f, 0.0f);
tZ = CATransform3DRotate(tZ, M_PI, 0.0f, 0.0f, 1.0f);
self.flipView.layer.transform = CATransform3DConcat(tX, CATransform3DConcat(tY, tZ));
}
This however, doesn't appear to perform any animations, as if they are canceling eachother out. Seems like this should be a pretty straightforward task, but I can't seem to figure out how to combine each of those 3 animation conditions. Any help greatly appreciated! thanks
Rotating by a half-rotation (180° or π radians) about each of the three axes does, in total, result in no change (the concatenation of the three rotation transforms results in the identity transform).
Try rotating about just one axis to see what that does.

Resources