Reputation: 1307
Hi all I am looking into ways of how I can draw a shape like the one in the illustration above.I have been looking and reading but getting slightly confused of how curves are drawn using UIBezierPath. I found really nice code which uses CAShapeLayer with animation to draw lines.
The code so far I have is :
@synthesize animationLayer = _animationLayer;
@synthesize pathLayer = _pathLayer;
@synthesize penLayer = _penLayer;
- (void) setupDrawingLayer
{
if (self.pathLayer != nil) {
[self.penLayer removeFromSuperlayer];
[self.pathLayer removeFromSuperlayer];
self.pathLayer = nil;
self.penLayer = nil;
}
CGPoint upperCurve = CGPointMake(101, 100);
CGPoint lowerCurve = CGPointMake(224,200);
UIBezierPath *path = [UIBezierPath bezierPath];
path.lineCapStyle = kCGLineCapRound;
path.miterLimit = -10.0f;
path.lineWidth = 10.0f;
[path moveToPoint:lowerCurve];
[path addQuadCurveToPoint:upperCurve controlPoint:lowerCurve];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.animationLayer.bounds;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = 10.0f;
pathLayer.lineJoin = kCALineJoinBevel;
[self.animationLayer addSublayer:pathLayer];
self.pathLayer = pathLayer;
}
-(void) startAnimation
{
[self.pathLayer removeAllAnimations];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 10.0;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[self.pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.animationLayer = [CALayer layer];
self.animationLayer.frame = CGRectMake(20.0f, 64.0f,
CGRectGetWidth(self.view.layer.bounds) - 40.0f,
CGRectGetHeight(self.view.layer.bounds) - 84.0f);
[self.view.layer addSublayer:self.animationLayer];
[self setupDrawingLayer];
[self startAnimation];
}
Upvotes: 0
Views: 1229
Reputation: 2113
A UIBezierPath generally starts with moveToPoint to set the starting point of the curve. Then it's followed by any number of curve segments using these methods: – addLineToPoint: – addArcWithCenter:radius:startAngle:endAngle:clockwise: – addCurveToPoint:controlPoint1:controlPoint2: – addQuadCurveToPoint:controlPoint:
You didn't state specifically what you're having trouble with, so I'm going to make a leap and assume it is addCurveToPoint:controlPoint1:controlPoint2 that you are struggling with.
The segment added by this call draws a segment starting at the most recently added or moved to point in the curve to the first argument. How it undulates is determined by the control points.
The simplest way to understand how it undulates is to imagine lines connecting the first point (established in the previous method call) to the first control point (let's call this control point line segment 1), and another line connecting the first argument (ending point of the segment being added) to the second control point (let's call this control point line segment 2).
The Bezier curve at the starting point is tangent to control point line segment 1. It is tangent to control point line segment 2 at the end of the curve.
So if you want to draw a curve with multiple Beziers such that they form a smooth line, you need to make sure that the slope of control point line segment 2 of one curve is the same as the slope of control point line segment 1 of the next curve that joins to it.
The distances from the starting point to the first control point, and the ending point to the second control point determine the curvature of the curve.
A friend of mine imagines it this way. Imagine a space ship traveling from point A to point B. The space ship starts out with a heading determined by the slope of control point line segment 1 and a speed determined by its length. The heading is gradually changed to the slope of control point line segment 2. Meanwhile, the speed is gradually changed to the length of of control point line segment 2. By the time the space ship arrives at point B, it is traveling tangent to that segment.
Upvotes: 1
Reputation: 534885
The way I solve this kind of problem is to draw the shape in a drawing program such as Illustrator. This shows clearly where the bezier curve points need to go in order to get the curve I'm after.
Upvotes: 1