Я создал подкласс CALayer для рисования фрагмента круговой диаграммы с пользовательским цветом (color
), начальным углом (actualStartAngle
), конечным углом (actualEndAngle
) и изображением (image
)[Это изображение всегда должно быть в середине the slice], так как анимация этого невозможна с помощью обычного CAShapeLayer. Слой в настоящее время рисуется следующим образом:
- (void)drawInContext:(CGContextRef)ctx{
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, self.center.x, self.center.y);
CGContextAddArc(ctx, self.center.x, self.center.y, self.radius, self.actualEndAngle, self.actualStartAngle, YES);
CGContextClosePath(ctx);
CGContextSetFillColorWithColor(ctx, self.color);
CGContextSetLineWidth(ctx, 0);
CGContextDrawPath(ctx, kCGPathFillStroke);
if (self.image) {
CGContextDrawImage(ctx, [self getFrameForImgLayerWithStartAngle:self.actualStartAngle andEndAngle:self.actualEndAngle], self.image);
}
}
Эти отдельные фрагменты анимируются:
[CATransaction begin];
CABasicAnimation *colorAnimation = [CABasicAnimation animationWithKeyPath:@"color"];
colorAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
colorAnimation.duration = duration;
colorAnimation.fromValue = (id)self.color;
colorAnimation.toValue = (id)colorTU.CGColor;
CABasicAnimation *startAngleAnimation = [CABasicAnimation animationWithKeyPath:@"actualStartAngle"];
startAngleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
startAngleAnimation.duration = duration;
startAngleAnimation.fromValue = [self valueForKey:@"actualStartAngle"];
startAngleAnimation.toValue = [[NSNumber alloc] initWithFloat:newStartAngle];
CABasicAnimation *endAngleAnimation = [CABasicAnimation animationWithKeyPath:@"actualEndAngle"];
endAngleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
endAngleAnimation.duration = duration;
endAngleAnimation.fromValue = [self valueForKey:@"actualEndAngle"];
endAngleAnimation.toValue = [[NSNumber alloc] initWithFloat:newEndAngle];
if (completionBlock) {
[CATransaction setCompletionBlock:completionBlock];
}
if (colorTU && colorTU.CGColor != self.color) {
[self addAnimation:colorAnimation forKey:@"color"];
}
if (newStartAngle != self.actualStartAngle) {
[self addAnimation:startAngleAnimation forKey:@"actualStartAngle"];
}
if (newEndAngle != self.actualEndAngle) {
[self addAnimation:endAngleAnimation forKey:@"actualEndAngle"];
}
[CATransaction commit];
Проблема в том, что я хотел бы, чтобы изображение занимало только то пространство, которое занимает отдельный слой (соответственно, форма в нем). Это решается в общем таким методом:
- (BOOL)imageFitsIntoSliceWithStartAngle:(float)sA andEndAngle:(float)eA{
BOOL fits = YES;
CGRect rectToUse = [self getFrameForImgLayerWithStartAngle:sA andEndAngle:eA];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:self.center];
[path addArcWithCenter:self.center radius:self.deg startAngle:sA endAngle:eA clockwise:YES];
for (int w = 0; w <= 1; w++) {
if (fits) {
for (int h = 0; h <= 1; h++) {
if (![path containsPoint:CGPointMake(rectToUse.origin.x + rectToUse.size.width * w, rectToUse.origin.y + rectToUse.size.height * h)]) {
fits = NO;
break;
}
}
}
}
return fits;
}
Проблема сейчас в том, что он может поместиться в конце, а не в начале анимации, поэтому мне пришлось бы обрезать изображение, чтобы оно было таким же большим, как фрагмент, когда это произойдет.
Я пробовал следующее:
- установите маску для среза вместо того, чтобы рисовать его напрямую -> Это, во-первых, плохое кодирование, и я обнаружил, что оно очень неэффективно с точки зрения энергии, а также создало для меня ошибку (
expecting model layer not copy
).
Любые идеи о том, как решить эту проблему? (не то, что я пытался, а эта проблема в целом, я не думаю, что вы должны делать что-то вроде того, что я пробовал выше)
Спасибо
CGContextClipToMask
, даже когда он будет работать, очень неэффективен. Я в основном «решил» эту проблему, применив маску к отдельному imageLayer, но это действительно неэффективный метод и вызывает адскую задержку. Нарисовать изображение было бы тем более, верно? - person user1710004   schedule 29.03.2015