I have a custom shape that i want to draw using UIBezierPaths and i want to use this drawing as a CALayer inside my view. The bezier path i use works if i draw it directly onto the UIView (inside drawRect). I want to know as to how i can use the same bezier drawing and perform the drawing inside my CALayer. I would then add this layer as a sub layer inside my view!
For instance lets say I'm drawing a concentric circle with my bezier paths and i want to draw this using a CALayer, how would i go about animating custom properties of the path, like its center, radius, startAngle and endAngle?
Specifically i want to know how i should
Arrange my CALayer (initializing, drawing , upadte drawing ,etc)
How do i draw the bezier inside my CALayer?
How do i interact between the layer and the view that contains it?
Any help is appreciated!
Here's how you create & draw a UIBezierPath in a CALayer. Using a CAShapeLayer is the easiest way:
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:...];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.path = circlePath.CGPath;
[self.view.layer addSublayer:circleLayer];
Here's a good tutorial on creating animatable properties in CALayers.
Related
I am developing a program which identifies a rectangle in an image and draws a path on the border of that identified rectangle. Now I want to reposition that path in case if it is not on the exact position. For an example look at this image
In cases like this i need to drag the corners of the path and reposition it as it fits the rectangle.
To draw the path I used CAShapeLayer and UIBezierPath. Here is the code I used to draw the path.
// imgView is the UIImageView which contains the image with the rectangle
let line: CAShapeLayer = CAShapeLayer();
line.frame = imgView.bounds;
let linePath: UIBezierPath = UIBezierPath();
linePath.moveToPoint(CGPointMake(x1, y1);
linePath.addLineToPoint(CGPointMake(x2, y2);
linePath.addLineToPoint(CGPointMake(x3, y3);
linePath.addLineToPoint(CGPointMake(x4, y4);
linePath.addLineToPoint(CGPointMake(x1, y1);
linePath.closePath();
line.lineWidth = 5.0;
line.path = linePath.CGPath;
line.fillColor = UIColor.clearColor().CGColor;
line.strokeColor = UIColor.blueColor().CGColor;
imgView.layer.addSublayer(line);
The thing is I tried to add a gesture to UIBezierPath. But there is nothing like that as I noticed. Couldn't find anything regarding this. So can someone please let me know a way to get my work done. Any help would be highly appreciated.
You are right that there is no way to attach a gesture recognizer to a UIBezierPath. Gesture recognizers attach to UIView objects, and a UIBezierPath is not a view object.
There is no built-in mechanism to do this. You need to do it yourself. I would suggest building a family of classes to handle it. Create a rectangle view class. It would use a bezier path internally, as well as placing 4 corner point views on the vertexes and installing pan gesture recognizers each corner point view.
Note that Cocoa rectangles (CGRects) can't be rotated. You'll need to use a series of connected line segments and write logic that forces it to stay square.
In simple words only part of my icon must change color at some event.
I drawing an icon with curves inside an UIView. The drawing boilds
down to combining several paths together like this (swift code):
let combinedPath = CGPathCreateMutableCopy(bezierPath.CGPath)
CGPathAddPath(combinedPath, nil, bezier2Path.CGPath);
CGPathAddPath(combinedPath, nil, bezier3Path.CGPath);
Then I'm adding the combined path to the UIView like this (obj-c, sorry for
the mix):
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = self.bounds;
shapeLayer.path = combinedPath;
self.layer.mask = shapeLayer;
And now at some point in time I want to change the fill color of
only one bezierPath with animation. How can I do this?
You can clean the current mask, and redraw any of the bezierpath with stroke/fill color and combine them together, and set it again. And for drawing animation, you can refer to How to Animate CoreGraphics Drawing of Shape Using CAKeyframeAnimation
I am draw some circle on a map with
CGContextFillEllipseInRect
This works great, but the only issue is that I have the alpha value set to .5
If tow or more circle overlap the the overlap area is darker because of the two alpha values being added I suppose. Is there an easy way to maintain the same alpha value regardless if the circle overlap?
Thanks
If you're working with closed shapes and drawing them all in the same drawrect (or at least in the same context) you can accomplish what you want by using UIBezierPath.
// create a path with a circle
UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:50.0f startAngle:0 endAngle:M_PI * 2.0f clockwise:YES];
// add another circle to the path
[path appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:50.0f startAngle:0 endAngle:M_PI * 2.0f clockwise:YES]];
// draw them both, since they are in a single path they will be treated as a single shape
[path fill];
Draw the circles at full opacity, and set the opacity of the view/layer to 0.5.
EDIT:
To clarify, I assume you know how to stop drawing your circles at half opacity, since you managed to set it up that way in the first place. So make the opacity of your circles be 1.0. Then, set your view's opacity to 0.5 by doing the following:
view.alpha = 0.5;
I'm assuming you have a UIView subclass, so this can either be in the place in your code where you create the view or it could be inside the subclass in your init method for it. So if you're doing it from within the UIView subclass, it would be self instead of view:
self.alpha = 0.5;
Also, this will make all of the drawing you do in this view be 0.5 opacity. If you want to have some content that's full opacity and some that's half opacity, the simplest solution I can give you is to have two different views, one for the half opacity content, the other for the full opacity content. There are better ways to accomplish this, but for the sake of communicating easily a solution, this is probably easiest.
I have a CAShapeLayer, I am able to rotate it using UIRotationGestureRecognizer. But when rotating, it only rotate its frame not the filled pattern inside it.
CAShapeLayer *shapeLayer = [finalShapeLayersArray objectAtIndex:indextobeRotated];
CGPathRef path = createPathRotatedAroundBoundingBoxCenter(shapeLayer.path,recognizer.rotation);
shapeLayer.path = path;
CGPathRelease(path);
recognizer.rotation = 0;
Bu doing this, it only rotates the boundary of the CAShapeLayer. I have filled a pattern with an image. I just want that pattern should also be rotated.
You need to set a rotation transform on your layer using CALayer's transform property instead (you do not rotate the the shape path then as the whole layer will be rotated).
See this answer on how to create such a transform. Also see the Core Animation Function Reference for all the functions that can create/modify transformations.
I am working on an application wherein the user draws some closed area on an image. I want to crop any closed area drawn on that image. In a way I would like to achieve this functionality in this app
I have done the drawing part using touches method and CGContext but I am unable to crop the drawn area. Please help me out. i am running out of time for the dead line.
I guess you have a CGPathRef that you where able to draw in the CGContext.
From there you can create a layer, assign the image as a content and use a CAShapeLayer a s a mask to crop it.
CGPathRef path;
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
[shapeLayer setPath:path];
CALayer *imgLayer = [CALayer layer];
[imgLayer setContents:img];
[imgLayer setMask:shapeLayer];
[self.layer addSublayer:imgLayer];