I making an app which sets the sleep timer with a clock .Basically it is clock which has a single hand which user can move to set his sleep time .I tried to rotate the image with uitouch but it rotates from middle but i want it to rotate from the tip.Secondly i want that the image only rotates when user is touching the tip of the image but in my project the image is also rotating when use touches any part of the screen.Also i want to rotate the image in both directions but in my project it moves only clockwise due to this method
image.transform = CGAffineTransformRotate(image.transform, degreesToRadians(1));
Can anybody give me hints or solutions about how can it be done?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//
touch = [[event allTouches] anyObject];
touchLocation = [touch locationInView:touch.view];
NSLog(#"began");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// get touch event
[image.layer setAnchorPoint:CGPointMake(0.0,0.0)];
if ([touch view] == image) {
image.transform = CGAffineTransformRotate(image.transform, degreesToRadians(1));
//image.center = touchLocation;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"end");
}
In detail, you can custom a rotateView,then:
1: In the delegate method of "touchesBegan", get initialPoint of finger and initialAngle.
2: During "touchesMoved",get the newPoint of finger:
CGPoint newPoint = [[touches anyObject] locationInView:self];
[self pushTouchPoint:thePoint date:[NSDate date]];
double angleDif = [self angleForPoint:newPoint] - [self angleForPoint:initialPoint];
self.angle = initialAngle + angleDif;
[[imageView layer] setTransform:CATransform3DMakeRotation(angle, 0, 0, 1)];
3: At last, in "touchesEnded" you can calculate final AngularVelocity.
If anything being confused, for more detail, you can write back.
To rotate it the other way you just use:
image.transform = CGAffineTransformRotate(image.transform, degreesToRadians(1));
And to rotate form the tip you should use setAnchorPoint (like you used in your code, but i think you should do: [image setAnchorPoint]).
more on the subject: setAnchorPoint for UIImage?
I tried to rotate the image with uitouch but it rotates from middle but i want it to rotate from the tip
I dont know any way in SDK to rotate an element on its extreme end. If you want to have that effect take the clock handle image you have twice in length with half portion transparent. It is not a direct solution, but a workaround.
Also i want to rotate the image in both directions but in my project it moves only clockwise due to this method
As per iOS developer documentation, a positive angle value specifies counterclockwise rotation and a negative value specifies clockwise rotation.
Related
When creating a new UIView or panning/swiping a view to a new position, whats the proper way of setting the new position and size. Currently, to move views resulting from a pan/swipe action, I'm using ratios based on the original position of the view that I'm moving and its relation to other views and items (navigation bar).
When moving a view due to a swipe I do the following:
CGFloat swipeUpDelta = -1 *(self.view.bounds.size.height - (self.view.bounds.size.height - recordView.frame.origin.y) - (self.navigationController.navigationBar.bounds.size.height + ([UIApplication sharedApplication].statusBarFrame.size.height)));
[UIView animateWithDuration:.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
recordView.frame = CGRectOffset(recordView.frame, 0, swipeUpDelta);
} completion:nil];
Or creating a view that renders a sineWave across my viewcontroller:
self.sineWave = [[OSDrawWave alloc] initWithFrame:CGRectMake(-1*self.view.bounds.size.width, (.75*self.view.bounds.size.height), 2*self.view.bounds.size.width, .3125*(2*self.view.bounds.size.width))];
Everything works fine, but I wanted to know if there is a better way of doing these things.
I'm not sure I understand the question. initWithFrame: or myView.frame is considered the correct way of positioning a UIView. Using animateWithDuration: with a new frame size is also pretty standard.
I'm unsure of what you mean as well. When you move a UIView you can move the view a variety of ways, it depends on your code and what you want out of it. The below is a valid example of code to move a CALayer inside of a UIView to follow touch positions. You can use this, you can animate your view, you can use explicit animations when changing the position of the layer or center of the view (By default iOS animates any changed property values of a CALayer... you can ride off of this and enable this feature for UIViews if you please). If you're moving a UIView, it's a good idea to move the view according to the center property. This is pretty much how SpriteKit works and any high functioning animation engine (avoid always resetting the frame... especially if you don't need to).
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
boxLayer.position = p;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
[CATransaction begin];
[CATransaction setDisableActions:YES];
boxLayer.position = p;
[CATransaction commit];
}
As a note, note the comment in the following line of code
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
/*UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self]; // this causes the animations to appear sluggish as there is a consistant change in destination location. The above code corrects this.
[boxLayer setPosition:p];*/
This is valid, and may provide the results you want... it all depends on what you want.
I want to rotate a gun based on the user dragging their finger on the screen. I figure i will need my cartesian points in polar coordinates and that i will need a long press gesture which is both things that i have. I am just wondering how i would go about programming this? sorry i'm really new to sprite kit i have read all of apple's documentation and i'm having a hard time finding this. My anchor point is 0,0.
-(void)shootBullets:(UILongPressGestureRecognizer *) gestureRecognizer
{
double radius;
double angle;
SKSpriteNode *gun = [self newGun];
}
i figured out how to get the angle but now my zrotation wont work. Like i nslog and the angles are right but when i click gun.zrotation and i tap nothing happens? please help i'm getting uber mad.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
SKSpriteNode *gun = [self newGun];
self.gunRotation = atanf(location.y/location.x)/0.0174532925;
gun.zRotation = self.gunRotation;
NSLog(#"%f",gun.zRotation);
}
This is a very old question, but here is what I did - hopefully it will help someone out there:
#import "MyScene.h"
#define SK_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) // PI / 180
Then add this:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint positionInScene = [touch locationInNode:self];
float deltaX = positionInScene.x - gun.position.x;
float deltaY = positionInScene.y - gun.position.y;
float angle = atan2f(deltaY, deltaX);
gun.zRotation = angle - SK_DEGREES_TO_RADIANS(90.0f);
}
}
Check out the answers I got to this question about how to implement a rotary knob, people have already figured out all the geometry, all you need to do is implement a transparent rotary knob, get its angle and pass it to your sprite kit object, using action rotate
I have a circular UIBezierPath. I use the path to draw a circle on my view to create an outline of a 24 hr clock. I have a UIButton whose position depends on the current time. The button acts like an Hour hand. I want the users to be able to move the UIButton along the circular path. I call it "visit the future/past" feature. How do I restrict the buttons movement to the path I have?
Override touchesBegan: and touchesMoved: methods in your view
- (void)touchesBegan: (NSSet *)touches withEvent:(UIEvent *)event
{
if([[event touchesForView:button] count])
{
//User is trying to move the button set a variable to indicate this.
}
}
- (void)touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint *point = [[event anyObject] locationInView:self];
/*Compare x and y coordinates with the centre property of the button
If x or y are greater set center of button to next point in circle or previous
point if any of them are lesser.*/
}
Note that you will have to save all points in your circle in an array before attempting this or you will have to calculate the points on the circumference of the circle by knowing the radius.
The easiest way is in touchesMoved, you can check to ignore touch which is not in your circle view by using:
CGPoint point = [touch locationInView:circleView];
if (![circleView pointInside:point withEvent:event]) {
return;
}
In Xcode, how would I make an image appear in a certain place on the iPhone screen by touching the place where I would want it to appear? The method that I'm currently trying to use is by getting the coordinates of the point and then trying to get a png file to appear at that point. Here is what I have so far for code:
- (void) touchesBegan:(NSSet *)touches
withEvent:(UIEvent *)event {
UITouch *theTouch = [touches anyObject];
startPoint = [theTouch locationInView:self.view];
CGFloat x = startPoint.x;
CGFloat y = startPoint.y;
But now that I have the points, I'm not sure how to get an image to appear there or if there might be a more efficient method. Any ideas?
You can use [-UIImage drawAtPoint:].
After getting x,y coordinates of a touch event, set center point of your UIImageView to it.
UIImageView *myImage = ...
CGPoint myPoint = CGPointMake(x_touch, y_touch);
[myImage setCenter:myPoint];
you can also animate this change by using animate block on the image view like so:
nsTimerInterval myAnimationDuration = 1.0;
[UIView animateWithDuration:myAnimationDuration animations:^{
[myImage setCenter:myPoint];
}
completion:^(BOOL finished){
//handle completion tasks
}];
I am developing a simple animation where an UIImageView moves along a UIBezierPath, now I want to provide user interation to the moving UIImageView so that user can guide the UIImageView by touching the UIImageView and drag the UIImageview around the screen.
Change the frame of the position of the image view in touchesMoved:withEvent:.
Edit: Some code
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch.view isEqual: self.view] || touch.view == nil) {
return;
}
lastLocation = [touch locationInView: self.view];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch.view isEqual: self.view]) {
return;
}
CGPoint location = [touch locationInView: self.view];
CGFloat xDisplacement = location.x - lastLocation.x;
CGFloat yDisplacement = location.y - lastLocation.y;
CGRect frame = touch.view.frame;
frame.origin.x += xDisplacement;
frame.origin.y += yDisplacement;
touch.view.frame = frame;
lastLocation=location;
}
You should also implement touchesEnded:withEvent: and touchesCanceled:withEvent:.
So you want the user to be able to touch an image in the middle of a keyframe animation along a curved path, and drag it to a different location? What do you want to happen to the animation at that point?
You have multiple challenges.
First is detecting the touch on the object while a keyframe animation is "in flight".
To do that, you want to use the parent view's layer's presentation layer's hitTest method.
A layer's presentation layer represents the state of the layer at any given instant, including animations.
Once you detect touches on your view, you will need to get the image's current location from the presentation layer, stop the animation, and take over with a touchesMoved/touchesDragged based animation.
I wrote a demo application that shows how to detect touches on an object that's being animated along a path. That would be a good starting point.
Take a look here:
Core Animation demo including detecting touches on a view while an animation is "in flight".
Easiest way would be subclassing UIImageView.
For simple dragging take a look at the code here (code borrowed from user MHC):
UIView drag (image and text)
Since you want to drag along Bezier path you'll have to modify touchesMoved:
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
//here you have location of user's finger
CGPoint location = [aTouch locationInView:self.superview];
[UIView beginAnimations:#"Dragging A DraggableView" context:nil];
//commented code would simply move the view to that point
//self.frame = CGRectMake(location.x-offset.x,location.y-offset.y,self.frame.size.width, self.frame.size.height);
//you need some kind of a function
CGPoint calculatedPosition = [self calculatePositonForPoint: location];
self.frame = CGRectMake(calculatedPosition.x,calculatedPosition.y,self.frame.size.width, self.frame.size.height);
[UIView commitAnimations];
}
What exactly you would like to do in -(CGPoint) calculatePositionForPoint:(CGPoint)location
is up to you. You could for example calculate point in Bezier path that is the closest to location. For simple test you can do:
-(CGPoint) calculatePositionForPoint:(CGPoint)location {
return location;
}
Along the way you're gonna have to decide what happens if user wonders off to far from your
precalculated Bezier path.