您的位置:首页 > 其它

[CAAnimation核心动画练习四]饼图1.5 增加值的显示

2016-03-13 18:50 351 查看
#import <UIKit/UIKit.h>

@protocol PieViewDelegate <NSObject>

@required
-(void)show;

@end

@protocol PieViewSourceDelegate <NSObject>

@required
-(NSInteger)NumberOfParts;
-(NSInteger)PartValue:(NSInteger) Index;
-(UIColor*)PartColor:(NSInteger) Index;
@end
@interface PieView : UIView
@property (nonatomic,assign) CGFloat Radius;
@property (nonatomic,assign) CGFloat BeginAngle;
@property (nonatomic,assign) CFTimeInterval CycleTime;
@property (nonatomic,weak) id<PieViewSourceDelegate> SourceDelegate;

-(instancetype)initWithFrame:(CGRect)frame;
-(void)Refresh;
-(void)ReCovery;
@end


#import "PieView.h"
#import "PieLayer.h"

@implementation PieView
{
@private
NSTimer* _timer;
NSMutableArray *_animations;
UIFont* _TextFont;
}
-(instancetype)initWithFrame:(CGRect)frame
{
if ([super initWithFrame:frame]) {
_animations = [NSMutableArray arrayWithCapacity:5];
_timer = nil;
self.Radius = MIN(frame.size.width / 2, frame.size.height / 2);
_TextFont = [UIFont boldSystemFontOfSize:12.0];
self.BeginAngle = 0;
self.CycleTime = 1;
}
return self;
}

-(void)ReCovery
{
NSInteger iCounts = self.layer.sublayers.count;
if (iCounts == 0) return;
__block stPieAngleSet sSet;
sSet.BeginAngle = self.BeginAngle;
sSet.StartAngle = 0.0;
sSet.EndAngle = 0.0;
[self.layer.sublayers enumerateObjectsUsingBlock:^(PieLayer* obj, NSUInteger idx, BOOL *stop) {
[CATransaction begin];
obj.Angles = sSet;
[obj CreateAnimations];
[CATransaction commit];
}];
}

-(void)Refresh
{
if (!self.SourceDelegate) return;

/*删除所有的layer,直接用self.layer.sublayers还有错误,和线程访问相关*/
NSArray* arrRecovery = [NSArray arrayWithArray:self.layer.sublayers];
if (arrRecovery.count > 0) {
[arrRecovery enumerateObjectsUsingBlock:^(CAShapeLayer* obj, NSUInteger idx, BOOL *stop) {
[obj removeFromSuperlayer];
}];
}
/*获取数目*/
NSInteger iPartCount = [self.SourceDelegate NumberOfParts];
NSInteger iValues[iPartCount];
NSInteger iSum = 0;

/*获取值*/
for (NSInteger i = 0; i < iPartCount; i++) {
iValues[i] = [self.SourceDelegate PartValue:i];
iSum += iValues[i];
}
if (iSum == 0) return;

/*计算角度,弧度表示*/
CGFloat fAngles[iPartCount];
for (NSInteger i = 0; i < iPartCount; i++) {
fAngles[i] = M_PI * 2 * iValues[i] / iSum;
}
stPieAngleSet sSets[iPartCount];
CGFloat StartAngle = 0.0;
for (NSInteger i = 0; i < iPartCount; i++) {
sSets[i].BeginAngle = self.BeginAngle;
sSets[i].StartAngle = StartAngle;
sSets[i].EndAngle = StartAngle + fAngles[i];
StartAngle += fAngles[i];
}

/*创建layer*/
for (NSInteger i = 0; i < iPartCount; i++) {
[CATransaction begin];/*认为可以不用加,因为创建了还看不到呢*/
PieLayer* Layer = [PieLayer layer];
[self.layer addSublayer:Layer];
Layer.Angles = sSets[i];
Layer.CADelegate = self;
Layer.fillColor = [[self.SourceDelegate PartColor:i] CGColor];
Layer.CycleTime = self.CycleTime;
Layer.Value = [NSString stringWithFormat:@"%ld", iValues[i]];
Layer.TextFont = _TextFont;
[Layer CreateAnimations];
[CATransaction commit];
}
}

-(void)TimerFired:(NSTimer*) timer
{
[self.layer.sublayers enumerateObjectsUsingBlock:^(PieLayer* obj, NSUInteger idx, BOOL *stop) {
NSNumber* StartAngle = [[obj presentationLayer] valueForKey:SAngle];
NSNumber* EndAngle = [[obj presentationLayer] valueForKey:EAngle];
CGFloat S = [StartAngle floatValue];
CGFloat E = [EndAngle floatValue];
CGPoint _Center = self.layer.position;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, _Center.x, _Center.y);
CGPathAddArc(path, NULL, _Center.x, _Center.y, self.Radius, S, E, 0);
CGPathCloseSubpath(path);
[obj setPath:path];

[CATransaction setDisableActions:YES];
CALayer* textLayer = [[obj sublayers] objectAtIndex:0];
CGFloat M = (S + E) / 2;
CGSize size = [@"0" sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:obj.TextFont,NSFontAttributeName, nil]];
[textLayer setBounds:CGRectMake(0, 0, size.width * 2, size.height)];
[textLayer setPosition:CGPointMake(_Center.x + (self.Radius / 2 * cos(M)),
_Center.y + (self.Radius / 2 * sin(M)))];
[CATransaction setDisableActions:NO];
}];
}

-(void)animationDidStart:(CAAnimation *)anim
{
if (!_timer) {
static float timeInterval = 1.0/60.0;
_timer = [NSTimer timerWithTimeInterval:timeInterval target:self selector:@selector(TimerFired:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];

}
[_animations addObject:anim];
}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
[_animations removeObject:anim];
if (_animations.count ==  0) {
[_timer invalidate];
_timer = nil;
}
}
@end
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
#define SAngle @"StartAngle"
#define EAngle @"EndAngle"
typedef struct
{
CGFloat BeginAngle;
CGFloat StartAngle;
CGFloat EndAngle;
}stPieAngleSet;

@interface PieLayer : CAShapeLayer

@property(nonatomic,assign) stPieAngleSet Angles;
@property(nonatomic,weak) id CADelegate;
@property(nonatomic,assign) CFTimeInterval CycleTime;
@property(nonatomic,strong,setter=SetFont:) UIFont* TextFont;
@property(nonatomic,strong,setter=SetStrValue:) NSString* Value;
-(void)CreateAnimations;
-(void)SetFont:(UIFont*) font;
-(void)SetStrValue:(NSString *)Value;
@end
#import "PieLayer.h"

@implementation PieLayer

-(void)SetStrValue:(NSString *)Value
{
_Value = Value;
CATextLayer* TextLayer = [self.sublayers objectAtIndex:0];
[TextLayer setString:_Value];
}

-(void)SetFont:(UIFont *)font
{
CATextLayer* TextLayer = [self.sublayers objectAtIndex:0];
_TextFont = font;

/*字体的处理,没有理解,但是没有还真不行*/
CGFontRef FontRef = nil;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
FontRef = CGFontCreateCopyWithVariations((__bridge CGFontRef)(_TextFont), (__bridge CFDictionaryRef)(@{}));
} else {
FontRef = CGFontCreateWithFontName((__bridge CFStringRef)[_TextFont fontName]);
}
if (FontRef) {
[TextLayer setFont:FontRef];
CFRelease(FontRef);
}

[TextLayer setFontSize:self.TextFont.pointSize];
[TextLayer setAlignmentMode:kCAAlignmentCenter];
}
-(void)CreateAnimations
{
/*创建两组动画,这里的动画没起作用,只提供了2个值,然后进行setPath*/
CABasicAnimation* base1 = [CABasicAnimation animation];
NSNumber* S  = [NSNumber numberWithFloat:self.Angles.BeginAngle];
NSNumber* E  = [NSNumber numberWithFloat:self.Angles.BeginAngle + self.Angles.StartAngle];
NSNumber* CS = [[self presentationLayer] valueForKey:SAngle];
if (!CS) CS = S;
[base1 setFromValue:CS];
[base1 setToValue:E];
[base1 setDuration:self.CycleTime];
[base1 setDelegate:self.CADelegate];
[base1 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
[self addAnimation:base1 forKey:SAngle];
[self setValue:E forKey:SAngle];

CABasicAnimation* base2 = [CABasicAnimation animation];
S  = [NSNumber numberWithFloat:self.Angles.BeginAngle];
E  = [NSNumber numberWithFloat:self.Angles.BeginAngle + self.Angles.EndAngle];
CS = [[self presentationLayer] valueForKey:EAngle];
if (!CS) CS = S;
[base2 setFromValue:CS];
[base2 setToValue:E];
[base2 setDuration:self.CycleTime];
[base2 setDelegate:self.CADelegate];
[base2 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
[self setValue:E forKey:EAngle];
[self addAnimation:base2 forKey:EAngle];

}

-(instancetype)init
{
if (self = [super init]) {
CATextLayer* TextLayer = [CATextLayer layer];
[self addSublayer:TextLayer];
TextLayer.contentsScale =[[UIScreen mainScreen] scale];
/*先给个默认的背景吧,好看点儿~~*/
[TextLayer setBackgroundColor:[UIColor clearColor].CGColor];
[TextLayer setShadowColor:[UIColor greenColor].CGColor];
[TextLayer setShadowOffset:CGSizeZero];
[TextLayer setShadowRadius:3.0];
[TextLayer setShadowOpacity:1.0];
[TextLayer setForegroundColor:[UIColor redColor].CGColor];
}
return self;
}
@end
调用部分

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) PieView* LeftPie;
@end

@implementation ViewController
{
Boolean _IsShowState;
}

- (void)viewDidLoad {
[super viewDidLoad];
self.LeftPie = [[PieView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
_IsShowState = NO;
[self.view addSubview:self.LeftPie];
self.LeftPie.CycleTime = 2;
[self.LeftPie setSourceDelegate:self];
[self.LeftPie setBeginAngle:M_PI / 2];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (_IsShowState) {
[self.LeftPie ReCovery];
}
else {
[self.LeftPie Refresh];
};
_IsShowState = !_IsShowState;
}
-(NSInteger)NumberOfParts
{
return 5;
}
-(NSInteger)PartValue:(NSInteger)Index
{
switch (Index) {
case 0: return 20;
case 1: return 10;
case 2: return 30;
case 3: return 40;
case 4: return 25;
}
return 20;
}
-(UIColor*)PartColor:(NSInteger)Index
{
switch (Index) {
case 0: return [UIColor grayColor];
case 1: return [UIColor redColor];
case 2: return [UIColor darkGrayColor];
case 3: return [UIColor blueColor];
case 4: return [UIColor brownColor];
}
return [UIColor clearColor];
}
@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: