Main Code
1. Traverse the proportions of all sectors, calculate the start and end angles of each sector area, and then draw FanShapeLayer
int max = 0; for (NSNumber * obj in self.angles) { max += [obj intValue]; } CGFloat startAngle = self.startAngle;// Start 0 represents the positive direction of the x-axis for (int i = 0; i < self.angles.count; i ++) { NSNumber * obj = [self.angles objectAtIndex:i]; CGFloat rate = [obj intValue]; CGFloat angle = rate / max * M_PI * 2.0; // Calculate the drawing angle - Endpoint The drawing direction is counterclockwise so it is subtracted CGFloat endAngle = startAngle - angle; // Set Colors UIColor * color = randomColor; // Create FanShapeLayer FanShapeLayer * layer = [[FanShapeLayer alloc]init]; layer.fillColor = color.CGColor; layer.name = [NSString stringWithFormat:@"layer = %d",i]; layer.startAngle = startAngle; layer.endAngle = endAngle; layer.radius = self.radius; layer.centerPoint = self.chartPoint; // Draw path (set parameters first) [layer drawPath]; [self.layer addSublayer:layer]; [self.fansArray addObject:layer]; // Calculate the starting point of the next drawing startAngle -= angle; }
2. After setting the parameters of FanShapeLayer, first draw CGMutablePathRef, which is a closed sector, then assign CGMutablePathRef to FanShapeLayer
CGMutablePathRef path = CGPathCreateMutable(); CGAffineTransform transform = CGAffineTransformMakeTranslation(1, 1); CGPathMoveToPoint(path, &transform, self.centerPoint.x, self.centerPoint.y); CGPathAddArc(path, &transform, self.centerPoint.x, self.centerPoint.y, radius, self.startAngle, self.endAngle, YES); CGPathCloseSubpath(path);
3. Mainly Click to zoom in. CALyer does not respond to click events. This is achieved by getting whether the point of the touch object is in the layer area or not.
You can find layers on the web that you can click on in the following ways, but here you get nil, and you don't know why.
CALayer * layer = [self.layer hitTest:point];
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ // Get the center point of a click UITouch * touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; // Gets whether the click area contains a CAShapeLayer FanShapeLayer * layer = [self touchLayer:point]; if (layer) { NSLog(@"%@", layer.name); // Set Selected to Unselected NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isSelected = YES"]; NSArray * selectArray = [self.fansArray filteredArrayUsingPredicate:predicate]; [selectArray makeObjectsPerformSelector:@selector(setIsSelected:) withObject:@NO]; if ([selectArray containsObject:layer]) { return ; } // Add animation layer.isSelected = YES; } } - (FanShapeLayer *)touchLayer:(CGPoint)point{ // Get the clicked area layer for (FanShapeLayer * layer in self.fansArray) { // Get the inPoint, coordinates in the layer CGPoint inPoint = [layer convertPoint:point fromLayer:self.layer]; if (CGPathContainsPoint(layer.path, 0, inPoint, YES)) { return layer; } } return nil; }
4. Finally add zoom animation when clicking
// Add animation CABasicAnimation *animation = [CABasicAnimation animation]; // Which property of the keyPath content object requires animation animation.keyPath = @"path"; // Set up proxy animation.delegate = self; // The value at the end of the changed property animation.toValue = (__bridge id _Nullable)(self.endPath); // Animation duration animation.duration = 0.25; // Do not remove after completion animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; // Add animation [self addAnimation:animation forKey:nil];