Process of animating paths using Quart2D - ios

I am new to using Quartz2D, and to start small I wanted to draw a line, but have that line be animated from start to finish. From the blogs I have read and similar questions I have looked at, it seems I need to set a path for layer, and animate on that layer. The problem for me is, even though a layer has a path property, I am unsure how to go about properly settings up a path for it.
I have a UIView displaying, and it shows a line just fine if I comment out the animation code.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 300, 400);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = 10.0;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
//[aLayer addAnimation:pathAnimation forKey:#"strokeEndAnimation"];
What do I need to do to animate a line from start to finish?

Here is what I've used to animate a line being drawn, make sure to import Quartz of course:
//Create the bezier path that will hold all the points of data
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[[UIColor greenColor] setFill];
[bezierPath fill];
[[UIColor redColor] setStroke];
[bezierPath stroke];
for (int i = 10 ; i < 20; i++) {
//If its the first point we need to make sure and move to that point not add to it
if (i == 10)
[bezierPath moveToPoint: CGPointMake(10, 10)];
else
[bezierPath addLineToPoint: CGPointMake(i * 2, i * 3)];
}
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.fillColor = nil;
shapeLayer.lineWidth = 10.0f;
shapeLayer.lineJoin = kCALineJoinRound;
shapeLayer.path = bezierPath.CGPath;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = 10.0;
pathAnimation.fromValue = #(0.0f);
pathAnimation.toValue = #(1.0f);
[shapeLayer addAnimation:pathAnimation forKey:#"strokeEnd"];
[self.view.layer addSublayer:shapeLayer];

Related

Animation for Layer in iOS

I masked an image with BezierPath.
I want to animate that mask image.
My code is as follow:
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(84.95, 205.11)];
[bezierPath addCurveToPoint: CGPointMake(122.89, 232.14) controlPoint1: CGPointMake(84.95, 205.11) controlPoint2: CGPointMake(110.81, 223.56)];
[bezierPath addCurveToPoint: CGPointMake(124.33, 233.04) controlPoint1: CGPointMake(123.37, 232.46) controlPoint2: CGPointMake(123.85, 232.78)];
[bezierPath closePath];
CAShapeLayer *maskImage = [CAShapeLayer layer];
maskImage.path = bezierPath.CGPath;
maskImage.fillColor = [[UIColor blackColor] CGColor];
_myImageView.layer.mask = maskImage;
CAShapeLayer *border = [CAShapeLayer layer];
border.path = bezierPath.CGPath;
border.strokeColor = [UIColor redColor].CGColor;
border.fillColor = [[UIColor clearColor] CGColor];
border.lineWidth = 5;
[_myImageView.layer addSublayer:border];
How can I animate this?
Thank you
Use following piece of code:
#property (nonatomic, retain) CAShapeLayer *animationLayer;
- (IBAction)drawPattern:(id)sender{
[self setup];
[self.animationLayer removeAllAnimations];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = 10.0;
pathAnimation.fromValue = #(0);
pathAnimation.toValue = #(1);
[self.animationLayer addAnimation:pathAnimation forKey:#"strokeEnd"];
}
- (void)setup{
[self.animationLayer removeFromSuperlayer];
self.animationLayer = nil;
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(84.95, 205.11)];
[bezierPath addCurveToPoint: CGPointMake(122.89, 232.14) controlPoint1: CGPointMake(84.95, 205.11) controlPoint2: CGPointMake(110.81, 223.56)];
[bezierPath addCurveToPoint: CGPointMake(124.33, 233.04) controlPoint1: CGPointMake(123.37, 232.46) controlPoint2: CGPointMake(123.85, 232.78)];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
// provide frame & bounds so that path can be drawn over that.
pathLayer.frame = CGRectMake(35, 100, 250, 200);
pathLayer.bounds = CGRectMake(35, 100, 250, 200);
pathLayer.path = bezierPath.CGPath;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.fillColor = [[UIColor clearColor] CGColor];
pathLayer.lineWidth = 6.f;
pathLayer.lineJoin = kCALineJoinRound;
[self.view.layer addSublayer:pathLayer];
[self setAnimationLayer:pathLayer];
}
Please let me know if this works for you & also if anything else comes up.
At the end of your code try below one
CAShapeLayer *pathLayer;
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [aPath CGPath];
shapeLayer.strokeColor = [[UIColor greenColor] CGColor];
shapeLayer.fillColor = nil;
shapeLayer.lineWidth = 5.0f;
shapeLayer.lineJoin = kCALineJoinBevel;
[myImageView.layer addSublayer:shapeLayer];
pathLayer = shapeLayer;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = 3.0;
pathAnimation.fromValue = #(0.0f);
pathAnimation.toValue = #(1.0f);
[pathLayer addAnimation:pathAnimation forKey:#"strokeEnd"];
We can animate the image with path using CABasicAnimation.
CABasicAnimation has position,path,transform,opacity,shadow......which including all layers keypaths,shape layer keypaths,CA layer keypaths,Text layer keypaths,Mask layer keypaths,UIView layer keypaths,Effect,Emit and replicator keypaths.
According to your question for drawing path we can use path and strokeEnd.But most prepare strokeEnd for accessing shape style properties.
So I think strokeEnd is the best one for animating the mask image with bezier path.
Below I give the code for path and strokeEnd also I diffrecicate both.
If I use animationWithKeyPath is path
The shape to be rendered and animatable.It is specifying the shape path.
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"path"];
animation.fromValue = #(0);
animation.toValue = #(1);
animation.duration = 6.0f;
[maskImage addAnimation:animation forKey:#"animatePath"];
The Path is a collection of individual components like lines and arcs that can be drawn and also animated.It is fundamental concept of Quartz 2D.
In below code I use strokeEnd
Generally if we want to access the shape style properties we can use
strokeEnd
The relative location at which to stop stroking the path and animatable.
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
animation.fromValue = #(0);
animation.toValue = #(1);
animation.duration = 6.0f;
[maskImage addAnimation:animation forKey:#"strokeEnd"];
The value of this property must be in the range 0.0 to 1.0. The default value of this property is 1.0.
Also strokeEnd defines following thing
Combined with the strokeStart property, this property defines the subregion of the path to stroke. The value in this property indicates the relative point along the path at which to finish stroking while the strokeStart property defines the starting point.

CAShapeLayer fillcolor arc animation not working

I am using below code to draw a Pie slice layer with CAShapeLayer.
CGFloat endAngle = (M_PI*2/5)-M_PI_2;
CAShapeLayer *outerBorderCircle = [CAShapeLayer layer];
int outerradius = self.frame.size.width/2;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(outerradius, outerradius)];
[path addLineToPoint:CGPointMake(outerradius, self.outerCircleBorder)];
[path addArcWithCenter:CGPointMake(outerradius,outerradius) radius:outerradius-self.outerCircleBorder startAngle:-M_PI_2 endAngle:endAngle clockwise:YES];
[path closePath];
outerBorderCircle.path = path.CGPath;
outerBorderCircle.fillColor = [UIColor whiteColor].CGColor;
outerBorderCircle.strokeColor = self.borderShadowColor.CGColor;
outerBorderCircle.lineWidth = self.outerCircleBorder;
outerBorderCircle.lineJoin = kCALineJoinRound;
outerBorderCircle.zPosition = MAXFLOAT;
CABasicAnimation *startanimation = [CABasicAnimation animationWithKeyPath:#"fillColor"];
startanimation.removedOnCompletion = YES;
startanimation.fromValue = (id)[[UIColor clearColor] CGColor];
startanimation.toValue = (id)[[UIColor whiteColor] CGColor];
startanimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
startanimation.duration = 10.0;
[startanimation setFillMode:kCAFillModeBoth];
[outerBorderCircle addAnimation:startanimation forKey:#"fillColor"];
[self.layer addSublayer:outerBorderCircle];
But animation part working as fade in fade out. But i need to animate arc kind of animation.
Please help me.
To animate the stroke you should animate those properties:
-strokeStart
-strokeEnd
From the documentation:
Combined with the strokeEnd property, this property defines the
subregion of the path to stroke. The value in this property indicates
the relative point along the path at which to begin stroking while the
strokeEnd property defines the end point. A value of 0.0 represents
the beginning of the path while a value of 1.0 represents the end of
the path. Values in between are interpreted linearly along the path
length.
[UPDATE]
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
drawAnimation.duration = timeInSeconds;
drawAnimation.fromValue = [NSNumber numberWithFloat:startAngle];
drawAnimation.toValue = [NSNumber numberWithFloat:endAngle];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[circle addAnimation:drawAnimation forKey:#"drawCircleAnimation"];
Credits to Rob Mayoff

how to create a line graph with multiple lines and different colors using bezierpath

I created one bezierpath and added that to cashapelayer but i cant able to change the color of path
//create path
UIBezierPath *graphPath = [[UIBezierPath alloc]init];
[graphPath setLineWidth:30];
[[UIColor blackColor] setStroke];
[graphPath moveToPoint:CGPointMake(30 , 30)];
[graphPath addLineToPoint:CGPointMake(30,600)];
[graphPath addLineToPoint:CGPointMake(380, 600)];
//adding path to layer
CAShapeLayer *graphLayout = [CAShapeLayer layer];
graphLayout.frame = CGRectMake(0, 65, VIEW_WIDTH, VIEW_HEIGHT);
graphLayout.fillColor = [[UIColor clearColor] CGColor];
graphLayout.strokeColor = [UIColor redColor].CGColor;
graphLayout.lineWidth = 2;
graphLayout.path = [graphPath CGPath];
[self.layer addSublayer:graphLayout];
//animation
drawAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
drawAnimation.duration = 3;
drawAnimation.repeatCount = 1.0;
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[graphLayout addAnimation:drawAnimation forKey:#"drawCircleAnimation"];

CAShaperLayer outlook change at initial point?

I have made the Circle like this in my iOS Demo App.
http://www.pastebin.ca/3119326
like below image
I want a needle shape crossing 90 degree to line which is being made. like below image, which I am unable to find via code.
How can achieve this, any suggestion.
Thanks.
Pseudo Code/Real Code, here's how the layout would work, just a quick sample:
a line:
UIBezierPath* bezierPath = UIBezierPath.bezierPath;
[bezierPath moveToPoint: CGPointMake(43.5, 30.5)];
[bezierPath addCurveToPoint: CGPointMake(166.5, 74.5) controlPoint1: CGPointMake(166.5, 74.5) controlPoint2: CGPointMake(166.5, 74.5)];
[UIColor.blackColor setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];
CAShapeLayer * firstNameCorners = [CAShapeLayer layer];
[firstNameCorners setPath:bezierPath];
[[self.view layer] addSublayer:firstNameCorners];
run spin animation:
- (void)spinUntilYouThrowUp:(CAShapeLayer*)shapeLayer duration:(CGFloat)duration rotations:(CGFloat)rotations repeat:(float)repeat;
{
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = repeat;
[shapeLayer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
}

Animating CAShapeLayer to follow the lline of UIBezierPath

I an trying to animate the stroke of a UIBezierPath, as if drawing with a pencil.
However, I am finding that the layer seems to be creating an entire shape by connecting my first and last points on the curve -- and this is not what I want. I simply want a line of stroke 2.0 to animate. Here is my code:
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(20.0f, 20.f)];
[path addLineToPoint:CGPointMake(20.f, 200.f)];
CGFloat radius = 6.f;
[path addArcWithCenter:CGPointMake(20.f + radius, 200.f) radius:radius startAngle:M_PI endAngle:M_PI/2 clockwise:NO];
[path addLineToPoint:CGPointMake(240, 200.f+radius)];
[path addLineToPoint:CGPointMake(240.f, 480.f)];
[path stroke];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor redColor] CGColor];
shapeLayer.lineWidth = 2.0;
[self.scrollView.layer addSublayer:shapeLayer];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
pathAnimation.duration = 4.f;
pathAnimation.fromValue = #(0.0f);
pathAnimation.toValue = #(1.0f);
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.6 :0.3 :0.8 :0.45];
[shapeLayer addAnimation:pathAnimation forKey:#"strokeEnd"];
and here is what it looks like:

Resources