Hi everybody meet with everybody again, today to share with everyone is the realization of Douyin’s point like animation, no more nonsense said above### This article mainly contains technical points:

CAShapeLayer and Bezier curves draw triangles

  • Time tricks for composing animations
  • I used to finish writing the demo attached to the bottom of the article, if you do not want to see the principle of friends can directly jump to the bottom to find a demo download.

First let’s break down the animation in detail

Please watch carefully

Let’s look at a single animation

Watch carefully as I set a duration of 10 seconds so you can see it clearly

From the above two pictures, we can see that it is a Bessel curve of a triangleSuch animations need to go through:

  • 2 PI (360°) rotates once
  • A circle has a total of six triangular bezier curve shapes per week.
  • An animation group contains the zoom animation from 0 to 1, if the animation executes 10 seconds, then the scale animation executes 10*0.2 = 2 seconds, the animation group also contains another animation is from the end of the animation position to the end of the vanishing position size change until the animation disappears.
  • Create a triangle of the figure above every 60° along the circle.

The keypath of the CABasicAnimation and the keypath of the CABasicAnimation are applied to a triangle and six triangles are created.

And it ends up going something like thisThe end is actually a transition from the path of the last animation to the path of three points on a line, until the end is hidden and disappeared.

Ok, so let’s implement this animation

Note: the background ❤️ red heart is a picture outside the scope of this article

Code implementation First we subclass a ZanLikeView that inherits from UIView and set the image at the bottom and click to transform the ❤️ image, which is just two UIImageViews with gestures, and when you click, differentiate the tags of different views to know which ImageView you click on, so you can animate two different effects, no You can refer to the demo.

I’ll focus on the core code

Create a CAShapeLayer to animate shapes and graphics.

CAShapeLayer *layer = [[CAShapeLayer alloc]init];
layer.position = _likeBefore.center;
layer.fillColor = [UIColor redColor].CGColor;
Copy the code

Color can eventually expose the interface

The for loop creates one of these triangles for every 30° Angle. We need to create 6 and loop 6 times

Create a Bessel path for the initial location

CGFloat length = 30; CGFloat duration = 0.5 f; for(int i = 0 ; i < 6; i++) { CAShapeLayer *layer = [[CAShapeLayer alloc]init]; layer.position = _likeBefore.center; layer.fillColor = [[UIColor redColor].CGColor; //... 1 //... 2 //... 3 }Copy the code

Here we create a total of 6 instances of shapeLayer and fill them with colors. Here we fill them with red and the other colors are self-packaging. _likeBefore is the ❤️ background view (UIImageView) that we see in white.

Here at / /… Add the following code where 1

UIBezierPath *startPath = [UIBezierPath bezierPath];
[startPath moveToPoint:CGPointMake(-2, -length)];
[startPath addLineToPoint:CGPointMake(2, -length)];
[startPath addLineToPoint:CGPointMake(0, 0)];
Copy the code

This line of code adds up to something like thisThen we need to pass the path to layer.path. Remember to change to CGPath

layer.path = startPath.CGPath; Layer. The transform = CATransform3DMakeRotation (M_PI / 3.0 f * I, 0.0, 0.0, 1.0); [self.layer addSublayer:layer]Copy the code

Note: CATransform3DMakeRotation () function when x, y, z value is 0, the representative does not rotate in the axial direction, the duty to 1, to represent counterclockwise in the axial direction, the duty to 1, to represent clockwise in the axial direction

Since we need 60° to create a layer, we need clockwise M_PI / 3.0f = 60°. Each loop creates the NTH Angle times 60 degrees.

Then, in / /… 2 Add the following code

CAAnimationGroup *group = [[CAAnimationGroup alloc] init]; group.removedOnCompletion = NO; group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; group.fillMode = kCAFillModeForwards; group.duration = duration; CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; ScaleAnim. FromValue = @ (0.0); ScaleAnim. ToValue = @ (1.0); Duration = duration * 0.2f; scaleanim. duration = duration * 0.2f; // Note that the scaling is performed 0.2f before the time length is givenCopy the code

Duration * 0.2 = 2; duration * 0.2 = 2;

Finally in the / /… The code output of 3 plus the following code

UIBezierPath *endPath = [UIBezierPath bezierPath]; [endPath moveToPoint:CGPointMake(-2, -length)]; [endPath addLineToPoint:CGPointMake(2, -length)]; [endPath addLineToPoint:CGPointMake(0, -length)]; CABasicAnimation *pathAnim = [CABasicAnimation animationWithKeyPath:@"path"]; pathAnim.fromValue = (__bridge id)layer.path; pathAnim.toValue = (__bridge id)endPath.CGPath; Pathanim.begintime = duration * 0.2f; Duration = duration * 0.8f; pathanim. duration = duration * 0.8f; [group setAnimations:@[scaleAnim, pathAnim]]; [layer addAnimation:group forKey:nil];Copy the code

The intention of these lines of code is to transition from the path of our last layer to the path of our end, and note that the start time pathanim. beginTime is duration * 0.2 The transition starts at the end of the last animation, and the remaining duration of the transition is Duration * 0.8. Then the two consecutive animations are finished, and finally the animation is added to the animation group and added to layer.

Below is an animation of the transition from start to finish.The rest of the work is to do a normal animation basically nothing.

[UIView animateWithDuration: 0.35 f delay: 0.0 f options: UIViewAnimationOptionCurveEaseIn animations: ^ { Self. LikeAfter. Transform = CGAffineTransformScale (CGAffineTransformMakeRotation (- M_PI_4), 0.1 f, 0.1 f);  } completion:^(BOOL finished) { [self.likeAfter setHidden:YES]; self.likeBefore.userInteractionEnabled = YES;  self.likeAfter.userInteractionEnabled = YES; }];Copy the code

skills

End animation start time and end time control, just right.

conclusion

The details of animation implementation need to be studied, learned and practiced. Here I would like to thank the open-source author’s code for giving ideas. I personally wrote code verification and added relevant external interfaces by learning and imitating principles.

Citation: Original address