IOS: CAShapeLayer for drawing an indirect image and animating its shape

I read the documentation on CAShapeLayer , but I still do not quite understand. In my opinion, Layer always flat, and its size is always a rectangle.

CAShapeLayer , on the other hand, allows you to define a layer that not only looks like a rectangle. It can be a circle, triangle, etc., while you use it with UIBezierPaths .

Is my understanding here?

What I had in mind was, for example, a tennis ball that bounces off the edges of the screen (simple enough), but I would like to show a little animation that does not use image animation - I would like it to show a little โ€œcompressibleโ€ like an animation when it hits the edge of the screen and then bounces. I do not use the image of a tennis ball. Just a yellow circle.

Will I fix CAShapeLayer here to accomplish this? If so, can you give an example of litle? Thanks.

+6
source share
1 answer

As long as you use the path to determine the shape of the layer, it is still created using the rectangle used to define the border / borders. Here is an example to get you started:

TennisBall.h:

 #import <UIKit/UIKit.h> @interface TennisBall : UIView - (void)bounce; @end 

TennisBall.m:

 #import <QuartzCore/QuartzCore.h> #import "TennisBall.h" @implementation TennisBall + (Class)layerClass { return [CAShapeLayer class]; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupLayer]; } return self; } /* Create the tennis ball */ - (void)setupLayer { CAShapeLayer *layer = (CAShapeLayer *)self.layer; layer.strokeColor = [[UIColor blackColor] CGColor]; layer.fillColor = [[UIColor yellowColor] CGColor]; layer.lineWidth = 1.5; layer.path = [self defaultPath]; } /* Animate the tennis ball "bouncing" off of the side of the screen */ - (void)bounce { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; animation.duration = 0.2; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; animation.fromValue = (__bridge id)[self defaultPath]; animation.toValue = (__bridge id)[self compressedPath]; animation.autoreverses = YES; [self.layer addAnimation:animation forKey:@"animatePath"]; } /* A path representing the tennis ball in the default state */ - (CGPathRef)defaultPath { return [[UIBezierPath bezierPathWithOvalInRect:self.frame] CGPath]; } /* A path representing the tennis ball is the compressed state (during the bounce) */ - (CGPathRef)compressedPath { CGRect newFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width * 0.85, self.frame.size.height); return [[UIBezierPath bezierPathWithOvalInRect:newFrame] CGPath]; } @end 

Now that you want to use this:

 TennisBall *ball = [[TennisBall alloc] initWithFrame:CGRectMake(10, 10, 100, 100)]; [self.view addSubview:ball]; [ball bounce]; 

Please note that this will need to be expanded so that you can โ€œbounceโ€ from different angles, etc., but this should make you point in the right direction!

+14
source

Source: https://habr.com/ru/post/946845/


All Articles