Implementation of unread bubble drag and drop in QQ (refer to the idea of a young hacker), bubble drag and drop
Link to the original article: http://kittenyang.com/drawablebubble/. the boss is very thoughtful. He is very admired for his age!
First, analyze the drag-and-drop graphs, such as large circles and irregular graphs (in fact, they cannot be drawn normally, but here they are just representative) and small circles. Yes. The effect of dragging is the result of these three parts. The main circle of the blogger uses the irregular UIView image CAShapeLayer, and the circle is also the UIView. When I implemented it myself, I found that the big circle uses UIView, and the circle and the middle part can be drawn using CAShapeLayer. CAHShapeLayer knows to pass a path to it, and it can generate layers of any shape based on the path. Therefore, we are actually building this path using the beiser curve. This path is not the foundation of our predecessors for people who have been in college for four years. It is estimated that this idea is not enough.
The following describes how to construct the six points A, B, C, D, O, and P, create A path, generate A layer for CAShapeLayer.
The following code is used:
Processing gesture
/** Processing gesture */-(void) panGesture :( UIPanGestureRecognizer *) gesture {// self. the parent view CGPoint newCenter = [gesture locationInView: self. containerView]; self. bubbleView. center = newCenter; if (gesture. state = UIGestureRecognizerStateBegan) {// start to remove the animation [self. bubbleView. layer removeAllAnimations];} else if (gesture. state = UIGestureRecognizerStateChanged) {// distance from the center of the circle> = distance from the broken if (centerDistance> = self. maxDistance) {// remove shapeView [self. shapeLayer removeFromSuperlayer];} else {// update the shape of the beiser curve shapeView [self updateCoordinate: newCenter];} else if (gesture. state = UIGestureRecognizerStateCancelled | gesture. state = UIGestureRecognizerStateEnded | gesture. state = UIGestureRecognizerStateFailed) {// greater than the set value and implement the block, run the block if (centerDistance> = self. maxDistance & self. breakComplete) {self. breakComplete ();} else {// let the ball back to its initial point [UIView animateWithDuration: 0.5 delay: 0 usingSpringWithDamping: 0.4 initialSpringVelocity: 0 options: Unknown animations: ^ {self. bubbleView. center = initBubbleCenter;} completion: ^ (BOOL finished) {// return the ball to the center of the initial point, and return the distance from the center to centerDistance = 0; if (finished & self. achieveAnimation) {[self animationForBubbleView] ;}];} [self. shapeLayer removeFromSuperlayer];}
The drag of the gesture causes the center of the circle to be updated. In this way, the six points A, B, C, D, O, and P are updated with the new path. For CAShapeLayer, if you pass it a new path, it will update its shape.
/** Update ABCDOP6 points based on the new center point to make the CAShapeLayer path */-(void) updateCoordinate :( CGPoint) currentCenter {CGFloat x2 = currentCenter. x; CGFloat y2 = currentCenter. y; CGFloat x1 = initBubbleCenter. x; CGFloat y1 = initBubbleCenter. y; // distance from the center of the current center at the center of the initial point to centerDistance = sqrt (x2-x1) * (x2-x1) + (y2-y1) * (y2-y1 )); // update the radius of the circle at the initialization Center (decreases as the drag distance increases to the specified distance) if (centerDistance = 0) {cos = 1; sin = 0;} else {cos = (y2-y1)/centerDistance; sin = (x2-x1)/centerDistance;} r1 = r2 * (1-(centerDistance/self. maxDistance) * self. modulus); A = CGPointMake (x1-r1 * cos, y1 + r1 * sin); B = CGPointMake (x1 + r1 * cos, y1-r1 * sin ); C = CGPointMake (x2 + r2 * cos, y2-r2 * sin); D = CGPointMake (x2-r2 * cos, y2 + r2 * sin); O = CGPointMake (. x + centterdistance/2.0 * sin,. y + centerDistance/2.0 * cos); P = CGPointMake (B. x + centerDistance/2.0 * sin, B. y + centerDistance/2.0 * cos); UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter: initBubbleCenter radius: r1 startAngle: 0 endAngle: M_PI * 2 clockwise: 1]; UIBezierPath * path1 = [describezierpath]; [path1 moveToPoint: A]; [path1 addLineToPoint: B]; [path1 addQuadCurveToPoint: C controlPoint: P]; [path1 addLineToPoint: D]; [path1 addQuadCurveToPoint: A controlPoint: O]; [path appendPath: path1]; self. shapeLayer. path = path. CGPath ;}
Full: http://pan.baidu.com/s/1dEzZLst