Referring to the following image:
. . . . notice how it does not end in a proper point.
I use the following drawing code:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextMoveToPoint(context, self.width - 20, (self.height / 2) - 5);
CGContextAddLineToPoint(context, self.width - 12, self.height / 2);
CGContextStrokePath(context);
CGContextMoveToPoint(context, self.width - 20, (self.height / 2) + 5);
CGContextAddLineToPoint(context, self.width - 12, self.height / 2);
CGContextStrokePath(context);
Is there an easy way to say that a line should end in a point? I know that I could fix this by modifying the coordinates slightly, but I'm curious to learn more.
The lines are not joined, so the CGLineJoin style does not take effect. It should be fine with the following code:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextMoveToPoint(context, self.width - 20, (self.height / 2) - 5);
CGContextAddLineToPoint(context, self.width - 12, self.height / 2);
CGContextAddLineToPoint(context, self.width - 20, self.height / 2 + 5);
CGContextStrokePath(context);
Related
I have this line around my shape:
The problem is, it obviously goes from 1px thick, to 2px. Here's the code I'm using:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetFillColorWithColor(context, [BUTTON_COLOR CGColor]);
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextSetLineWidth(context, 1);
int radius = 8;
CGContextMoveToPoint(context, 0, self.frame.size.height / 2);
CGContextAddLineToPoint(context, POINT_WIDTH, self.frame.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius,
rect.origin.y + rect.size.height);
CGContextAddArc(context, rect.origin.x + rect.size.width - radius,
rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius);
CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius,
radius, 0.0f, -M_PI / 2, 1);
CGContextAddLineToPoint(context, POINT_WIDTH, 0);
CGContextAddLineToPoint(context, 0, self.frame.size.height / 2);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
Any ideas?
The reason your top, bottom, and right edges appear thinner than your diagonals is because you are chopping off half of the lines drawn along those edges. As Costique mentioned, Core Graphics draws a stroke so that it is centered on the path. That means half of the stroke lies on one side of the path, and half of the stroke lies on the other side. Since your path runs exactly along the top, right, and bottom edges of your view, half of the stroke falls outside the bounds of your view and isn't drawn.
Costique is also correct that you should move your paths in by .5 points. (Technically you should move by half the stroke width.) However, you're not specifying your coordinates uniformly based on the rect variable, so moving all your paths is difficult.
What you want to do is inset rect by .5 in both dimensions, adjust your graphics context so that its origin is at rect.origin, and use only rect.size to get your coordinates - not self.frame.size. Here's my test:
- (void)drawRect:(CGRect)dirtyRect
{
CGContextRef gc = UIGraphicsGetCurrentContext();
CGContextSaveGState(gc); {
CGContextSetFillColorWithColor(gc, [UIColor colorWithWhite:.9 alpha:1].CGColor);
CGContextSetStrokeColorWithColor(gc, [[UIColor blackColor] CGColor]);
CGContextSetLineWidth(gc, 1);
static const CGFloat Radius = 8;
static const CGFloat PointWidth = 20;
CGRect rect = CGRectInset(self.bounds, .5, .5);
CGContextTranslateCTM(gc, rect.origin.x, rect.origin.x);
rect.origin = CGPointZero;
CGContextMoveToPoint(gc, 0, rect.size.height / 2);
CGContextAddLineToPoint(gc, PointWidth, rect.size.height);
CGContextAddLineToPoint(gc, rect.origin.x + rect.size.width - Radius,
rect.origin.y + rect.size.height);
CGContextAddArc(gc, rect.origin.x + rect.size.width - Radius,
rect.origin.y + rect.size.height - Radius, Radius, M_PI / 2, 0.0f, 1);
CGContextAddLineToPoint(gc, rect.origin.x + rect.size.width, rect.origin.y + Radius);
CGContextAddArc(gc, rect.origin.x + rect.size.width - Radius, rect.origin.y + Radius,
Radius, 0.0f, -M_PI / 2, 1);
CGContextAddLineToPoint(gc, PointWidth, 0);
CGContextAddLineToPoint(gc, 0, rect.size.height / 2);
CGContextClosePath(gc);
CGContextDrawPath(gc, kCGPathFillStroke);
} CGContextRestoreGState(gc);
}
Here's the result:
Core Graphics draws the stroke on the path edge, that is, half of the stroke width lies inside the path, and the other half, outside. Since you cannot draw outside of the view, half of the stroke is clipped by the context. You have to inset the path by half the stroke width.
The complete example:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetFillColorWithColor(context, [BUTTON_COLOR CGColor]);
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextSetLineWidth(context, 1);
int radius = CORNER_RADIUS;
CGRect pathRect = CGRectInset(self.bounds, 0.5f, 0.5f);
CGContextMoveToPoint(context, CGRectGetMinX(pathRect), CGRectGetMidY(pathRect));
CGContextAddLineToPoint(context, CGRectGetMinX(pathRect) + POINT_WIDTH, CGRectGetMaxY(pathRect));
CGContextAddArc(context, CGRectGetMaxX(pathRect) - radius,
CGRectGetMaxY(pathRect) - radius, radius, M_PI / 2, 0.0f, 1);
CGContextAddArc(context, CGRectGetMaxX(pathRect) - radius, CGRectGetMinY(pathRect) + radius,
radius, 0.0f, -M_PI / 2, 1);
CGContextAddLineToPoint(context, CGRectGetMinX(pathRect) + POINT_WIDTH, CGRectGetMinY(pathRect));
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
Note that several redundant drawing commands are removed without affecting the result. Enjoy.
I having the follow pop up and I want to make the edges curved.
Using this code.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [[UIColor greenColor] CGColor]);
CGFloat baseWidth = 15.0;
CGFloat height = 10.0;
CGContextMoveToPoint(context, self.bounds.size.width / 2.0 - baseWidth / 2.0, height);
CGContextAddLineToPoint(context, self.bounds.size.width / 2.0, 0);
CGContextAddLineToPoint(context, self.bounds.size.width / 2.0 + baseWidth / 2.0, height);
CGContextAddLineToPoint(context, self.bounds.size.width, height);
CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height);
CGContextAddLineToPoint(context, 0, self.bounds.size.height);
CGContextAddLineToPoint(context, 0, height);
CGContextClosePath(context);
CGContextStrokePath(context);
How can I curve the edges?
You are using Core Graphics and drawing those straight lines right up to each other in the screen shot above. To be able to draw curves you need to add in some calls to CGContectAddArcToPoint, there is also CGContextAddCurveToPoint but that is overkill for your implementation here.
If you want more information about Core Graphics then you can find a bunch of documentation here: https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_paths/dq_paths.html#//apple_ref/doc/uid/TP30001066-CH211-TPXREF101
I'm trying to draw a rectangle that has a 15 degree angle splitting two colors down the center but the line between them is pixelated. I've tried different blend options and can't seem to figure out how to make this look clean.
This is what the header looks like now
Does anyone know how I can make the line between them look clean?
if (!_backgroundImageView.image) {
CGFloat width = CGRectGetWidth(self.bounds);
CGFloat height = CGRectGetHeight(self.bounds);
CGFloat tWidth = 0.26794919243f/*tan(15 degrees)*/ * height;
UIGraphicsBeginImageContext(CGSizeMake(width, height));
CGContextRef context = UIGraphicsGetCurrentContext();
if (_color1) {
CGContextSetFillColorWithColor(context, _color1.CGColor);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 1.0f + RoundPixelValue((width + tWidth) / 2.0f), 0);
CGContextAddLineToPoint(context, 1.0f + RoundPixelValue((width - tWidth) / 2.0f), height);
CGContextAddLineToPoint(context, 0, height);
CGContextFillPath(context);
}
if (_color2) {
CGContextSetFillColorWithColor(context, _color2.CGColor);
CGContextMoveToPoint(context, width, 0);
CGContextAddLineToPoint(context, RoundPixelValue((width + tWidth) / 2.0f) - 1.0f, 0);
CGContextAddLineToPoint(context, RoundPixelValue((width - tWidth) / 2.0f) - 1.0f, height);
CGContextAddLineToPoint(context, width, height);
CGContextFillPath(context);
}
_backgroundImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
The main issue here is that you're not creating the context with the correct scale.
Instead of using UIGraphicsBeginImageContext use UIGraphicsBeginImageContextWithOptions like so:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), YES, 0);
Specifying a scale of 0 sets it to the scale factor of the device screen.
This should eliminated most of the aliasing artifacts.
So i have a weird problem when im trying to draw in a custom class that has a subclass of a uiview the lines are thick and fuzzy but when i change the subclass to a uilabel it looks smooth and thin. Just curious are there different default settings enabled for this to occur and if so what are they ?
cant post screens yet
Thanks in advance
Update:
Relevent code note no changes are being made between changing of the subclass
CGContextRef ctx = UIGraphicsGetCurrentContext();
// CGContextSetAllowsAntialiasing(ctx, YES);
// CGContextSetShouldAntialias(ctx,YES);
// CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh);
CGContextSetStrokeColorWithColor(ctx, [UIColor blackColor].CGColor);
CGContextSetShadow(ctx, CGSizeMake(0, 3), 2);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 1, 0);
CGContextAddCurveToPoint(ctx, 5, self.frame.size.height - 10, 15, self.frame.size.height - 1, 30, self.frame.size.height - 1);
CGContextAddLineToPoint(ctx, self.frame.size.width - 30, self.frame.size.height - 1);
CGContextAddCurveToPoint(ctx, self.frame.size.width - 15, self.frame.size.height - 1, self.frame.size.width - 5, self.frame.size.height - 10, self.frame.size.width - 1, 0);
[AppDel.styleChangerController.RoomHightlightColor setFill];
CGContextDrawPath(ctx, kCGPathFillStroke);
[super drawRect: rect];
Im trying to achieve a button shapped as
This is the current code I'm trying . It achieves concentric circle but the outer one is filled instead. Help.
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, rect);
CGContextAddEllipseInRect(ctx,
CGRectMake(
rect.origin.x + 10,
rect.origin.y + 10,
rect.size.width - 20,
rect.size.height - 20));
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
CGContextEOFillPath(ctx);
Make two contexts and fill only the inner circle
- (void)drawRect:(CGRect)rect
{
CGContextRef outer = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(outer, 1.5);
CGContextSetStrokeColorWithColor(outer, [UIColor blueColor].CGColor);
CGContextAddEllipseInRect(outer, CGRectMake(rect.origin.x + 5, rect.origin.y + 5, rect.size.width - 10, rect.size.height - 10));
CGContextStrokePath(outer);
CGContextRef inner = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(inner, 1.5);
CGContextSetFillColorWithColor(inner, [UIColor blueColor].CGColor);
CGContextAddEllipseInRect(inner, CGRectMake(rect.origin.x + 15, rect.origin.y + 15, rect.size.width - 30, rect.size.height - 30));
CGContextFillPath(inner);
}
I have added padding of 5 units to outer context so that it looks like circle and not rounded rectangle.
In your custom view drawRect:
CGContextSetLineWidth(outerCircleContext, 1.0);
CGContextSetStrokeColorWithColor(outerCircleContext, [UIColor greenColor].CGColor);
CGRect outerRectangle = CGRectMake(CGRectGetMidX(rect) - 25, CGRectGetMidY(rect) - 25 , 50, 50);
CGContextAddEllipseInRect(outerCircleContext, outerRectangle);
CGContextStrokePath(outerCircleContext);
CGContextRef innerCircleContext = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(innerCircleContext, 1.0);
CGContextSetFillColorWithColor(innerCircleContext, [UIColor greenColor].CGColor);
CGRect innerRectangle = CGRectMake(CGRectGetMidX(rect) - 20, CGRectGetMidY(rect) - 20 , 40, 40);
CGContextAddEllipseInRect(innerCircleContext, innerRectangle);
CGContextFillPath(innerCircleContext);
Yo can also use path also.