CAShapeLayer
In a nutshell: CAShapeLayer can generate a graph based on a path drawn by a Bezier curve
Comprehensive example
- rendering
-
Analysis of key technical points
-
The key point of analyzing QQ stickiness animation is how to draw the shape between 2 circles when the gesture is dragged
Answer: A mathematical abstraction of the shape formed between two circles at some point in time.
- How to perform explosion animation when dragging beyond a certain range
UIImageView can perform frame animations, similar to Flash effects
The key code
- (void)pan:(UIPanGestureRecognizer *)pan{// transP = [pan translationInView:self]; // The transform does not change its center (center is the position of the layer), but changes the frame NSLog(@)"Offset :%@",NSStringFromCGPoint(transP)); CGPoint center = self.center; center.x += transP.x; center.y += transP.y; self.center = center; //self.transform = CGAffineTransformTranslate(self.transform, transP.x, transP.y); // Gesture reset: set the last coordinate [pan]setTranslation:CGPointZero inView:self];
CGFloat distance = [self distanceWith:self.smallCircle bigCircle:self];
NSLog(@"%f",distance);
CGFloat smallCircleRadius = self.bounds.size.width * 0.5;
smallCircleRadius = smallCircleRadius - distance/10;
if (smallCircleRadius < 3) {
smallCircleRadius = 3;
}
self.smallCircle.bounds = CGRectMake(0, 0, smallCircleRadius*2, smallCircleRadius*2);
self.smallCircle.layer.cornerRadius = smallCircleRadius;
if(self. SmallCircle. Hidden = = NO) {/ / returns an irregular path UIBezierPath * path = [self drawTracertWithSmallCircle: self. SmallCircle bigCircle:self]; // convert the shape to a shapeLayer self.shapelayer. path = path.cgpath; / / create shape layer shape was generated according to path} / / [self. Superview. Layer insertSublayer: self. ShapeLayer atIndex: 0];if (distance > 60) {
self.smallCircle.hidden = YES;
[self.shapeLayer removeFromSuperlayer];
}
if(pan) state = = UIGestureRecognizerStateEnded) {/ / end gesturesif (distance < 60) {
[self.shapeLayer removeFromSuperlayer];
self.center = self.smallCircle.center;
self.smallCircle.hidden = NO;
}
else{/ / it will play an animated gestures to drag and drop more than 60 UIImageView * imageView = [[UIImageView alloc] initWithFrame: self. The bounds]; NSMutableArray *images = [NSMutableArray array];for (int i=0; i<8; i++) {
NSString *imageName = [NSString stringWithFormat:@"%d",i+1];
UIImage *image = [UIImage imageNamed:imageName];
[images addObject:image];
}
imageView.animationImages = images;
[imageView setAnimationDuration:1]; [imageView startAnimating]; [self addSubview:imageView]; Dispatch_after (dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), dispatch_get_main_queue(), ^{ [self removeFromSuperview]; }); } } } - (CGFloat )distanceWith:(UIView *)smallCircle bigCircle:(UIView *)bigScirle{ CGFloat offsetX = bigScirle.frame.origin.x - smallCircle.frame.origin.x; CGFloat offsetY = bigScirle.frame.origin.y - smallCircle.frame.origin.y;returnsqrt( pow(offsetX, 2) + pow(offsetY, 2)); } / / to run two circular trajectory using code simulation - (UIBezierPath *) drawTracertWithSmallCircle: (UIView *) smallCircle bigCircle bigCircle: (UIView *) { CGFloat X1 = smallCircle.center.x; CGFloat X2 = bigCircle.center.x; CGFloat Y1 = smallCircle.center.y; CGFloat Y2 = bigCircle.center.y; CGFloat r1 = smallCircle.bounds.size.width/2; CGFloat r2 = bigCircle.bounds.size.width/2; CGFloat d = [self distanceWith:smallCircle bigCircle:bigCircle]; // ø represents the Angle CGFloat Sinø = (X2 - X1)/d; CGFloat Cos ø = (y2-y1)/d; CGPoint pointA = CGPointMake(X1 - R1 *Cos ø, Y1 + R1 *SinØ); CGPoint pointB = CGPointMake(X1 + R1 *Cos ø, Y1 - R1 *SinØ);
CGPoint pointC = CGPointMake(X2 + r2*CosØ, Y2 - r2*SinØ); CGPoint pointD = CGPointMake(X2 - r2*Cos ø, Y2 + R2 *SinØ);
CGPoint pointO = CGPointMake(X1 + Sinø ø d/2, Y1 + Cos ø d/2); CGPoint pointP = CGPointMake(X1 + Sinø ø d/2,Y1 + Cos ø d/2); UIBezierPath *path = [UIBezierPath bezierPath]; //AB [path moveToPoint:pointA]; [path addLineToPoint:pointB]; / / BC (curve) [path addQuadCurveToPoint: pointC controlPoint: pointP]; //CD [path addLineToPoint:pointD]; / / DA (curve) [path addQuadCurveToPoint: pointA controlPoint: pointO];return path;
}
Copy the code
Complete code, Github address