How to create Custom flip animation using UIView - ios

I am trying to create a custom animation something like the default flip animation for a UIView, but without the actual flip, and also the axis of the flip I want to be on the left side not on the center. Here is an example of what I am trying to accomplish but without the repeat:
Also in the code I will add UILabel as sub view and a few more elements.
If you can provide a code example it will be much appreciated
Thank you very much in advance for any support!
Update:
used the example provided by #artal and obtained the wanted effect for UIImageView but how can I obtain the same example for an UIButton?
Tried the next code:
objectivesButton = [[UIButton alloc] initWithFrame:CGRectMake( 0.25f * [UIScreen mainScreen].bounds.size.width, 0.7f * [UIScreen mainScreen].bounds.size.height, 0.5f * [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height * 0.3f)];
[objectivesButton addTarget:self
action:#selector(startAnimationButton)
forControlEvents:UIControlEventTouchUpInside];
objectivesButton.backgroundColor = [UIColor yellowColor];
objectivesButton.layer.anchorPoint = CGPointMake(0, 0.5);
[self.view addSubview:objectivesButton];
- (void)startAnimationButton{
CATransform3D perspectiveTrasnform = CATransform3DIdentity;
perspectiveTrasnform.m34 = -0.004;
CGFloat rotateAngleDeg = 90;
CATransform3D flipTransform = CATransform3DRotate(perspectiveTrasnform, rotateAngleDeg / 180.0 * M_PI, 0, 1.5, 0);
[UIView animateWithDuration:3.0f animations:^()
{
objectivesButton.layer.transform = flipTransform;
}];
}

You can animate the view this way by applying a perspective and rotation transform to its underlying CALayer (a 3D transform).
To start it from the left side you can set the anchorPoint of the layer.
Here's an example:
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
imageView.center = CGPointMake(self.view.center.x - imageView.frame.size.width * 0.5, self.view.center.y + imageView.frame.size.height * 0.5);
imageView.layer.anchorPoint = CGPointMake(0, 1);
[self.view addSubview:imageView];
CATransform3D perspectiveTrasnform = CATransform3DIdentity;
perspectiveTrasnform.m34 = -0.004;
CGFloat rotateAngleDeg = 90;
CATransform3D flipTransform = CATransform3DRotate(perspectiveTrasnform, rotateAngleDeg / 180.0 * M_PI, 0, 1, 0);
[UIView animateWithDuration:5 animations:^()
{
imageView.layer.transform = flipTransform;
}];

Related

IOS: Resize View Using CGAffineTransform

I can't get a CGAffineTransform transformation to expand a view in a table cell and cannot understand why.
Can anyone see what is wrong. Here is my code:
UIView* resizedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))];
[resizedView addSubview:view];
[cell addSubview:view];
CGSize sizeDifference = CGSizeMake(resizedView.frame.size.width - view.frame.size.width, view.frame.size.height - view.frame.size.height);
NSLog(#"width = %f, height = %f", sizeDifference.width, sizeDifference.height);
CGSize transformRatio = CGSizeMake(resizedView.frame.size.width / view.frame.size.width, view.frame.size.height / view.frame.size.height);
// Original transform
CGAffineTransform transform = CGAffineTransformIdentity;
// Scale custom view so image will fill entire cell
transform = CGAffineTransformScale(transform, transformRatio.width, transformRatio.height);
// Move custom view so the old vie's top left aligns with the cell's top left
transform = CGAffineTransformTranslate(transform, -sizeDifference.width / 2.0, -sizeDifference.height / 2.0);
[resizedView setTransform:transform];
The view remains exactly the same. Would appreciate any suggestions.

IOS - How to rotate image at some degree

I want to rotate image with some angle as show in the below image.
I am trying to with that
CGAffineTransform t = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
imageView.transform = t;
I am not getting output like this. even I am not close with this.
Here is the code I used to rotate an image by 30 degrees
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 20, 320, 400)];
imgView.image = [UIImage imageNamed:#"maxresdefault.jpg"];
[self.view addSubview:imgView];
float degrees = 30.0f;
float radians = (degrees* M_PI/180);
imgView.layer.transform = CATransform3DMakeRotation(radians, 0, 0, 1.0);
The Simulator ScreenShot before transform
Here is the Simulator ScreenShot after Transform
Hope this helps you out.
Reset by transform before apply other transforms...
imageView.transform = CGAffineTransformIdentity
// i hope your angle is proper calculate
CGAffineTransform t = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
imageView.transform = t;
Hope it will help you
You can change the layer.transform like below in swift
imageView?.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(rotationAngle: CGFloat(M_PI_2)))
For Objective C :
imageView.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(M_PI_2));

Width and height of progressView

How can I create progressView with width 100 and height 200. And rotate progressView on 90 degrees?
It does not work together.
Or progressView is turned by 90 or change size
self.progressView.transform = CGAffineTransformMakeRotation(M_PI_2);
CGAffineTransform transform = CGAffineTransformMakeScale(1.0f, 3.0f);
_progressView.transform = transform;
You need to chain your transformations. In your sample, the 2nd assignment to transform effectively overwrites the first one. This one works:
UIProgressView *progressBar = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progressBar.frame = CGRectMake(50, 100, 100, 50);
CGAffineTransform t = CGAffineTransformMakeRotation(M_PI_2);
t = CGAffineTransformScale(t, 1.0f, 50.0f);
progressBar.transform = t;
[self.view addSubview:progressBar];
I read about that somewhere...I think CGAffineTransform() works for that
[self.progressView setTransform:CGAffineTransformMakeScale(1.0, 2.0)];
For rotation
#define DEGREES_TO_RADIANS(angle) ((90) / 180.0 * M_PI)
[self.progressView setTransform:CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(angle))];
Swift 4
progressView.transform = CGAffineTransform(scaleX: 1.0, y: 2.0)

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();

iOS - Rotate UIImageView or UIImage while moving its frame with NSTimer

I need to rotate my UIImageView, or the UIImage in the UIImageView, while moving its frame with NSTimer. This is the NSTimer movement :
timer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:#selector(animate) userInfo:nil repeats:YES];
This is the animate method (a part of it, the most important) :
CGRect viewLocation = [[[self layer] presentationLayer] frame];
self.frame = CGRectMake(viewLocation.origin.x, viewLocation.origin.y + 0.2, viewLocation.size.width, viewLocation.size.height);
And this is the method i'm trying to use to rotate the UIImage :
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
[rotatedViewBox release];
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// Rotate the image context
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
This code is inside a subclass of UIImageView, so self is referred to UIImageView.
I also try to rotate UIImageView with CGAffineTransform, but the UIImageView is being stretched and rotate in a strange manner.
This is the method :
- (void)rotateWithDegrees:(CGFloat)degrees {
CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
self.transform = transform;
}
And this is the macro :
#define DEGREES_TO_RADIANS(angle) (angle / 180.0 * M_PI)
The important thing is that you can always use the timer to move the object, so that part is unchangeable.
I found the solution! First of all we exclude the solution that provides the resize of UIImage. So, we rotate the UIImageView, but when use CGAffineTransform the frame have NOT to be modified! So, to move the UIImageView with the timer we have to modify the center of the UIImageView. This is to delete :
CGRect viewLocation = [[[self layer] presentationLayer] frame];
self.frame = CGRectMake(viewLocation.origin.x, viewLocation.origin.y + 0.2, viewLocation.size.width, viewLocation.size.height);
And this is to add :
self.center = CGPointMake(self.frame.origin.x + (self.frame.size.width / 2), self.frame.origin.y + 0.2 + (self.frame.size.height / 2));
Then, we can use the rotateWithDegrees: method to rotate the UIImageView :
- (void)rotateWithDegrees:(CGFloat)degrees {
CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
self.transform = transform;
_degrees+=0.5;
if (_degrees == 360) {
_degrees = 1;
}
}
So, we can add the line :
[self rotateWithDegrees:_degrees];
below :
self.center = CGPointMake(self.frame.origin.x + (self.frame.size.width / 2), self.frame.origin.y + 0.2 + (self.frame.size.height / 2));
The UIImageView moves due to the change of its center, and not due to the change of its frame and this allow to use CGAffineTransform for the rotation.

Resources