Adding Bezier path to CGPath: ObjectiveC - objective-c

I have a rectangle drawn using drawRect method.
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect outline = CGRectMake(4, 4, width - 8, height - 8);
CGColorRef white = [[UIColor whiteColor] CGColor];
CGColorRef black = [[UIColor blackColor] CGColor];
CGContextSetFillColorWithColor(context, white);
CGContextFillEllipseInRect(context, outline);
CGContextSetLineWidth(context, 2.0f);
CGContextSetStrokeColorWithColor(context, black);
CGContextStrokeEllipseInRect(context, outline);
I have a bezier path drawn in the samedrawn rect method.
[[UIColor blackColor] setStroke];
[[UIColor whiteColor] setFill];
UIBezierPath * path = [UIBezierPath bezierPath];
[path moveToPoint:point1];
[path addQuadCurveToPoint:point3 controlPoint:point2];
[path addQuadCurveToPoint:point5 controlPoint:point4];
[path setLineWidth:2.0f];
[path stroke];
[path fill];
I need to add a CALayer over these two shapes so that they appear as one.
aPath = CGPathCreateMutable();
CGPathAddEllipseInRect(aPath, nil, outline);
CGPathCloseSubpath(aPath);
pathCopy = CGPathCreateCopyByTransformingPath(aPath, nil);
myLayer = nil;
myLayer = [CAShapeLayer layer];
myLayer.path = pathCopy;
myLayer.fillColor = [[UIColor whiteColor] CGColor];
[self.layer addSublayer:myLayer];
The problem is that I cant add the bezier path to the CGPath. That's one.
Another one is that I cant add a border color or border width to the layer which I am creating. Can anyone help?

Try:
CGPathAddPath(aPath, nil, path.CGPath);
Where aPath is your mutable CGPath and path is your UIBezierPath.

Related

How to clip a triangular view from a rectangular view in objective C?

I want view like below image:-
desired view
I am using UIBezierPath and CAShapeLayer to archives this below code:-
UIBezierPath *path = [[UIBezierPath alloc] init];
// [[UIColor blackColor] setStroke];
// [[UIColor redColor] setFill];
[path moveToPoint:CGPointMake(_pendingView.frame.origin.x, _pendingView.frame.origin.y)];
[path addLineToPoint:CGPointMake(_pendingView.frame.origin.x+15, _pendingView.frame.origin.y+15)];
[path addLineToPoint:CGPointMake(_pendingView.frame.origin.x, _pendingView.frame.origin.y+30)];
[path closePath];
// [path fill ];
// [path stroke];
CAShapeLayer *shapeLayer = [CAShapeLayer new];
shapeLayer.frame = _pendingView.bounds;
shapeLayer.path = path.CGPath;
shapeLayer.fillColor = [UIColor redColor].CGColor;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
self.pendingView.layer.mask = shapeLayer;
// [self.pendingView.layer addSublayer:shapeLayer];
but i am unable to achieve. View appear without Clipping and background colour of view.
P.S :- pendingview is a view.
AS PER #inderJit suggestion, i rectify my code but i am getting this output image not desired one which above attached. View background colour causing problem. how can i achieve that??
In your code you are using _pendingView i.e. your UIView, origin for drawing path but layer will placed inside the _pendingView, so because of this you are not getting proper output.
For more clarification you can go through the below code
UIBezierPath *path = [[UIBezierPath alloc] init];
// [[UIColor blackColor] setStroke];
// [[UIColor redColor] setFill];
[path moveToPoint:CGPointMake(0, 0)];
[path addLineToPoint:CGPointMake(15, _vwArrow.frame.size.height/2)];
[path addLineToPoint:CGPointMake(0, _vwArrow.frame.size.height)];
[path closePath];
// [path fill ];
// [path stroke];
CAShapeLayer *shapeLayer = [CAShapeLayer new];
shapeLayer.frame = _vwArrow.bounds;
shapeLayer.path = path.CGPath;
shapeLayer.fillColor = self.view.backgroundColor.CGColor;
// shapeLayer.strokeColor = [UIColor blackColor].CGColor;
// _vwArrow.layer.masksToBounds = TRUE;
[_vwArrow.layer addSublayer:shapeLayer];
[self.view setNeedsDisplay];

How to animate a drawn line in Objective C?

I am trying to animate drawn objects, for example I have drawn a line with this approach:
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(Center.x, Center.y)];
[path addLineToPoint:CGPointMake(Point.x,Point.y)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor whiteColor] CGColor];
shapeLayer.lineWidth = 1.5;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
[self.view.layer addSublayer:shapeLayer];
After a while I need to animate the line to have a different Point, but keeping Center as is, but I have no idea how to do that. Is my approach alright? Is there a better way to do so?
Solved it:
CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:#"path"];
morph.duration = 1.0;
UIBezierPath *path5 = [UIBezierPath bezierPath];
[path5 moveToPoint:CGPointMake(P22.x+5, P22.y+5)];
[path5 addLineToPoint:CGPointMake(P21.x,P21.y)];
morph.fromValue = (id) path.CGPath;
morph.toValue = (id) path5.CGPath;
[shapeLayer addAnimation:morph forKey:nil];
//next line to update the shapeLayer's new path
shapeLayer.path = path5.CGPath;

NSTextFieldCell rounded corners stroke not rounded

I want to have an NSTextField with rounded corners, for that I subclassed my NSTextFieldCell, and used drawInteriorWithFrame:(NSRect) inView:(NSView *)
My code looks like that :
-(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
//Color Declarations
NSColor* fillColor = [NSColor colorWithCalibratedRed: 1 green: 1 blue: 1 alpha: 1];
NSColor* strokeColor = [NSColor colorWithCalibratedRed: 0.679 green: 0.679 blue: 0.679 alpha: 1];
//Shadow Declarations
NSShadow* shadow = [[NSShadow alloc] init];
[shadow setShadowColor: strokeColor];
[shadow setShadowOffset: NSMakeSize(0.1, 0.1)];
[shadow setShadowBlurRadius: 4];
//Rounded Rectangle Drawing
NSBezierPath* roundedRectanglePath = [NSBezierPath bezierPathWithRoundedRect:cellFrame xRadius: 10 yRadius: 10];
[fillColor setFill];
[roundedRectanglePath fill];
//Rounded Rectangle Inner Shadow
NSRect roundedRectangleBorderRect = NSInsetRect([roundedRectanglePath bounds], -shadow.shadowBlurRadius, -shadow.shadowBlurRadius);
roundedRectangleBorderRect = NSOffsetRect(roundedRectangleBorderRect, -shadow.shadowOffset.width, -shadow.shadowOffset.height);
roundedRectangleBorderRect = NSInsetRect(NSUnionRect(roundedRectangleBorderRect, [roundedRectanglePath bounds]), -1, -1);
NSBezierPath* roundedRectangleNegativePath = [NSBezierPath bezierPathWithRect: roundedRectangleBorderRect];
[roundedRectangleNegativePath appendBezierPath: roundedRectanglePath];
[roundedRectangleNegativePath setWindingRule: NSEvenOddWindingRule];
[NSGraphicsContext saveGraphicsState];
{
NSShadow* shadowWithOffset = [shadow copy];
CGFloat xOffset = shadowWithOffset.shadowOffset.width + round(roundedRectangleBorderRect.size.width);
CGFloat yOffset = shadowWithOffset.shadowOffset.height;
shadowWithOffset.shadowOffset = NSMakeSize(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset));
[shadowWithOffset set];
[[NSColor grayColor] setFill];
[roundedRectanglePath addClip];
NSAffineTransform* transform = [NSAffineTransform transform];
[transform translateXBy: -round(roundedRectangleBorderRect.size.width) yBy: 0];
[[transform transformBezierPath: roundedRectangleNegativePath] fill];
}
[NSGraphicsContext restoreGraphicsState];
[strokeColor setStroke];
[roundedRectanglePath setLineWidth: 2];
[roundedRectanglePath stroke];
[super drawInteriorWithFrame:cellFrame inView:controlView];
}
The result looks great apart from borders which are not rounded. Images are better than words : My NSTextField
All help is accepted ! :D Thank you in advance.
UPDATE
I did a copy paste with the code of the site you said, but I'm still having the same trouble...
NSTextField with on rounded corner
You may simply choose the Border of Text Field in its Attributes Inspector if you want a text field with its all corners rounded. Or to draw a text field with any one round corner, go through this
Also if you want draw a custom all round corner text field, just follow the steps in above link, but instead of drawing a bezier path with one round corner, simply draw a bezier path with all corners round using
[NSBezierPath bezierPathWithRoundedRect:textfieldrect xRadius:10 yRadius:10]

Animating NSView via NSBezierPath

I have some NSBezierPath, and some NSView. I want to animate this NSView and use NEBezierPath as a animation path.
Creating CAKeyframeAnimation with path from UIBezierPath on IOS works fine for me, but for OSX it's not exactly the same.
Here is the code:
self.headView = [[NSView alloc] initWithFrame:NSMakeRect(100, 100, 50, 50)];
[self.headView setWantsLayer:YES];
[self.headView.layer setBackgroundColor:[NSColor redColor].CGColor];
[self.contentView addSubview:self.headView];
NSBezierPath *path = [NSBezierPath bezierPath];
[path moveToPoint:pathStart];
[path curveToPoint:endPoint controlPoint1:[pointValue pointValue] controlPoint2:[pointValue pointValue]];
[path setLineWidth:3.0];
[[NSColor whiteColor] set];
[path stroke];
CAKeyframeAnimation *posAnim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
posAnim.path = [path quartsPath];
posAnim.duration = 1.0;
posAnim.calculationMode = kCAAnimationLinear;
[self.headView.layer addAnimation:posAnim forKey:#"posAnim"];
Converting NSBezierPath to CGPathRef is from there: https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/CocoaDrawingGuide/Paths/Paths.html#//apple_ref/doc/uid/TP40003290-CH206-SW2
But it doesn't animate at all, here is the video: http://d.pr/v/glqQ
I don't getting what is the problem...
P.S. I prefer Keyframe animation because I would like to add some bouncing effect latter.
Make sure the superview of your headView also has a valid layer. Try this:
self.contentView.wantsLayer = YES;

How can I mask a square image with a circle and also put a black border around the image

I have a square image 40x40 that I want to make round via clipping, but also put a black 5 pixel border around the image.
I have the following which is masking the square image so its now round
UIImage *image = self.imageView.image;
CGSize imageSize = image.size;
CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
// Create the clipping path and add it
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:imageRect];
[path addClip];
[image drawInRect:imageRect];
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.imageView.image = roundedImage;
But now I need to also add a round border around it. Do I need a new path or can I just tack onto the one one in the code above?
Add the following three lines in your code (with whatever color and stroke width you want):
CGContextSetStrokeColorWithColor(ctx, [[UIColor greenColor] CGColor]);
[path setLineWidth:50.0f];
[path stroke];
So it becomes:
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Create the clipping path and add it
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:imageRect];
[path addClip];
[image drawInRect:imageRect];
CGContextSetStrokeColorWithColor(ctx, [[UIColor greenColor] CGColor]);
[path setLineWidth:50.0f];
[path stroke];
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.imageView.image = roundedImage;