Line drawing animation

I am trying to animate a line drawing as follows:

.h

CAShapeLayer *rootLayer; CAShapeLayer *lineLayer; CGMutablePathRef path; 

.m

  path = CGPathCreateMutable(); CGPathMoveToPoint(path, nil, self.frame.size.width/2-100, 260); CGPathAddLineToPoint(path, nil, self.frame.size.width/2+100.0, 260); CGPathCloseSubpath(path); self.rootLayer = [CALayer layer]; rootLayer.frame = self.bounds; [self.layer addSublayer:rootLayer]; self.lineLayer = [CAShapeLayer layer]; [lineLayer setPath:path]; [lineLayer setFillColor:[UIColor redColor].CGColor]; [lineLayer setStrokeColor:[UIColor blueColor].CGColor]; [lineLayer setLineWidth:1.5]; [lineLayer setFillRule:kCAFillRuleNonZero]; [rootLayer addSublayer:lineLayer]; [self performSelector:@selector(startTotalLine) withObject:nil afterDelay:1.5]; - (void)startTotalLine { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"animatePath"]; [animation setDuration:3.5]; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [animation setAutoreverses:NO]; [animation setFromValue:(id)path]; [animation setToValue:(id)path]; [lineLayer addAnimation:animation forKey:@"animatePath"]; } 

The line was drawn before the startTotalLine method was startTotalLine . In addition, the startTotalLine method startTotalLine not affect the row.

I want him to animate the line drawing from right to left.

+7
source share
3 answers

I think the easiest way to do what you want is to present a UIView with a height of 1.5 pixels and an animation of its width. Ask me if I do not understand.

I think your code is not working because your path variable is not a layer property. Read the manuals :

CABasicAnimation provides basic animation with a single key feature for layer properties.

And you are doing something strange here:

 [animation setFromValue:(id)path]; [animation setToValue:(id)path]; 

EDIT: I came across an article and realized what you were trying to achieve! Now I think the reason you failed is because you can animate a path that doesn't change the number of points. And now I thought you could create a route line with two points. At first they are in the same place, and the other way is the line in which you want to end. Now animate from the first path to the second. I think it should work, but I'm not sure.

EDIT: Definitely! You need this guy code. Git link .

+4
source

I would do this with an animated property.

To achieve this, I would create a custom class CALayer - call LineLayer . Define the startPoint property and the length property. Then I would set the length property to "animatable".

The code for this will look something like this:

 // LineLayer.h @interface LineLayer: CALayer @property (nonatomic, assign) int length; // This was omitted from the SO code snippet. @property (nonatomic, assign) CGPoint startPoint; @end // LineLayer.m @implementation LineLayer @synthesize length = _length; // This was omitted from the SO code snippet. @synthesize startPoint= _startPoint; - (id) initWithLayer:(id)layer { if(self = [super initWithLayer:layer]) { if([layer isKindOfClass:[LineLayer class]]) { // This bit is required for when we CA is interpolating the values. LineLayer *other = (LineLayer*)layer; self.length = other.length; self.startPoint = other.startPoint; // This was omitted. } } return self; } + (BOOL)needsDisplayForKey:(NSString *)key { if ([key isEqualToString:@"length"]) { return YES; } return [super needsDisplayForKey:key]; } - (void) setLength:(int)newLength { if (newLength < 0) { return; // Fail early. } _length = newLength; [self setNeedsDisplay]; } /* This should have been drawInContext:(CGContextRef)context - (void) drawRect:(CGRect) rect */ - (void) drawInContext:(CGContextRef)context { //...Do your regular drawing here. // This was omitted from the SO code snippet. CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextSetLineWidth(context, 2); CGContextMoveToPoint(context, _startPoint.x, _startPoint.y); CGContextAddLineToPoint(context, _startPoint.x + _length, _startPoint.y); CGContextStrokePath(context); } @end 

Then in your view controller, you can use LineLayer as follows:

 - (void)viewDidLoad { [super viewDidLoad]; LineLayer *lineLayer = [LineLayer new]; // This was omitted from the SO code snippet. lineLayer.frame = CGRectMake(0, 0, 320, 480); [lineLayer setNeedsDisplay]; // --- lineLayer.startPoint = CGPointMake(0, 100); lineLayer.length = 0; [self.view.layer addSublayer:lineLayer]; // Now animate the changes to the length property CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"length"]; anim.duration = 5; // Change should table about 5 mins. anim.fromValue = [NSNumber numberWithInt:0]; anim.toValue = [NSNumber numberWithInt:200]; [lineLayer addAnimation:anim forKey:@"animateLength"]; lineLayer.length = 200; //Do clean up below... } 

Happy coding :)

+6
source

Here is my solution for your case using "UIBezierPath", "CAShapeLayer" and the "strokeEnd" property:

.m file

 @synthesize shapeLayer; [self drawLine]; -(void)drawLine { CGFloat X1 = self.frame.size.width/2-100; CGFloat Y1 = 260; CGFloat X2 = self.frame.size.width/2+100.0; CGFloat Y2 = 260; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(X1, Y1)]; [path addLineToPoint:CGPointMake(X2, Y2)]; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [path CGPath]; shapeLayer.strokeColor = [[UIColor blueColor] CGColor]; shapeLayer.lineWidth = 1.5; shapeLayer.fillColor = [[UIColor redColor] CGColor]; shapeLayer.strokeEnd =0; [self.layer addSublayer:shapeLayer]; [self performSelector:@selector(startTotalLine) withObject:nil afterDelay:1.5]; } - (void)startTotalLine { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; animation.duration = 3.5f; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [animation setAutoreverses:NO]; [animation setFromValue:[NSNumber numberWithInt:0]]; [animation setToValue:[NSNumber numberWithInt:1]]; [shapeLayer addAnimation:animation forKey:@"animatePath"]; } 

The default value of "strokeEnd" is 1, so make it 0 at the beginning (the line will not appear). Btw, here are some useful examples: http://jamesonquave.com/blog/fun-with-cashapelayer/

+1
source

All Articles