Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw bullet arrow in Core Graphics

I don't want to reinvent the wheel unless absolutely necessary, so I wanted to see how I would go about drawing an arrow like this with Core Graphics:

enter image description here

Does anyone know how I can get started with this? This is what I have so far, but it draws a regular triangle instead of a bracket shape:

    CGPoint origin = CGPointMake(100, 20);
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:origin];
    [path addLineToPoint:CGPointMake(origin.x-10, origin.y-20)];
    [path addLineToPoint:CGPointMake(origin.x-10, origin.y+20)];
    [[UIColor redColor] set];
    [path fill];
like image 990
Snowman Avatar asked Dec 12 '22 03:12

Snowman


2 Answers

If you draw with strokes as suggested by @NSGod, you need to move to the upper or lower tip, and then line to the arrow head, then line to the lower or upper tip. If you want a 45 degree angle like the one you drew, the amount you add to or subtract from the coordinates should be equal.

You will also need to set the line width for the path. This will need to be proportional to the size.

CGPoint origin = CGPointMake(100, 20);

UIBezierPath *path = [UIBezierPath bezierPath];
// Upper tip
[path moveToPoint:CGPointMake(origin.x+20, origin.y-20)];
// Arrow head
[path addLineToPoint:CGPointMake(origin.x, origin.y)];
// Lower tip
[path addLineToPoint:CGPointMake(origin.x+20, origin.y+20)];

[[UIColor redColor] set];
// The line thickness needs to be proportional to the distance from the arrow head to the tips.  Making it half seems about right.
[path setLineWidth:10];
[path stroke];

The result is a shape like this.

Arrow drawn by code above

If you want to fill, not stroke - which may be necessary if you want to outline your arrow - you will need to plot out 6 points and then close the path.

like image 171
Cowirrie Avatar answered Jan 02 '23 17:01

Cowirrie


One potential part of the problem is that you were using fill instead of stroke.

By changing [path fill] to [path stroke], you'd have gotten this:

CGPoint origin = CGPointMake(100, 20);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:origin];
[path addLineToPoint:CGPointMake(origin.x - 10, origin.y - 20)];
[path addLineToPoint:CGPointMake(origin.x - 10, origin.y + 20)];
[[UIColor redColor] set];
// [path fill];
[path stroke];

enter image description here

This raises the question of what you intended by the origin point. It would really translate to the arrow point rather than the traditional sense of how origin is used (would mean the upper left corner of the object being drawn).

If you want to keep your meaning of origin, you'd need to modify the code to be the following:

CGPoint origin = CGPointMake(100, 20);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(origin.x - 20, origin.y - 20)];
[path addLineToPoint:origin];
[path addLineToPoint:CGPointMake(origin.x - 20, origin.y + 20)];
path.lineWidth = 4.0;
[[UIColor redColor] set];
[path stroke];

Or, if you want to use the traditional meaning of origin, you could use:

CGPoint origin = CGPointMake(100, 20);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:origin];
[path addLineToPoint:CGPointMake(origin.x + 20, origin.y + 20)];
[path addLineToPoint:CGPointMake(origin.x, origin.y + 20 * 2)];
path.lineWidth = 4.0;
[[UIColor redColor] set];
[path stroke];

This produces the following:

enter image description here

like image 32
NSGod Avatar answered Jan 02 '23 17:01

NSGod