Draw a line with finger and make an UIView follow it - objective-c

Ok, I have a View, and first, I want that as soon as the user touches the View (a rectangle in this case) and starts dragging around a line should be drawn, following the path of the finger. Later, when I call a specific method, I want the View to follow the line and of course the line to disappear.
My thought for drawing the line:
Add a UIPanGestureRecognizer to the view, and then AddLineToContext, then draw it.
Use the touchesBegan, etc. methods. But later, I have multiple Views in there, and I need to find out which one the user touched. (have fun, there will be between 1 and 15...)
And I still have no idea about the other thing.

For the purpose of drawing the path, you are on the right track. I would use the gesture recognizer out of the two options you have.
To make the rectangle follow the path the easiest method I can think of is to keep an array of x and y for each point you are passing trough (don't forget to remove the consecutive duplicates).
So, now that you have an array of points that describe the shape of the path you can start a timer, or better use CADisplayLink, that will set the position of the rectangle to each of the points in the array. This will make the rectangle follow the path.
If you want the rectangle to follow the orientation as well, you will need to use vectors to describe the direction in which the rectangle should head.
First you need calculate the distance between the rectangle's position and the point in which it should go next using:
then, when you know the distance you can use arcsine to get you the direction angle. Then simply rotate the rect by that value.
Be careful at angle representation (pi vs degrees) and at the coordinates system.

Related

How to get the selected BezierPath on MouseDown or MouseDragged or MouseUp?

I am drawing multiple NSBezierpaths, then I am trying to erase them so on MouseDown event How can I identify which bezierpath was hit?
My bezierpath is custom subclass of NSObject.
Well, get the mouse click point from the NSEvent in your mouseDown: method with -locationInWindow, convert the click point from window coordinates to your view's coordinates with -convertPoint:fromView:, loop through the NSBezierPath objects that you're drawing, from top to bottom, and call -containsPoint: to test for a hit on each path. That works well if your bezier paths are closed, filled paths. If they are unclosed or stroked paths, you will need to drop down a level and use CGPathCreateCopyByStrokingPath(), and perhaps also CGPathCreateCopyByDashingPath(), to get the fill-style bezier path that describes the outline of the area that is filled when your original path is stroked (see How to get the path Quartz is using to stroke a NSBezierPath).
However, I'm not sure what you mean by "My bezierpath is custom subclass of NSObject"; if you are doing additional complicated things beyond just using NSBezierPath, then you will need to describe what you're doing (and why), and post code for it.

UIPanGesture ignore outside of of mask with CAShapeLayer

I ran into this problem, I have 27 UIView's laying on top of each other, with exactly the same frame, visually they are laying next to each other, visual respresentation:
So the frame for all of them is the big yellow square. They get masked using a CAShapeLayer (the colored triangles). I add a UIPanGesture to all of them (not sure this is the best way to do it), and I want to determine on which one the user panned. Of course (obviously), only the top one is accessible, and always is the view in the UIPanGesture. How do I determine on which one of the UIView's the finger was panning? A for loop seems expensive too.. Or am I approaching this wrong?
This is the code for creating all of them and handling the pan gesture:
Gist to code
Sender to tag is always 27 though, of course... No clue how to solve this one guys! Anyone a clue?
Figure it out!
I moved everything into a custom UIView, where in draw rect I draw all the triangles using CAShapeLayers, add a UIPanGesture to it self, and in the gesture handler you can check in a for loop with CGPathContainsPoint if that layer contains the gesture point!
Solution code snippet
Hope this helps someone!

How to move uiview on circle trajectory?

Is there any way to animate uiview moving with cicle trajectory?
You will have to create a circular path and animate your view on the path. You can use UIBezierPath to create a circular path . Here is an example that does what exactly you want.
There are a couple of options. Probably the simplest is to place your view on a parent view, and then animate rotating the parent view around its Z axis.
I guess you could also build a transform that shifts your view, then rotates it, and animate the transform to different rotation values. I'd have to tinker with that. I know the first approach would be quick and easy to set up.
As the other poster said, you could also create a keyframe animation that uses a CGPath to animate your view along a curve that approximated the shape of a circle, but that would be much more work.

cache drawing in a uiview

I have a UIView that allows the user to draw a line (myLine) on the screen. This UIView is directly above another UIView that has several shapes drawn with CGPaths. When the user taps on one of these shapes I need to erase any portion of myLine that is above one of these other shapes as if I was erasing the pixels with an eraser.
What would be the best way to approach this?
I need the light blue part of the line to be erased leaving the dark blue portion
1) (current approach partially works) I'm able to use the path shape from the bottom view as a mask in the top view but it is only masking the UIView. If I later need to change the mask location the vector strokes are still there. (I know this is because all off my lines are being redrawn in the drawrect of the view)
2) After I draw each line should I somehow cache the drawing as an image and THEN
slice out the parts inside the triangle?
3)Is there a better approach to this?
This link provided the answer:
Building a Simple Drawing App
I cache the drawing to a bitmap context and then clip out
the unneeded parts of the bitmap.

Difficulty finding correct anchor point for rotation transforms

I'm animating a button's position, rotating it around a circle. This creates a UISwitch-like behavior, except it is a lot more fancy. The button rotates, but it ends up off the desired position by about 0.25 radians. I'm trying to figure out where to put the anchor point to make the button rotate in a perfect circle around its origin.
Here's the code that I use to make the button "orbit" with a 120 pixel radius from the original location.
float offsetX=120;
float offsetY=0;
enableDisableButton.layer.anchorPoint =
CGPointMake(offsetX/enableDisableButton.frame.size.width,
offsetY/enableDisableButton.frame.size.height);
I use the following method to do the calculations. Passing an argument of 90 for degrees, I expect to see the button start at a 180˚ position and move to 90˚, still 120 pixels away from its origin
-(CGAffineTransform)calculateLabelPositionFromFixedPointWithOffsetClockwiseInDegrees:(float)degrees
{
float rotation = degrees*(2*M_PI/360);
CGAffineTransform transform24 = CGAffineTransformMakeRotation(rotation);
NSLog(#"rotation: %f", rotation);
return transform24;
}
This little 0.25 radian or so offset means that I need to visually confirm the location of each button and cannot easily adjust its location programmatically. Any help in determining the correct way to rotate the button is appreciated.
I tried other ways to rotate objects. For example, I have an arrow
<--------x, and I would like to rotate this arrow in a circle around x . What is the correct anchor point placement for this operation? Is it [1, 0.5]?
An easier way to do this kind of rotations is to put an object within a symmetric UIView, center it at the desired point of rotation and assign a rotation transform. This works, but requires the view to be twice as big:
Y----x----Y < this rotates Y around center point X without any anchor point adjustments. this is a very useful method to rotate arrows within analog gauges and such.
"An easier way to do this kind of rotations is to put an object within a symmetric UIView, center it at the desired point of rotation and assign a rotation transform." this way is fine.
The anchor point of your enableDisableButton in the example would be
CGPointMake(offsetX/enableDisableButton.frame.size.width, 0)
i.e. not vertically centered in your button. Rotating around the anchor point would result in the button being offset to the top or bottom of the desired position. The transform looks alright, so I think it is just the anchor point. It should be:
CGPointMake(offsetX/enableDisableButton.frame.size.width, 0.5f)