CATransform3DMakeRotation Setting AnchorPoint and position. iOS7 View position mistake - ios

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.

Related

CABasicAnimation rotate view on x axis

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;
}

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];
}
}

Animate the height of UILabel to 0

I've got a UILabel and what I want to do is to smoothly change it's height to 0.
CGRect newFrame = self.label1.frame;
newFrame.size.height = 0;
[UIView animateWithDuration:1.0 animations:^{
self.label1.frame = newFrame;
}];
The problem is that the animation is jamming does some wierd things. I guess that the label is trying to resize and reposition it's text and that is why it does not work. I've tried like every possible combination of properties on the label but without success.
You could enclose your UILabel into another UIView, set the enclosing UIView autoresizesSubviews' property to NO and clipToBounds to YES, and then animate the height of the enclosing UIView...
Try with a transform. I dug this code out for you:
//[self setAnchorPoint:CGPointMake(0.5, 1.0) forView:self.label];
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationCurveEaseInOut
animations:^{
//Scale the height to close to zero
//0.00001, because 0.0 behaves strange
self.label.transform = CGAffineTransformMakeScale(1, 0.00001);
}
completion:^(BOOL finished) {
self.label.hidden = YES;
}];
This will shrink it into the middle. If you want it to shrink to the top or bottom, you will need to set an anchor point. I also have some code for this too:
- (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;
}

How to rotate an layer at a specific anchor point without a skip?

I want to rotate a layer with an image at the top left corner, and not the center. According to the docs I set the anchorPoint property to [0, 1]. The view rotates in my example by 50°, but before it starts to animate, the view jumps to another point at the screen.
self.shakeTag.layer.anchorPoint = CGPointMake(0.0f, 1.0f);
[UIView beginAnimations:#"rotate" context:nil];
[self.shakeTag.layer setTransform:
CATransform3DRotate(CATransform3DIdentity,
radians(50.0), 0.0f, 0.0f, 1.0f)];
[UIView commitAnimations];
radians() is defined like this:
static inline double radians (double degrees) {return degrees * M_PI/180;}
When I use an image that is 4 times the size and has a lot of transparent pixels, I can rotate it at the default anchor point [0.5, 0.5], but I don’t want to waste the space for invisible pixels. Any ideas how I can prevent the layer from jumping before the rotation takes place?
Changing the anchor point affects the positioning of your view. You'll need to change the view's position if you change the anchor point and if you want to keep your view where it currently is. Use something like this (taken from here: Layer Position jumps at start of (Core) Animation) to set your anchor point and compensate position changes:
-(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;
}
Also see here for more details: Changing my CALayer's anchorPoint moves the view

Resources