CABasicAnimation rotate view on x axis - ios

I need to rotate my view on x axis with 180 degree. Rotation is done but when it start rotating it folds my half view. This is the code I have done can any one help.
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
rotationAnimation.fromValue = [NSNumber numberWithFloat:0];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0];
rotationAnimation.duration = 2.0;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 0;
[_view_topShowDate.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];

You have to set the anchor point preferably in viewDidLoad or somewhere before the animation starts. by default, it takes the anchorPoint as (0.5,0.5) and hence you see the rotation from the center.
_viewToRotate.layer.anchorPoint = CGPointMake(0.5, 1.0);
And then call the basic animation method.
Read more on http://ronnqvi.st/about-the-anchorpoint/
While you change the anchor point, it moves the layer's position.
to reposition it, use the following
-(void)setNewAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}

Related

How To Get A Perfect Position Of Rotating View?

I am have one view and I am rotating that view using CABasicAnimation.
Now my problem is that how I get a perfect position of that view while rotating. I have tried many type of codes but i can't got a perfect position during rotation of that view.
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
NSNumber *currentAngle = [CircleView.layer.presentationLayer valueForKeyPath:#"transform.rotation"];
rotationAnimation.fromValue = currentAngle;
rotationAnimation.toValue = #(50*M_PI);
rotationAnimation.duration = 50.0f; // this might be too fast
rotationAnimation.repeatCount = HUGE_VALF; // HUGE_VALF is defined in math.h so import it
[CircleView.layer addAnimation:rotationAnimation forKey:#"rotationAnimationleft"];
I am using this code for rotating my view.
I have also attached a one photo of my view.
Thank you In Advance Please Help If You Know.
To get view's parameters during the animation you should use view.layer.presentationLayer
ADDED:
In order to get the coordinate of top left corner of the view, use the following code:
- (CGPoint)currentTopLeftPointOfTheView:(UIView *)view
{
CGRect rect = view.bounds;
rect.origin.x = view.center.x - 0.5 * CGRectGetWidth(rect);
rect.origin.y = view.center.y - 0.5 * CGRectGetHeight(rect);
CGPoint originalTopLeftCorner = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
CGPoint rectCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
CGFloat radius = sqrt(pow(rectCenter.x - originalTopLeftCorner.x, 2.0) + pow(rectCenter.y - originalTopLeftCorner.y, 2.0));
CGFloat originalAngle = M_PI - acos((rectCenter.x - originalTopLeftCorner.x) / radius);
CATransform3D currentTransform = ((CALayer *)view.layer.presentationLayer).transform;
CGFloat rotation = atan2(currentTransform.m12, currentTransform.m11);
CGFloat resultAngle = originalAngle - rotation;
CGPoint currentTopLeftCorner = CGPointMake(round(rectCenter.x + cos(resultAngle) * radius), round(rectCenter.y - sin(resultAngle) * radius));
return currentTopLeftCorner;
}
Resulting CGPoint will be the coordinate of the top left corner of your (rotated) view relative to its superview.
Set the position of the layer that you what
[layer setPosition:endpoint];
Or you may also refer this CABasicAnimation rotate returns to original position

CATransform3DMakeRotation Setting AnchorPoint and position. iOS7 View position mistake

CATransform3DMakeRotation Setting AnchorPoint and position
iOS7 View position mistake...
but iOS8 and iOS9 dont have this problem..
why?
-(void)viewDidAppear:(BOOL)animated
{
[self setAnchorPoint:CGPointMake(0.5, 1) forView:self.chieldImageView];
}
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}
This is probably due to the use of auto layout, on iOS8 and major they fixed it.
There are not so many solution, one is to keep the view you are transforming inside a container view. You use constraints on the container view to position it and in the contained (need to be transformed view) you just add it as a subview by keeping the -translatesAutoresizingMaskIntoConstraints to YES.
Check on Matt book.

iOS CGAffineTransformScale keep left anchor

I am using CGAffineTransformScale to scale down my UITableView, it is scaling it down correctly but i can't seem to set the anchor point correctly.
self.myTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8);
If I don't set the anchor point it scales it down from the center but as my requirement I need to keep the left top corner point fixed. For this I've used this
self.myTableView.layer.anchorPoint = CGPointMake(0, 0);
self.myTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8);
But this doesn't set the anchor correctly.. One more thing I haven't used AutoLayout
Please can anyone help me out on this…? thanks in advance..
Try this
[self setAnchorPoint:CGPointMake(0, 0.5) forView:recognizer.view]; // for left anchor point
and here setAnchorPoint
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}

Calculate rotation angle for anchor point

I got stuck with a problem where I need to reposition views to predefined locations.
All views have a UIPanGestureRecognizer and a UIRotationGestureRecognizer and are positioned/rotated inside the controllers view. Upon a certain event the views should move to a new position with a new rotation angle.
Everything works fine but a soon as one of the gesture recognizer was active and thus the anchorPoint has changed repositioning/rotation fails.
Here is my method I try to use to take the shift in the anchorPoint into account.
- (CGPoint)centerPointWithInVisibleAreaForPoint:(CGPoint)point
{
CGPoint anchorP = self.layer.anchorPoint;
anchorP.x -= 0.5;
anchorP.y -= 0.5;
CGRect rect = self.bounds;
CGFloat widthDelta = CGRectGetWidth(self.bounds) * anchorP.x;
CGFloat heightDelta = CGRectGetHeight(self.bounds) * anchorP.y;
CGPoint newCenter = CGPointMake(point.x + widthDelta, point.y + heightDelta);
return newCenter;
}
The controller asks for the corrected center point and sets the center value of the view. Afterwards the rotation transform is set using CGAffineTransformConcat(view.transform, CGAffineTransformMakeRotation(differenceAngle)).
I think the problem is caused by the fact that the predefined target angle is based on a rotation around the center which is obviously different when rotated around a different anchorPoint, but I don't know how to compensate for that.
The only solution I found (and it is after all the most easiest one) is to reset the anchorPoint to 0.5/0.5 and correct the position accordingly.
- (void)resetAnchorPoint
{
if (!CGPointEqualToPoint(self.layer.anchorPoint, CGPointMake(0.5, 0.5))) {
CGFloat width = CGRectGetWidth(self.bounds);
CGFloat height = CGRectGetHeight(self.bounds);
CGPoint newPoint = CGPointMake(width * 0.5, height * 0.5);
CGPoint oldPoint = CGPointMake(width * self.layer.anchorPoint.x, height * self.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, self.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, self.transform);
CGPoint position = self.layer.position;
position.x += (newPoint.x - oldPoint.x);
position.y += (newPoint.y - oldPoint.y);
[CATransaction setDisableActions:YES];
self.layer.position = position;
self.layer.anchorPoint = CGPointMake(0.5, 0.5);
[CATransaction setDisableActions:NO];
}
}

Animating a UIView to a value without a specified duration

I want to animate a sub-classed UIView using Core Animation. The oddity in my case is that I want the animation to run a fixed amount every frame and not by the duration. So animating from 100 -> 200 should take longer than 100 -> 50, but the "velocity" of the view should be constant. My code currently looks like this:
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
animation.duration = 0.4;
[[self layer] addAnimation:animation forKey:#"transform"];
self.transform = CGAffineTransformMakeTranslation(0, 100);
It this possible? How would it be done?
Why not just compute the desired time from the desired movement? Something like:
CGFloat distanceToTimeFactor = 0.1;
CGPoint current = self.center;
CGPoint new = CGPointMake(100,100);
CGFloat xDist = (new.x - current.x);
CGFloat yDist = (new.y - current.y);
CGFloat distance = sqrt((xDist * xDist) + (yDist * yDist));
CGFloat duration = distance * distanceToTimeFactor;
And then animate with that duration.

Resources