Making the outer-edges of a UIBezierPath semi-transparent - iphone

I am currently drawing a UIImage within a UIBezierPath like so:
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
UIBezierPath *polygonPath = [UIBezierPath bezierPath];
CGPoint curPoint = [self originalPoint:[[drawArray objectAtIndex:0]CGPointValue]];
// set the starting point for the lines
[polygonPath moveToPoint:curPoint];
// go through each point in drawArray and add it to polygonPath
for(NSInteger i = 1; i < [drawArray count]; i++) {
curPoint = [self originalPoint:[[drawArray objectAtIndex:i]CGPointValue]];
// scale point
curPoint = CGPointMake(curPoint.x, curPoint.y);
[polygonPath addLineToPoint:curPoint];
}
[polygonPath closePath];
[polygonPath addClip];
[image drawAtPoint:CGPointZero];
It works great, however I'd like to have "smooth edges", slightly transparent, for the image, as I'm drawing it on top of another image... Right now the edges are pretty rough.
Thanks for your help!

As you are drawing on the image. So I suggest you to use following code...
Where YourImageis the UIImage on which you are drawing line.
[[UIColor colorWithPatternImage:YourImage] set];
For More Visit this reference
Hope, this will help you...

Related

How to create an oval shape UIButton

I have to draw an oval shape button, i don't want to set the image in oval shape.
I have read that you can draw different shaper with UIBezierPath but i am unable to draw a proper oval shape.
Here is the code is am using to create a circular shape.
self.layer.borderWidth=1.0;
self.clipsToBounds = YES;
[self setTitleColor:ktextColor forState:UIControlStateNormal];
self.layer.cornerRadius = self.bounds.size.width/2;//half of the width
self.layer.borderColor=[[UIColor whiteColor]CGColor];
Any help is appreciated !!
You can set the delegate for your button's layer and implement the delegate method `displayLayer:'
-(void)displayLayer:(CALayer *)layer
{
UIGraphicsBeginImageContext(layer.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0.0, 0.0, CGRectGetWidth(layer.frame), CGRectGetHeight(layer.frame))];
[[UIColor whiteColor] setFill];
[ovalPath fill];
[[UIColor blackColor] setStroke];
ovalPath.lineWidth = 1;
[ovalPath stroke];
UIImage *imageBuffer = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
layer.contents = (id)[imageBuffer CGImage];
}
You can also create a CAShapelayer and than add gesture to the layer as below:
-(void)generateOvalWithSize:(CGSize)size origin:(CGPoint)origin {
CAShapeLayer ovalLayer = [CAShapeLayer layer];
CGMutablePathRef ovalPath = CGPathCreateMutable();
CGPathAddEllipseInRect(ovalPath, NULL, CGRectMake(origin.x, origin.y, size.width, size.height));
CGPathCloseSubpath(ovalPath);
ovalLayer.path = ovalPath;
// Configure the apperence of the circle
ovalLayer.fillColor = [UIColor whiteColor].CGColor;
ovalLayer.strokeColor = [UIColor whiteColor].CGColor;
ovalLayer.lineWidth = 2;
// Add to parent layer
[[self layer] addSublayer:ovalLayer];
}
i have been using these two functions for a while, i haven't come across any issues yet, but if someone sees an issue please let me know.
you can pass anything that is a subclass of UIView (ie. UIButton, UICollectionViewCell, etc.)
+ (void)setCornerRadius:(CGFloat)radius forView:(UIView*)view
{
[view.layer setCornerRadius:radius];
[view.layer setMasksToBounds:YES];
}
+ (void)setBordersForView:(UIView*)view width:(CGFloat)width color:(UIColor*)color
{
view.layer.borderColor = color.CGColor;
view.layer.borderWidth = width;
}
the above yields me the effect below in a collection view:
the collection view cell has a single button which is bound all the way around the edges (auto layout) and takes up the full height and width of the cell.
then i pass in the entire cell (or self.viewForBaseLineLayout if calling from within the cell) as the view parameter in both functions listed above.
for the radius parameter i am passing 20.0f.
(but this value will vary depending on the size the view you are passing; you just have to play around with it)
i know this post is old, but maybe it will help someone new : )
You can use the OBShapedButton class Download Here

Draw a simple vertical bar in iphone

I wanted to draw a vertical single bar graph. I was trying to do it using DrawRect, but could not able to do so. Can nay one hlep me to knwo if this can be done easily by providing start and end point in view to change the color.
thanks
If you have a custom view, it's just a matter of drawing the lines and rectangles that you want. For example:
- (void)drawRect:(CGRect)rect
{
CGAffineTransform t = CGAffineTransformMakeScale(1, -1);
self.transform = t;
CGFloat baseline = 50;
CGFloat inset = 40;
CGFloat barWidth = 20;
CGFloat barHeight = 80;
CGRect r = CGRectMake(inset + barWidth, baseline, barWidth, barHeight);
UIBezierPath *p = [UIBezierPath bezierPathWithRect:r];
[[UIColor redColor] set];
[p fill];
p = [UIBezierPath bezierPath];
[p moveToPoint:CGPointMake(inset, baseline)];
[p addLineToPoint:CGPointMake(inset + 3 * barWidth, baseline)];
[[UIColor blackColor] set];
[p stroke];
}
produces this:
I've created a UIView subclass with the -drawRect: method above and created an instance of that view that's the size of the window. Note that I flipped the coordinate system using a transform -- you don't have to do that, but drawing with the origin at the lower left corner can be easier.
try this one
1. http://www.raywenderlich.com/13271/how-to-draw-graphs-with-core-plot-part-2
2 OVGraph.- a library for the graphs

Drawing animation

I'm creating a simple app where when the user presses a button, a series of lines will be drawn on the screen and the user will be able to see these lines drawn in real time (almost like an animation).
My code looks something like this (has been simplified):
UIGraphicsBeginImageContext(CGSizeMake(300,300));
CGContextRef context = UIGraphicsGetCurrentContext();
for (int i = 0; i < 100; i++ ) {
CGContextMoveToPoint(context, i, i);
CGContextAddLineToPoint(context, i+20, i+20);
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextStrokePath(context);
}
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
My problem is that:
1) As soon as the user presses the button, the UIThread blocks until the drawing is done.
2) I can't get the lines to be drawn on the screen one at a time - I've tried setting the UIImage directly inside the loop and also tried setting a layer content inside the loop.
How do I get around these problems?
You say "just like an animation". Why not do an actual animation, a la Core Graphics' CABasicAnimation? Do you really need to show it as a series of lines, or is a proper animation ok?
If you want to animate the actual drawing of the line, you could do something like:
#import <QuartzCore/QuartzCore.h>
- (void)drawBezierAnimate:(BOOL)animate
{
UIBezierPath *bezierPath = [self bezierPath];
CAShapeLayer *bezier = [[CAShapeLayer alloc] init];
bezier.path = bezierPath.CGPath;
bezier.strokeColor = [UIColor blueColor].CGColor;
bezier.fillColor = [UIColor clearColor].CGColor;
bezier.lineWidth = 5.0;
bezier.strokeStart = 0.0;
bezier.strokeEnd = 1.0;
[self.view.layer addSublayer:bezier];
if (animate)
{
CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
animateStrokeEnd.duration = 10.0;
animateStrokeEnd.fromValue = [NSNumber numberWithFloat:0.0f];
animateStrokeEnd.toValue = [NSNumber numberWithFloat:1.0f];
[bezier addAnimation:animateStrokeEnd forKey:#"strokeEndAnimation"];
}
}
Then all you have to do is create the UIBezierPath for your line, e.g.:
- (UIBezierPath *)bezierPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0.0, 0.0)];
[path addLineToPoint:CGPointMake(200.0, 200.0)];
return path;
}
If you want, you can patch a bunch of lines together into a single path, e.g. here is a roughly sine curve shaped series of lines:
- (UIBezierPath *)bezierPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
CGPoint point = self.view.center;
[path moveToPoint:CGPointMake(0, self.view.frame.size.height / 2.0)];
for (CGFloat f = 0.0; f < M_PI * 2; f += 0.75)
{
point = CGPointMake(f / (M_PI * 2) * self.view.frame.size.width, sinf(f) * 200.0 + self.view.frame.size.height / 2.0);
[path addLineToPoint:point];
}
return path;
}
And these don't block the main thread.
By the way, you'll obviously have to add the CoreGraphics.framework to your target's Build Settings under Link Binary With Libraries.

Irregularly shaped UIBezierPath filling

I'm making some custom control. One of the subviews of the control is transparent UIView with UIBezierPath path drawn on. On the one of the photos there is just let's say border of the UIBezierPath (there's called [path stroke]), but on the second one you can see what happens when I call [path fill]. I'd like the path filled to create shape similar to the one on the first photo. drawRect method from this transparent UIView is below.
- (void)drawRect:(CGRect)rect
{
// Drawing code
[super drawRect:rect];
UIBezierPath *path;
[[UIColor greenColor] setStroke];
[[UIColor greenColor] setFill];
//Angles
CGFloat startAngle = degreesToRadians(225);
CGFloat endAngle = degreesToRadians(315);
CGPoint center = CGPointMake(CGRectGetMidX(rect), lRadius);
path = [UIBezierPath bezierPathWithArcCenter: center radius:lRadius startAngle:startAngle endAngle:endAngle clockwise:YES];
rightEndOfLine = path.currentPoint;
bigArcHeight = rightEndOfLine.y;
CGFloat smallArcHeight = lRadius - bigArcHeight - sRadius;
CGFloat smallArcWidthSquare = (8*smallArcHeight*sRadius) - (4 * (smallArcHeight * smallArcHeight));
smallArcWidth = sqrtf(smallArcWidthSquare);
leftStartOfLine = CGPointMake((rect.size.width - smallArcWidth)/2, lRadius-sRadius + smallArcHeight);
CGFloat lengthOfSpace = (rect.size.width - rightEndOfLine.x);
[path moveToPoint:leftStartOfLine];
[path addArcWithCenter:center radius:sRadius startAngle:startAngle endAngle:endAngle clockwise:YES];
rightStartOfLine = path.currentPoint;
leftEndOfLine = CGPointMake(lengthOfSpace, bigArcHeight);
[path moveToPoint:rightStartOfLine];
[path addLineToPoint:rightEndOfLine];
[path moveToPoint:leftStartOfLine];
[path addLineToPoint:leftEndOfLine];
[path closePath];
[path stroke];
// [path fill];
}
Thanks for help !
Try to remove all of your moveToPoint calls. This is a continuous shape so they are not required, and they are confusing the filling algorithm. You can start at the top left corner, draw the arc clockwise, draw the segment (?) line, draw the arc anticlockwise, then draw the last segment line (or close the path). This will fill properly.

Drawing a rectangle in UIGraphics context does not work

I am trying to overlay an image with some extra information: some text and rectangles. Right now I am stuck at drawing the rectangles. They just won't show up. What am I doing wrong? The image itself is being drawn, so the graphics context must be ok.
- (void)drawTag:(NSString *)tag withRect:(CGRect)rect
{
// Set the color in the current graphics context for future draw operations
[[UIColor yellowColor] setStroke];
[[UIColor yellowColor] setFill];
// Create our drawing path
UIBezierPath* drawingPath = [UIBezierPath bezierPathWithRect:rect];
// actually draw it
[drawingPath stroke];
}
- (IBAction)showDetails:(id)sender
{
// draw the image
UIGraphicsBeginImageContext(self.userImage.size);
// This one shows up:
[self.userImage drawAtPoint:CGPointZero];
// This one does not:
[self drawTag:#"Test" withRect:CGRectMake(10, 10, 50, 50)];
// Show the whole thing:
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.imageViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:self.imageViewController animated:YES];
}
You should set the lineWidth property of UIBezierPath to a value >= 1