As a part of my application,
I have implemented a sample paint by following RayWendrlich Simple Drawing App with UIKit
I almost completed my application with all requirements
By this i can able to draw but the lines are not smooth when we draw cross or, curves..
While surfing i found that we can able to make smooth with Bezier Path,
How should i use this bezier path in my app easy, can any help please.
Thanks
You can draw using.
UIBezierPath *aPath = [UIBezierPath bezierPath];
[aPath moveToPoint:CGPointMake(p1.x, p1.y)];
for (uint i=1; i<points.count; i++)
{
CGPoint p = [points objectAtIndex:i]
[aPath addQuadCurveToPoint:CGPointMake(p.x, p.y) controlPoint:controlPoint];
}
[aPath closePath];
[aPath fill];
For more information you can follow UIBezierPath Class Reference
Here is nice example
you can use uibezirpath for drawing path when touch end you can capture that uiview to image and setbackground of the uiview and clear path this will done smooth drawing app
Related
OK, so I needed a rounded triangle. So what I did was use a technique similar to what I've used in other vector drawing programs. Draw the triangle and use the stroke to create the rounded corners. Worked like a charm too, until I needed to reduce the alpha of the color used to fill and stroke the UIBezierPath. For some reason I keep getting this inset outline that isn't the same color as the Fill and Stroke. Somehow the alpha value isn't being respected. Maybe I'm overlooking something silly here, but try as I might I can't get the triangle all one color with a alpha value lower than 1. This is what I get:
And heres the simple code:
- (void)drawRect:(CGRect)rect
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint: CGPointMake(63.5, 10.5)];
[path addLineToPoint: CGPointMake(4.72, 119.5)];
[path addLineToPoint: CGPointMake(122.28, 119.5)];
[path addLineToPoint: CGPointMake(63.5, 10.5)];
[path closePath];
path.miterLimit = 7;
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 8;
UIColor *whiteAlph5 = [UIColor colorWithWhite:0.6 alpha:0.5];
[whiteAlph5 setFill];
[whiteAlph5 setStroke];
[path fill];
[path stroke];
}
I can't understand why the line would be anything other than the "whiteAlpha5" if that's the only color I've set for both fill and stroke. I suppose I can just draw the rounded triangle out adding the curves to to corners, but I'm just curious as to why this happens.Thanks in advance...
If you must have the stroke, alter your call to [UIBezierPath stroke] like so:
[path fill];
[path strokeWithBlendMode:kCGBlendModeCopy alpha:1.0];
This should achieve the effect you want (I think - haven't been able to test it)
This is a bit of a guess, but I think you're seeing here is essentially two layers of semitransparent white, one drawn on top of the other. When the triangle is just filled in, it would be what you're expecting. When you stroke, it's drawing the same colour - but it's adding it on top of the existing colour, not replacing it, which is the effect you might expect if you've done this before in paint programs or similar. Thus, where the stroke and fill overlap, you're getting a stronger white than you're after. Just using fill by itself could solve this, but might not get the rounded effect you're after.
If you need a visual demonstration of what I mean, you can do this in Photoshop. Create a new image with a black background and create a new layer above it, set to 50% opacity. Draw a white square on it (which will look grey due to the opacity). Then, without changing layers, draw a line through it. You won't see the line, because it's replacing the existing colour - this is what you expected to happen with your code. Then, add another layer above it, also set to 50% opacity. Draw a line on this layer, through the square. You'll see the line as a brighter grey. This is additive, the white overlapping on both layers - the effect that your code is creating.
The line is because your stroke and your fill are drawing to the same pixels. Since both the stroke and the fill are partially transparent, the colors accumulate.
One way to fix this is to just create a path that outlines your rounded triangle, and fill it without stroking it.
Here's the interface for a category that creates a path outlining a rounded polygon:
#interface UIBezierPath (MyRoundedPolygon)
+ (UIBezierPath *)my_roundedPolygonWithSides:(int)sides center:(CGPoint)center
vertexRadius:(CGFloat)vertexRadius cornerRadius:(CGFloat)cornerRadius
rotationOffset:(CGFloat)rotationOffset;
#end
Here's the implementation:
#implementation UIBezierPath (MyRoundedPolygon)
static CGPoint vertexForPolygon(int sides, CGPoint center, CGFloat circumradius, CGFloat index) {
CGFloat angle = index * 2 * M_PI / sides;
return CGPointMake(center.x + circumradius * cosf(angle),
center.y + circumradius * sinf(angle));
}
+ (UIBezierPath *)my_roundedPolygonWithSides:(int)sides center:(CGPoint)center
vertexRadius:(CGFloat)vertexRadius cornerRadius:(CGFloat)cornerRadius
rotationOffset:(CGFloat)rotationOffset
{
CGFloat circumradius = vertexRadius + cornerRadius;
CGPoint veryLastVertex = vertexForPolygon(sides, center, circumradius, rotationOffset - 1);
CGPoint currentVertex = vertexForPolygon(sides, center, circumradius, rotationOffset);
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPathMoveToPoint(cgpath, NULL, (veryLastVertex.x + currentVertex.x) / 2,
(veryLastVertex.y + currentVertex.y) / 2);
for (CGFloat i = 0; i < sides; ++i) {
CGPoint nextVertex = vertexForPolygon(sides, center, circumradius,
i + 1 + rotationOffset);
CGPathAddArcToPoint(cgpath, NULL, currentVertex.x, currentVertex.y,
nextVertex.x, nextVertex.y, cornerRadius);
currentVertex = nextVertex;
}
CGPathCloseSubpath(cgpath);
UIBezierPath *path = [self bezierPathWithCGPath:cgpath];
CGPathRelease(cgpath);
return path;
}
#end
Here's how you use it:
#implementation MyView
- (void)drawRect:(CGRect)rect
{
CGRect bounds = self.bounds;
CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
UIBezierPath *path = [UIBezierPath my_roundedPolygonWithSides:3 center:center
vertexRadius:70 cornerRadius:8 rotationOffset:0.25];
[[UIColor colorWithWhite:0.6 alpha:0.5] setFill];
[path fill];
}
#end
And here's the result:
Note that setting rotationOffset to 0.25 rotated the triangle one quarter turn. Setting it to zero will give you a right-pointing triangle.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Circle to Circle Segment Collision
I am the beginner with iOS development. Do you know how to draw a image like this http://www.hoodshomecenters.com/product_images/v/723/QuarterRound__65714_zoom.jpg with CoreGraphic?
This is the code for drawing the arc portion. Once it is drawn then you can draw lines within it.
#include <math.h>
CGFloat radius = 100;
CGFloat starttime = M_PI/6; //1 pm = 1/6 rad
CGFloat endtime = M_PI; //6 pm = 1 rad
//draw arc
CGPoint center = CGPointMake(radius,radius);
UIBezierPath *arc = [UIBezierPath bezierPath]; //empty path
[arc moveToPoint:center];
CGPoint next;
next.x = center.x + radius * cos(starttime);
next.y = center.y + radius * sin(starttime);
[arc addLineToPoint:next]; //go one end of arc
[arc addArcWithCenter:center radius:radius startAngle:starttime endAngle:endtime clockwise:YES]; //add the arc
[arc addLineToPoint:center]; //back to center
[[UIColor yellowColor] set];
[arc fill];
You need to overwrite the drawRect method of the view in which you will be used for showing this drawing.
You can draw an arc segment with the UIBezierPath class using the method bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise. Have a look here
You will also need to create a path for your lines using the combination of CGContextMoveToPoint/ CGContextAddLineToPoint
Last you stroke your lines by invoking the stroke method on your path.
EDIT
To draw the inner lines you probably want to clip those: this is done with the CGContextClip function
You can certainly use
void CGContextAddArcToPoint
The documentation:
CGContext reference
I am again here with two Question, both inter-related
I want to draw embossed lines with core graphics.
Can any one suggest me how to give inner shadows to line drawn on touch events?
Even for drawing outer shadows.
Shadow drawn overlaps in between. and line drawn with colors other than black is like worm..
Can any one help me?
Following image illustrates what I mean to explain for Question 2:
Shadows creates are not even. They darken at some points
I am adding the code that I am using to draw lines..
for (int i=0; i<[currentPath count]; i++)
{
CGPoint mid1 = [[self midPoint:[currentPath objectAtIndex:i+1] :[currentPath objectAtIndex:i]] CGPointValue];
CGPoint mid2 = [[self midPoint:[currentPath objectAtIndex:i+2] :[currentPath objectAtIndex:i+1]] CGPointValue];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, [[currentPath objectAtIndex:i+1] CGPointValue].x, [[currentPath objectAtIndex:i+1] CGPointValue].y, mid2.x, mid2.y);
CGContextSetShadow(context, CGSizeMake(-2, -2), 3);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetStrokeColorWithColor(context,[color CGColor]);
CGContextSetLineWidth(context, linewidth);
CGContextStrokePath(context);
i+=2;
}
I found my solution..
Problem was very silly...
I was stoking path on every iteration which was creating the issue.. Now I can draw even with alpha less then 1..
CGContextStrokePath(context);
This line goes outside for loop.. And all is working fine now :)
For your overlapping shadows, you want a transparency layer to composite them first. See Transparency Layers in the Quartz 2D Programming Guide.
It looks like you are drawing the path by using a series of circles.
The trouble is that you have set the shadow on the individual dots, and that's why you are getting the strange effects.
A possible solution - dont put a shadow on the dots, put on the path: duplicate the line that you have drawn, draw it in a different colour, offset it and put in under your actual line.
Alternatively, if you are using layers - have a look at shadow paths.
I am developing an application in which I have to show the selected time in my clock image.
Description:-
What I exactly want to say it I am having a image of circle. Now according to the selected time I want that portion to be filled in some other color on my circle image.
Please help me in doing this.
I am stuck here.
I have attached the image that will describe more what I exactly want to do.
I also tried it with doing it with pie-chart but area showing not giving proper time.
Please please help me.
In this image it shows time 1:am to 6:am
Any help would be highly appreciated.
For what you want above (not using coreplot). Place this code in the relevant drawRect/drawInContext method.
Not at mac so not 100% sure it will compile. Should be close. Also might be out by 90
#include <math.h>
CGFloat radius = 100;
//CGFloat pi = 3.1415927; //comes for free in math.h
//draw underlying circle;
UIBezierPath *basecircle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,radius*2,radius*2)];
[[UIColor blackColor] set];
[basecircle fill];
CGFloat starttime = pi/6; //1 pm = 1/6 rad
GFloat endtime = pi; //6 pm = 1 rad
//draw arc
CGPoint center = CGPointMake(radius,radius);
UIBezier *arc = [UIBezierPath bezierPath]; //empty path
[arc moveToPoint:center];
CGPoint next;
next.x = radius + radius * sin(starttime);
next.y = radius + radius * cos(starttime);
[arc moveToPoint:next]; //go one end of arc
[arc addArcWithCenter:center radius:radius startAngle:starttime endAngle:endtime clockwise:YES]; //add the arc
[arc moveToPoint:center]; //back to center
[[UIColor yellowColor] set];
[arc fill];
Did a simple application for line drawing with UIBezierPath, but now need a way to erase the line drawn with UIBezierPath. Is there a way to implement eraser feature for removing the line painting?
If you are using an image as background then you can set the same image as brush pattern to draw the bezierpath it will virtually give you the eraser effect. It works for me. :)
brushPattern=[[UIColor alloc]initWithPatternImage:[UIImage imageNamed:#"image.jpg"]];
// Here image.jpg is you background image
if(erase)
{
[myPath strokeWithBlendMode:kCGBlendModeClear alpha:1.0f];
}
else
{
[myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0f];
}
An eraser effectively draws a line that's the same color as the background atop every path that's been drawn thus far. You might need to note that it's an eraser line somewhere so that you can update the eraser line's stroke color if the background color changes, otherwise you lose the illusion of erasure.
Based on your comments on Jeremy's answer, it seems like you're trying to do dashed lines. Have you tried using setLineDash:count:phase:
UIBezierPath *path = [UIBezierPath new];
CGFloat dashArray[3];
dashArray[0] = 8;
dashArray[1] = 3;
dashArray[2] = 8;
[path setLineDash:dashArray count:dashCount phase: 0.0];
Apple has sample code here: http://developer.apple.com/library/mac/#samplecode/BezierPathLab/Introduction/Intro.html