I have a simple UILabel that starts rotating when you do a long-press on it. I'm achieving this successfully using the following code:
-(IBAction)longPressEffect:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
UIViewAnimationOptions animationOptions = UIViewAnimationCurveLinear | UIViewAnimationOptionRepeat;
[UIView animateWithDuration:0.4 delay:0.0 options:animationOptions animations:^ {
labelObject.transform = CGAffineTransformMakeRotation(DegreesToRadians(angle));
} completion:nil];
angle = angle + 180;
}
else if (sender.state == UIGestureRecognizerStateEnded) {
;
}
}
The user can stop this animation at any point by simply double-clicking on the Label. Here's the code for that:
-(IBAction)doubleTapEffect:(UITapGestureRecognizer *)sender {
[labelObject.layer removeAllAnimations];
labelObject.transform = CGAffineTransformMakeRotation(DegreesToRadians(0));
}
The problem is that the next time you do long-press on the Label - it doesn't respond. The rotation animation doesn't start up again. You to have to click on it yet one more time to get it going again.
So the pattern is:
1) Long press - animation starts
2) Double click - animation stops
3) Long Press - nothing happens
4) Long press yet again - animation starts up again.
How do I fix this?
It is animating - it just doesn't look as if it is, because you are adding 180 to the angle all the time.
Assuming that angle is 180 to start with, you animate from 0 to 180 then 180 around to 180 then 180 around to 180. Then angle is + 180, which puts angle at 360, and the initial animation is 360, which is interpreted as 0, so the label animates from 0 to 0.
Change
angle = angle + 180;
to
angle = angle + 30;
and you should see the rotation happening.
This link might help you do a continuous rotation, if that's what you're trying to do:
How can I rotate a UIButton continuously and be able to stop it?
Related
I need to make run this animation from left to right continuously. Now Is working, but show 1 time only (when the game is loaded). I want to make this animation run continously, left to right continuously. Timer and speed is already working. Here my current code:
- (void)airplane1Code {
airplane1.center = CGPointMake(airplane1.center.x + 10, airplane1.center.y);
}
Any suggestion? Thanks
You can create a UIView animation with the UIViewAnimationOptionRepeat
airplane1.center = CGPointMake(startX, startY);
[UIView animateWithDuration:10.0 //10seconds
delay: 0
options: UIViewAnimationOptionRepeat
animations:^{
airplane1.center = CGPointMake(endX, endY);
}
completion:nil];
That will make it do the same animation from start to end over and over. In order to stop the animation, call
[airplane1.layer removeAllAnimations];
If you want the airplane to show up on the start side after it disappears from the end side, just reset the center off screen on the start side once it passes the window's frame. If you want another plane to show up and start flying after that one has left, then add another plane object and move them at the same time.
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
-(void) airplane1Code{
airplane1.center = CGPointMake(airplane1.center.x + 10, airplane1.center.y);
if(airplane1.center > screenWidth + halfTheImageSize)
// if the plane is completely off the screen, move the image to other side
// and keep running this method with your loop
airplane1.center = CGPointMake(0 - halfTheImageSize, airplane1.center.y);
}
I'm simulating some effects, like leafs falling, snow and rain.
My first call was to use CAEmitterLayer, that works very well, but i need to render the layer in context to save as an image, and that seens impossible or, at least, very complicated.
So i am working with some view animations. I need to continuously animate my imageViews so it can fall through screen and reappear on top of it, each one with diffenrent speed.
So i relocate each imageView on screen with animateWithDuration and when animation is done i call the method that do that recursively from completion block so the imageview can make it's way to the end of screen. Once an imageView reachs the end of screen i relocate it on top.
The problem is when animation is over my imageView stops a little bit until the completion block calls the method recursively, i want it to be continuously.
My code generates random position for each imageView, and my animation duration is very short so i can always update imageView's location in case the user tap the button to save the view as an image.
Anyway, here is my code:
- (void)effectOnObject:(UIImageView *)object{
NSInteger initialX;
NSInteger initialy;
CGFloat duration;
//the object have reached the end of screen
if (object.frame.origin.y >= self.frame.size.height) {
//generate random position to relocate the object on x axis
initialX = arc4random() % 321;
//generate random position to relocate the object on y axis (little bit above top of screen)
initialy = ((NSInteger)-object.frame.size.height) - arc4random() % 11;
//duration 0 so the object can be replaced without animation
duration = 0.0;
}
else{
initialX = object.frame.origin.x;
//this change the speed of object
initialy = object.frame.origin.y + 10
//setted duration to short time
duration = 0.01;
}
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
[object setFrame:CGRectMake(initialX, initialy, object.frame.size.width, object.frame.size.height)];
}
completion:^(BOOL completed){
//recursively call
[self effectOnObject:object];
}];
}
- (void)startEffect{
//initiate effect on each imageView
for (UIImageView *object in self.subviews) {
[self effectOnObject:object];
}
}
How can i make this animation repeatedly and continuously, without the gap when the method is called recursively from completion block and the animation restarts?
You don't need to do the animation with 0 duration when the object reaches the end of the screen. Just test for this in your completion block and relocate the view before calling recursively. Also, a duration of 0.01 seems a bit extreme (100 frames per second). Perhaps a more reasonable value like 0.1 would help.
Something like this:
- (void)effectOnObject:(UIImageView *)object{
//setted duration to short time
CGFloat duration = 0.1;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
NSInteger initialX = object.frame.origin.x;
//this change the speed of object
NSInteger initialy = object.frame.origin.y + 10;
[object setFrame:CGRectMake(initialX, initialy, object.frame.size.width, object.frame.size.height)];
}
completion:^(BOOL completed){
NSInteger initialX = arc4random() % 321;
//generate random position to relocate the object on y axis (little bit above top of screen)
NSInteger initialy = ((NSInteger)-object.frame.size.height) - arc4random() % 11;
[object setFrame:CGRectMake(initialX, initialy, object.frame.size.width, object.frame.size.height)];
//recursively call
[self effectOnObject:object];
}];
}
From what I read briefly you should check out CAReplicatorLayer. It is perfect for repeating stuff! Only issue I can think of is that the transform and values have to be incremental...
i have simple UIView animation block which animates the origin of 2 views. I have a Button on a special position placed on a mapview view. so when i'd like to animate the center of the map and move the pin with the map, the map moves faster than the button. Is there a way, to speed up the animation of the button or to slow down the animation of the map? At the moment it looks like the map moves and the button jumps to his end position.
CGPoint newCenter = mapView.center;
newCenter.x -= 1;
newCenter.y -= (button.frame.size.height/2)
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
CGPoint screenPoint = fakePin.frame.origin;
screenPoint.x -= 5;
screenPoint.y += button.frame.size.height-4;
mapView.mapCoord = [mapView.map convertPoint:screenPoint toCoordinateFromView:self.view];
self.mapView.map.centerCoordinate = mapView.mapCoord;
[button setCenter:newCenter];
}];
Any Ideas?
Why not show the button as an annotation? Then it would move along the map.
Still, try to animate the property frame on the button instead of center. You'll need to do the calculations on your own but I think that may be the problem.
i just figured out, that the Problem was that my setCenter: was called without animating, somehow it worked with the Google Maps in ios5 (animating itself but not in ios6=
No it works!!
I am simply trying to spin a UIImageView 360 degrees clockwise using this:
#define DEGREES_TO_RADIANS(angle) (angle / 180.0 * M_PI)
and this
imageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(360));
However imageView doesn't spin at all even those it is being called. Is there something wrong I am doing? I do not want to use CAAnimations so please don't recommend me to do so.
Thanks!
The problem is that Core Animation will apply animations by finding the most direct route from the current state to the new state. Rotation by 0 degrees is the same as rotation by 360 degrees so the most direct route to your final transform is to do absolutely nothing.
Two steps of 180 degrees would be problematic because there are two equally direct routes from 0 to 180 degrees and Core Animation could pick either. So you probably need to break your animation into three steps. Do the first with a UIViewAnimationOptionCurveEaseIn, the second with UIViewAnimationOptionCurveLinear and the final with UIViewAnimationOptionCurveEaseOut.
Perhaps because the transform isn't happening over a duration of time. It seems to me that as long as it isn't perceivable over time you may need to perform the transform or sequence of transforms over a fraction of time.
Here is the code inspired by Tommy's answer.
I used
NSInteger step;
to keep track of current rotated degree of the image view.
- (void)startAnimation
{
[UIView animateWithDuration:0.5f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^{
imageView.transform = CGAffineTransformMakeRotation(120 * step / 180.0f * M_PI);
}
completion:^(BOOL finished) {
step++;
// rotation completed, reset for the next round
if (step == 4){
step = 1;
}
// perform the next rotation animation
[self startAnimation];
}];
}
I have a problem with a UIView-subclass object that I am rotating using Core Animation in response to a UISwipeGesture.
To describe the context: I have a round dial that I have drawn in CG and added to the main view as a subview.
In response to swipe gestures I am instructing it to rotate 15 degrees in either direction dependent on whether it;s a left or right swipe.
The problem that it will only rotate each way once. Subsequent gestures are recognised (evident from other actions that are triggered) but the animation does not repeat. I can go left once then right once. But trying to go in either direction multiple times doesn't work. Here's the relevant code, let me know your thoughts...
- (IBAction)handleLeftSwipe:(UISwipeGestureRecognizer *)sender
{
if ([control1 pointInside:[sender locationInView:control1] withEvent:nil])
{
//updates the display value
testDisplay.displayValue = testDisplay.displayValue + 0.1;
[testDisplay setNeedsDisplay];
//rotates the dial
[UIView animateWithDuration:0.25 animations:^{
CGAffineTransform xform = CGAffineTransformMakeRotation(radians(+15));
control1.transform = xform;
[control1 setNeedsDisplay];
}];
}
CGAffineTransform xform = CGAffineTransformMakeRotation(radians(+15));
Do you keep a total of how far the rotation is. CGAffineTransformMakeRotation are not additive. Only the most recent is used. So you are setting it to 15 each time, not 15 more each time.
Here's a super simple example of rotating a view cumulatively. This rotates the view by 180 degrees each button press.
- (IBAction) onRotateMyView: (id) sender
{
[UIView animateWithDuration:0.3 animations:^{
myView.transform = CGAffineTransformMakeRotation(M_PI/2*rotationCounter);
} completion:^(BOOL finished){
//No nothing
}];
++rotationCounter;
}