How to slow the rotation of an object? - ios

I have an issue.
i have this code:
if(CGRectContainsPoint(compassTarcsa.frame, curLoc))
{
compassTarcsaTouch = YES;
float fromAngle = atan2( compassFirstLoc.y-compassTarcsa.center.y,compassFirstLoc.x-compassTarcsa.center.x );
float toAngle = atan2( curLoc.y-compassTarcsa.center.y,curLoc.x-compassTarcsa.center.x );
newAngle = (angle + (toAngle - fromAngle));
iranyFok = (newAngle / (M_PI / 180.0f)) ;
if (iranyFok < 0.0f) {
iranyFok += 360.0f;
}
iranyFok = 360-(fmodf(( 360 + iranyFok ), 360));
CGAffineTransform cgaRotate = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(- iranyFok));
compassTarcsa.transform = cgaRotate;
repcsi.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(iranyFok));
This rotates a compass from 0 to to 360 degrees, but the rotation speed is fast for me...
Can somebody help me understand how to slow this rotate?
Thx,
Alex

Try this:
[UIView animateWithDuration:2.0 delay:0 options: UIViewAnimationOptionCurveEaseInOut
animations:^(void){
compassTarcsa.transform = cgaRotate;
} completion:NULL
];
This will wrap your transform rotation in an animation that allows you to control the rotation duration.

You should consider using rotation animation and set its duration as per your required speed if you want slow rotation of an object.
Following links may be helpful to you:
UIView Infinite 360 degree rotation animation?
http://iosdevelopertips.com/user-interface/rotate-an-image-with-animation.html

Related

Rotating Image multiple times and stopping at desired degree?

i had tried various method and couldn't figure out how to achieve this.i searched on internet a lot but can't figure out.
i have an ImageView (a wheel which spins) , i want to rotate it by 360 degree for 10 times(this is to just give user feel of fast turning wheel) , and then i want to rotate it by particular value say 90 degree( but it might be varying).
after this animation finishes i want to bring ImageView back to the initial position.
how do i achieve this ?
Thanks in advance.
well i found out how to do this.
i used below method to rotate by 360 degree for 10 times , and then rotate by particular degree.
-(void)rotate:(int)degreeToRotate
{
CGFloat radians = (M_PI/180) * degreeToRotate;
[UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations: ^{
//configuring to rotate 360 degree 10 times
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 10;
[_scoreImageView.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
} completion:^(BOOL finished) {
//rotate by particular degree
[ UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
// -radians, to ensure clockwise rotation
self.scoreImageView.transform = CGAffineTransformMakeRotation(-radians);
} completion:^(BOOL finished) {
//method call to reset image original position
[self performSelector:#selector(resetPosition) withObject:nil afterDelay:3];
}];
}];
}
below method is used to reset image to original position.
-(void)resetPosition
{
[UIView animateWithDuration:0.2 animations:^() {
self.scoreImageView.transform = CGAffineTransformIdentity;
}];
}

iOS 360 endless rotation

I've this code for endless rotating an UIImageView
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionRepeat
animations: ^{
self.spinner.transform = CGAffineTransformRotate(CGAffineTransformIdentity, -M_PI);
}
completion: ^(BOOL finished) {
}];
But the first I call this method the image, it rotate clockwise instead anti clockwise. If I re-call this method while image is rotating, it change direction and start rotate anti clockwise.
Ideas?
Use a CABasicAnimation instead since it is far more powerful. You have to call the below snippet only once and the animation will run indefinitely:
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotate.toValue = #(M_PI * 2); // use #(-M_PI * 2) for counter clockwise
rotate.duration = 0.3;
rotate.cumulative = true;
rotate.repeatCount = HUGE_VALF;
[self.spinner.layer addAnimation:rotate forKey:#"rotateAnim"];
Swift:
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.toValue = M_PI * 2
rotate.duration = 0.3
rotate.cumulative = true
rotate.repeatCount = HUGE
self.spinner.layer.addAnimation(rotate, forKey: "rotateAnim")
From the documentation:
In iOS, a positive value specifies counterclockwise rotation and a
negative value specifies clockwise rotation.
CGAffineTransformRotate(CGAffineTransformIdentity, -M_PI)
Update: M_PI is constant not effected by the negative value. Somehow -M_PI is still taken as positive at the end!!!
If you give -180 it will rotate in clockwise, and if you give 180 it will rotate anti-clockwise

Rotating iOS UILayer like a ticking clock, not smoothly in a circle

I am able to rotate an image a certain number of degrees continuously, but I want to rotate the image a tiny amount, pause, a little more, pause, etc.
The follow code does this continuously:
// rotate
CGFloat finalValue = 360 / 14.f;
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
[rotationAnimation setFromValue:[self degreesToNumber:0]];
[rotationAnimation setToValue:[self degreesToNumber:finalValue]];
[rotationAnimation setDuration:5.0];
[rotationAnimation setRemovedOnCompletion:NO];
[rotationAnimation setFillMode:kCAFillModeForwards];
[self.secondHandImageView.layer addAnimation:rotationAnimation forKey:#"rotate"];
Is there a way to wrap this in a for-loop with the number of angle changes I need and set the duration and delay of the specific animations? Nothing I have tried works. Below is what I am currently trying:
// rotate in ticks, so
NSTimeInterval delay = 0;
CGFloat currentAngle = 0;
CGFloat finalAngle = 360 / 14.f;
// angle difference
CGFloat numberOfTicks = 25.f;
CGFloat angleDelta = finalAngle / numberOfTicks;
for (NSUInteger tick = 0; tick < numberOfTicks; tick++) {
[UIView animateWithDuration:0.1 delay:delay options:UIViewAnimationOptionCurveLinear animations:^{
self.secondHandImageView.layer.transform = CATransform3DMakeRotation(0, 0, angleDelta, 1.0);
} completion:nil];
// update delay
delay += .2; // 200 milliseconds, 5 tickets every second
currentAngle += angleDelta;
}
You code is OK - except that you can't animate layers inside UIView animation blocks. Instead you can animate the view. Replace the (3D)layer transform with a (2D)view transform:
self.secondHandImageView.transform =
CGAffineTransformRotate(self.tickView.transform,angleDelta);

ios rotation animation with CGAffineTransformRotate

I want to perform some rotation animation. Right now I do it like that:
#define degreesToRadians(x) (M_PI * x / 180.0)
[self.crossButton setTransform:CGAffineTransformRotate(self.crossButton.transform, degreesToRadians(-rotationDegree))];
but when I pass for instance 360 degrees nothong happens. When I pass value above 180 it starts not wokring well. Do you know what im doing wrong?
Your problem is that 'setTransformation' works with matrix rotation. For this reason you will always get the shortest way to the end result. When you pass in a 360 degree rotation, your object will be the same after the transformation. For this reason, the transformation will just do nothing, since it is already where it is supposed to end up. For values between 180 and 360 degrees your rotation will be 'backwards', since again. The rotation uses the 'shortest' path to the end result.
You can try this code:
UIView* toRotate = VIEW_TO_ROTATE;
CGFloat degreesToRotate = DEGREES;
CGFloat animationTime = TOTAL_ANIMATION_TIME;
NSInteger intervals = ((int)degreesToRotate)/179.9;
CGFloat rest = degreesToRotate-(intervals*179.9);
CGFloat radInterval = degreesToRotate>=0?179.9:-179.9;
CGFloat radRest = (M_PI * rest / 180.0);
CGFloat intervalTime = (1-(radRest/M_PI/2))/intervals;
CGFloat restTime = (radRest/M_PI/2)/intervals;
[UIView animateKeyframesWithDuration:animationTime
delay:0.0f
options:UIViewKeyframeAnimationOptionCalculationModeLinear
animations:
^{
for (int i=0; i<intervals; i++) {
[UIView addKeyframeWithRelativeStartTime:intervalTime*i relativeDuration:intervalTime animations:^{
toRotate.transform = CGAffineTransformConcat(toRotate.transform, CGAffineTransformMakeRotation(radInterval));
}];
}
[UIView addKeyframeWithRelativeStartTime:intervalTime*intervals relativeDuration:restTime animations:^{
toRotate.transform = CGAffineTransformConcat(toRotate.transform, CGAffineTransformMakeRotation(radRest));
}];
} completion:^(BOOL finished) {
}];
Make sure to replace VIEW_TO_ROTATE,DEGREES and TOTAL_ANIMATION_TIME with the values you need!

How to scale (zoom) a UIView to a given CGPoint

I've spent a lot of time trying to find a way to use CGAffineScale to transform a view to a given point, including messing around with anchor points, moving the centre of a view before and after transforming and comprehensive Googling. I am aware this would be a lot simpler with a UIScrollview; but I know it's technically possible to do without one, and it's become a splinter in my mind.
This answer gets remarkably close to what I want to achieve, but the answer only gives details on how to zoom to a given corner (instead of a given point) by cleverly moving the centre to the corner opposite the one you want to zoom in to.
How can I modify mvds' code to scale a UIView to any given point in a UIView?
CGFloat s = 3;
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
self.view.transform = tr;
self.view.center = CGPointMake(w-w*s/2,h*s/2);
} completion:^(BOOL finished) {}];
There are 2 steps involved: First you scale up the view you want to zoom in to. Then you set the center of this blown up view such that the part you want to see ends up in the middle of the view.
You should draw this out on paper and the formulas will follow: (untested)
CGFloat s = 3;
CGPoint p = CGPointMake(100, 200);
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
self.view.transform = tr;
CGFloat cx = w/2-s*(p.x-w/2);
CGFloat cy = h/2-s*(p.y-h/2);
self.view.center = CGPointMake(cx, cy); //was: (w*s/2,h-h*s/2);
} completion:^(BOOL finished) {}];
I actually ran into this very same problem myself. To fix it, all I did was change the anchor point of the view I was scaling because CGAffineTransforms are performed on the view in relation to its anchor point, so depending on where the anchor point is, the transform will scale, translate, or rotate the view differently. Here's the basic idea:
CGPoint pointToScaleTo = CGPointMake(x, y); //Just enter the coordinates you
//want to scale your view towards
CGFloat viewWidth = self.view.bounds.size.width;
CGFloat viewHeight = self.view.bounds.size.height;
CGFloat scaleFactorX = ...;
CGFloat scaleFactorY = ...;
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scaleFactorX, scaleFactorY);
[UIView animateWithDuration:2.5f delay:0.0f options:0 animations:^{
//I divide the x and y coordinates by the view width and height
//because the anchor point coordinates are normalized to the range
//0.0-1.0.
self.view.layer.anchorPoint = CGPointMake(pointToScaleTo.x/viewWidth, pointToScaleTo.y/viewHeight);
//Now that the anchor point has been changed, apply the scale transform
self.view.layer.transform = scaleTransform;
} completion:^(BOOL finished) {}];

Resources