CAShapeLayer动画(弧从0到最终尺寸) [英] CAShapeLayer animation (arc from 0 to final size)
问题描述
我有一个 CAShapeLayer
中的弧线添加使用 UIBezierPath
。我看到一对夫妇的职位(一个实际上)在这里计算器,但似乎没有给我答案。正如标题所说,我想动画弧(是的,它会成为一个饼图)。
如何才能实现从空的弧动画完全伸展的呢?有点像一个弯曲的进度条。难道真的不可能通过 CoreAnimation
?
下面就是我如何做的弧。哦,而忽略了意见和计算,因为我已经习惯了逆时针单位圆和苹果开始按顺时针方向。弧出现就好了,我只需要动画:
//苹果的单位圆进去顺时针方向旋转,而IM用于沿逆时针方向旋转,这就是为什么我的角度沿x轴镜像
workAngle = 6.283185307 - DEGREES_TO_RADIANS(360 * item.value /个); //我的单位圆,这就是为什么负面currentAngle中
[路径moveToPoint:CGPointMake(center.x + cosf(outerPaddingAngle - currentAngle中)*(bounds.size.width / 2),center.y - (SINF(outerPaddingAngle - currentAngle中)*(bounds.size.height / 2))) ]; //苹果的单位圆,顺时针旋转,我们添加角度
[路径addArcWithCenter:中心半径:120由startAngle:currentAngle中endAngle:顺时针currentAngle中+ workAngle:NO]; //我的单位圆,逆时针旋转,我们减去角度
[路径addLineToPoint:CGPointMake(center.x + cosf(-currentAngle - workAngle)*((bounds.size.width / 2) - pieWidth),center.y - SINF(-currentAngle - workAngle)*((bounds.size。高度/ 2) - pieWidth)]); //苹果的单位圆,顺时针旋转,另外的角度
[路径addArcWithCenter:中心半径:120 - pieWidth由startAngle:currentAngle中+ workAngle endAngle:currentAngle中 - 顺时针innerPaddingAngle:YES]; //不需要我的自定义计算,因为我可以简单地闭合路径
[路径调用closePath] 外形= [CAShapeLayer层]
shape.frame = self.bounds;
shape.path = path.CGPath;
shape.fillColor = kRGBAColor(255,255,255,0.2F + 0.1F *(I + 1))CGColor。 // kRGBAColor是#defined定义 [self.layer addSublayer:形状];
//这是部件IM感兴趣的产品
如果(_shouldAnimate)
{
CABasicAnimation * pieAnimation = [CABasicAnimation animationWithKeyPath:@路径];
pieAnimation.duration = 1.0;
pieAnimation.removedOnCompletion = NO;
pieAnimation.fillMode = kCAFillModeForwards;
//往返只是假人,所以我不得到错误
pieAnimation.fromValue = [NSNumber的numberWithInt:0]; //从何而来
pieAnimation.toValue = [NSNumber的numberWithFloat:1.0F]; //什么 [形状addAnimation:pieAnimation forKey:@animatePath];
}
下面是一个基于CAShapeLayer一个的CALayer的实现:
ProgressLayer.h / M
#进口< QuartzCore / QuartzCore.h>@interface ProgressLayer:CAShapeLayer - (无效)computePath:(的CGRect)R;
- (无效)showProgress;
@结束#进口ProgressLayer.h@implementation ProgressLayer
- (ID)初始化{
自= [超级初始化]
如果(个体经营){
self.path = CGPathCreateWithEllipseInRect(CGRectMake(0,0,50,50),0);
self.strokeColor =的UIColor绿彩] .CGColor;
self.lineWidth = 40;
self.lineCap = kCALineCapRound;
self.strokeEnd = 0.001;
}
返回自我;
} - (无效)computePath:(的CGRect)R {
self.path = CGPathCreateWithEllipseInRect(R,0);
}
- (无效){showProgress
提前浮= 0.1;
如果(self.strokeEnd→1)self.strokeEnd = 0; CABasicAnimation *刷卡= [CABasicAnimation animationWithKeyPath:@strokeEnd];
swipe.duration = 0.25;
swipe.fromValue = [NSNumber的numberWithDouble:self.strokeEnd];
swipe.toValue = [NSNumber的numberWithDouble:self.strokeEnd +提前] swipe.fillMode = kCAFillModeForwards;
swipe.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
swipe.removedOnCompletion = NO;
self.strokeEnd = self.strokeEnd +提前;
[个体经营addAnimation:轻扫forKey:@strokeEnd动画];
}@结束
我用这层作为的UIView的衬里层:
#进口ProgressView.h
#进口ProgressLayer.h@implementation ProgressView
- (ID)initWith codeR:(NS codeR *)ADE $ C $ {CR
自= [超级initWith codeR:ADE codeR]
如果(个体经营){
[(ProgressLayer *)self.layer computePath:self.bounds];
}
返回自我;
} - (无效)的touchesBegan:(*的NSSet)触及withEvent:方法(*的UIEvent)事件{
ProgressLayer * L = self.layer;
[L showProgress]
}
- (无效)的drawRect:(的CGRect){RECT
[的UIColor redColor] setStroke]
UIRectFrame(self.bounds);
}
+(类)layerClass {
返回[ProgressLayer类]
}@结束
I have a CAShapeLayer
in which an arc is added using UIBezierPath
. I saw a couple of posts (one actually) here on stackoverflow but none seemed to give me the answer. As said in the title I would like to animate an arc (yes it will be for a pie chart).
How can one accomplish an animation from an "empty" arc to the fully extended one? Kinda like a curved progress bar. Is it really impossible to do it via CoreAnimation
?
Here's how I "do" the arc. Oh and ignore the comments and calculation since I'm used to counter clockwise unit circle and apple goes clockwise. The arcs appear just fine, I only need animation:
//Apple's unit circle goes in clockwise rotation while im used to counter clockwise that's why my angles are mirrored along x-axis
workAngle = 6.283185307 - DEGREES_TO_RADIANS(360 * item.value / total);
//My unit circle, that's why negative currentAngle
[path moveToPoint:CGPointMake(center.x + cosf(outerPaddingAngle - currentAngle) * (bounds.size.width / 2), center.y - (sinf(outerPaddingAngle - currentAngle) * (bounds.size.height / 2)))];
//Apple's unit circle, clockwise rotation, we add the angles
[path addArcWithCenter:center radius:120 startAngle:currentAngle endAngle:currentAngle + workAngle clockwise:NO];
//My unit circle, counter clockwise rotation, we subtract the angles
[path addLineToPoint:CGPointMake(center.x + cosf(-currentAngle - workAngle) * ((bounds.size.width / 2) - pieWidth), center.y - sinf(-currentAngle - workAngle) * ((bounds.size.height / 2) - pieWidth))];
//Apple's unit circle, clockwise rotation, addition of angles
[path addArcWithCenter:center radius:120 - pieWidth startAngle:currentAngle + workAngle endAngle:currentAngle - innerPaddingAngle clockwise:YES];
//No need for my custom calculations since I can simply close the path
[path closePath];
shape = [CAShapeLayer layer];
shape.frame = self.bounds;
shape.path = path.CGPath;
shape.fillColor = kRGBAColor(255, 255, 255, 0.2f + 0.1f * (i + 1)).CGColor; //kRGBAColor is a #defined
[self.layer addSublayer:shape];
//THIS IS THE PART IM INTERESTED IN
if (_shouldAnimate)
{
CABasicAnimation *pieAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pieAnimation.duration = 1.0;
pieAnimation.removedOnCompletion = NO;
pieAnimation.fillMode = kCAFillModeForwards;
//from and to are just dummies so I dont get errors
pieAnimation.fromValue = [NSNumber numberWithInt:0]; //from what
pieAnimation.toValue = [NSNumber numberWithFloat:1.0f]; //to what
[shape addAnimation:pieAnimation forKey:@"animatePath"];
}
Here is an implementation of a CALayer based on CAShapeLayer:
ProgressLayer.h/m
#import <QuartzCore/QuartzCore.h>
@interface ProgressLayer : CAShapeLayer
-(void) computePath:(CGRect)r;
-(void) showProgress;
@end
#import "ProgressLayer.h"
@implementation ProgressLayer
-(id)init {
self=[super init];
if (self) {
self.path = CGPathCreateWithEllipseInRect(CGRectMake(0, 0, 50, 50), 0);
self.strokeColor = [UIColor greenColor].CGColor;
self.lineWidth=40;
self.lineCap = kCALineCapRound;
self.strokeEnd=0.001;
}
return self;
}
-(void) computePath:(CGRect)r {
self.path = CGPathCreateWithEllipseInRect(r, 0);
}
-(void)showProgress {
float advance=0.1;
if (self.strokeEnd>1) self.strokeEnd=0;
CABasicAnimation * swipe = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
swipe.duration=0.25;
swipe.fromValue=[NSNumber numberWithDouble:self.strokeEnd];
swipe.toValue= [NSNumber numberWithDouble:self.strokeEnd + advance];
swipe.fillMode = kCAFillModeForwards;
swipe.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
swipe.removedOnCompletion=NO;
self.strokeEnd = self.strokeEnd + advance;
[self addAnimation:swipe forKey:@"strokeEnd animation"];
}
@end
I used this layer as a backing layer of an UIView:
#import "ProgressView.h"
#import "ProgressLayer.h"
@implementation ProgressView
-(id)initWithCoder:(NSCoder *)aDecoder {
self=[super initWithCoder:aDecoder];
if (self) {
[(ProgressLayer *)self.layer computePath:self.bounds];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
ProgressLayer * l = self.layer;
[l showProgress];
}
- (void)drawRect:(CGRect)rect {
[[UIColor redColor] setStroke];
UIRectFrame(self.bounds);
}
+(Class)layerClass {
return [ProgressLayer class];
}
@end
这篇关于CAShapeLayer动画(弧从0到最终尺寸)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!