I want to draw a triangle with dynamic values with base down and sharp edge up. How can I do that?
This should do it.
- (void)drawRect:(CGRect)rect {
//This set the line color
[[UIColor blueColor] setStroke];
[[UIColor redColor] setFill];
UIBezierPath *path = [UIBezierPath bezierPath];
//Starting point
[path moveToPoint:CGPointMake(0, 0)];
//Vertice one
[path addLineToPoint:CGPointMake(1, 1)];
//Vertice two
[path addLineToPoint:CGPointMake(0, 1)];
[path closePath];
//fill path with the defined color
[path fill];
//draw the stroke with the defined color
[path stroke];
}
Related
I want to draw a single path, which can overlap itself. What I want is like a snap of Moves below:
Can I achieve this just fill a single CGPathRef on iOS?
I created two paths, a gray one and red one below:
There are two overlaps on the gray line, one for itself and one for the red line. The red overlap, you can see it clearly, is above (or below) the gray one. But the gray overlap is just merged.
The Moves trace line is a single line, maybe is not implemented by a single path fill or stroke.
Here's my code:
[[UIColor colorWithWhite:0.0 alpha:0.3] setStroke];
CGFloat lineWidth = 10.0;
UIBezierPath *path = [UIBezierPath bezierPath];
path.lineWidth = lineWidth;
[path moveToPoint:CGPointMake(300, 50)];
[path addLineToPoint:CGPointMake(20, 400)];
[path addLineToPoint:CGPointMake(300, 400)];
[path addLineToPoint:CGPointMake(20, 50)];
[path stroke];
[[UIColor colorWithRed:1.0 green:0.5 blue:0.5 alpha:0.5] setStroke];
UIBezierPath *anotherPath = [UIBezierPath bezierPath];
anotherPath.lineWidth = lineWidth;
[anotherPath moveToPoint:CGPointMake(160, 50)];
[anotherPath addLineToPoint:CGPointMake(300, 200)];
[anotherPath stroke];
I want to create a custom shape into a UIView by drawing it myself using a UIBezierPath object and render it in drawRect:.
So far I managed to create the shape and stroke it so it is drawn on screen exactly how I want it to be. However I can't fill it properly. Here is the code so far:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.f);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:2.f];
[path setLineJoinStyle:kCGLineJoinRound];
// Stroke top left arc
//[path moveToPoint:CGPointMake(20.f, 2.f)];
[path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];
// Stroke bottom left arc
[path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];
// Stroke bottom line
[path moveToPoint:CGPointMake(10.f, 55.f)];
[path addLineToPoint:CGPointMake(60.f, 55.f)];
// Stroke bottom arc
[path moveToPoint:CGPointMake(80.f, 55.f)];
[path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(315) endAngle:degreesToRadians(215) clockwise:1];
// Stroke bottom right arc
[path moveToPoint:CGPointMake(80.f, 55.f)];
[path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];
// Stroke top right arc
[path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];
// Close path
[path moveToPoint:CGPointMake(80.f, 5.f)];
[path addLineToPoint:CGPointMake(10.f, 5.f)];
[path stroke];
[path fill];
}
Stroke works as expected, but the fill only fills portions on the path, instead of filling the entire path. Is there something I'm missing?
Thanks in advance!
Remove all your
- (void)moveToPoint:(CGPoint)point
methods except the first one because it is a continuous path you don't need it.
It is highly recommended to close the path by calling the method - (void)closePath because you are having 3 pixel gap.
I figured it out.
Just needed to get rid of moveToPoint: calls since they create subpaths and so the filling will only affect the new subpaths. And finally called closePath.
Now my path is continuous and the fill works for the entire shape.
Edited code:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:2.f];
[path setLineJoinStyle:kCGLineJoinRound];
// Stroke top left arc
[path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];
// Stroke bottom left arc
[path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];
// Stroke bottom arc
[path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(215) endAngle:degreesToRadians(315) clockwise:0];
// Stroke bottom right arc
[path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];
// Stroke top right arc
[path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];
// Close path
[path closePath];
[path fill];
[path stroke];
}
Simply call the method
- (void)closePath
at the end to close your UIBezierPath.
I'm trying a UIBezierPath for the first time and am trying to fill a graph I've drawn with a color but without success. This is what I've done within a custom UIView:
- (void)calculateGraphSize
{
self.topY = CGRectGetMinY(self.bounds);
self.bottomY = CGRectGetMaxY(self.bounds);
self.minX = CGRectGetMinX(self.bounds);
self.maxX = CGRectGetMaxX(self.bounds);
}
- (void) drawRect: (CGRect) rect
{
CGSize cornerRadius = CGSizeMake(10.0f, 10.0f);
[self calculateGraphSize];
UIBezierPath *graphBorder = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:cornerRadius];
[[UIColor redColor] setFill];
[graphBorder fill];
UIBezierPath *barGraph = [UIBezierPath bezierPath];
barGraph.lineWidth = 2.0f;
CGPoint point = CGPointMake(self.minX, self.bottomY);
[barGraph moveToPoint:point];
point = CGPointMake(self.minX + 50, self.bottomY - 50);
[barGraph addLineToPoint:point];
point = CGPointMake(self.minX + 100, self.bottomY - 75);
[barGraph addLineToPoint:point];
point = CGPointMake(self.minX + 200, self.bottomY);
[barGraph addLineToPoint:point];
[[UIColor blackColor] setStroke];
[[UIColor greenColor] setFill];
[barGraph closePath];
[barGraph stroke];
}
Just add [barGraph fill]:
[[UIColor blackColor] setStroke];
[[UIColor greenColor] setFill];
[barGraph closePath];
[barGraph fill];
[barGraph stroke];
You probably want to fill and then stroke as I can't remember if the fill will cover up the stroke (I always have to check ha!)
I am creating a UIBezierPath like this:
UIBezierPath *path = [UIBezierPath bezierPath];
[path addLineToPoint:CGPointMake(200.0, 40.0)];
[path addLineToPoint:CGPointMake(160, 140)];
[path addLineToPoint:CGPointMake(40.0, 140)];
[path addLineToPoint:CGPointMake(0.0, 40.0)];
[path closePath];
The problem is that when I try to draw my UIBezierPath, it does not appear and I get an error:
<Error>: void CGPathCloseSubpath(CGMutablePathRef): no current point.
My drawing code is very basic:
UIGraphicsBeginImageContext(self.view.bounds.size);
[[UIColor whiteColor] set];
[myPath stroke];
UIGraphicsEndImageContext();
What am I doing wrong?
The error message is clear. One line of code was missing when I was creating my UIBezierPath:
[path moveToPoint:CGPointMake(0, 0)];
I added it and everything worked like a charm.
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 0)];
[path addLineToPoint:CGPointMake(160, 140)];
[path addLineToPoint:CGPointMake(40.0, 140)];
[path addLineToPoint:CGPointMake(0.0, 40.0)];
[path closePath]
It is interesting that the error happened when I was trying to draw the line and not before - when I created it.
I'm getting a clipped LineJoin in a UIBezierPath when one line comes back exactly over the previous line. If I adjust the second line by one pixel, the LineJoin behaves as expected. Here's the code:
UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:10.0f];
[path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound];
[path moveToPoint:CGPointMake(100, 100)];
[path addLineToPoint:CGPointMake(200, 100)];
[path addLineToPoint:CGPointMake(150, 100)];
[path moveToPoint:CGPointMake(100, 120)];
[path addLineToPoint:CGPointMake(200, 120)];
[path addLineToPoint:CGPointMake(150, 121)];
[[UIColor redColor] setStroke];
[path stroke];
Here's what's displayed:
Is this a bug?
If not, is there some way to get the top path LineJoin to be rounded? (without fudging the points)
This came up when I made a UIBezierPath from 'touch-input', and while scribbling around sometimes this happened.
This is fixed in iOS 7.
Open Radar also updated.