-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLDGaugesLayer.m
168 lines (136 loc) · 5.55 KB
/
LDGaugesLayer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//
// LDGaugesLayer.m
//
// Created by Luca D'Incà on 29/06/13.
// Copyright (c) 2013 Luca D'Incà. All rights reserved.
//
// This code comes with no warranty, free to use for any purpose
// Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
#import "LDGaugesLayer.h"
#define START_ANGLE_BACKGROUND 0.f
#define STOP_ANGLE_BACKGROUND 360.f
#define ANIMATION_DURATION 1.f
#define DEGRESS_TO_RADIUS(degress) ((M_PI * degress)/ 180.f)
@implementation LDGaugesLayer
@dynamic startAngle, stopAngle;
#pragma mark Inizialization method
- (id)initWithLayer:(id)layer
{
if (self = [super initWithLayer:layer]) {
if ([layer isKindOfClass:[LDGaugesLayer class]]) {
LDGaugesLayer *previous = (LDGaugesLayer *)layer;
[self doInizialSetup:previous];
}
}
return self;
}
- (void)initWithFreame:(CGRect)frame center:(CGPoint)center radius:(CGFloat)radius
thickness:(CGFloat)thickness;
{
[self setContentsScale:[[UIScreen mainScreen] scale]];
self.frame = frame;
self.center = center;
self.radius = radius;
self.thickness = thickness;
}
- (void)doInizialSetup:(LDGaugesLayer *)previous
{
self.center = previous.center;
self.stopAngle = previous.stopAngle;
self.radius = previous.radius;
self.thickness = previous.thickness;
self.color = previous.color;
self.backgroudColor = previous.backgroudColor;
}
//Return true if "startAngle" or "stopAngle"
//change their values
+(BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:@"startAngle"] ||
[key isEqualToString:@"stopAngle"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
-(id<CAAction>)actionForKey:(NSString *)event
{
if ([event isEqualToString:@"startAngle"] ||
[event isEqualToString:@"stopAngle"]) {
//if startAngle or stopAngle change their values,
//the system automatically invokes a method to create the animation
return [self makeAnimationForKey:event];
}
return [super actionForKey:event];
}
-(CAAnimation *)makeAnimationForKey:(NSString *)key
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
animation.fromValue = [[self presentationLayer] valueForKey:key];
//Set animation type, the animation to begin quickly, and then slow as it completes
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation.duration = ANIMATION_DURATION;
return animation;
}
#pragma mark Create gauge form
-(CGMutablePathRef)creteGaugesBackGroundForm:(CGFloat)radius thickness:(CGFloat)thickness
{
CGMutablePathRef path = CGPathCreateMutable();
CGPoint center = self.center;
//External circle
CGPathAddArc(path, NULL, center.x, center.y, radius, START_ANGLE_BACKGROUND ,
DEGRESS_TO_RADIUS(STOP_ANGLE_BACKGROUND), YES);
CGPathCloseSubpath(path);
//Internal circle
CGPathAddArc(path, NULL, center.x, center.y, radius- thickness, START_ANGLE_BACKGROUND ,
DEGRESS_TO_RADIUS(STOP_ANGLE_BACKGROUND), YES);
CGPathCloseSubpath(path);
return path;
}
-(CGMutablePathRef)createStartStopBlock:(CGPoint)startLinePoint angle:(CGFloat)angle
{
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, startLinePoint.x, startLinePoint.y);
CGPathAddLineToPoint(path, NULL, (self.center.x + (self.radius) * cosf(angle)),
self.center.y + (self.radius) * sinf(angle));
return path;
}
-(CGMutablePathRef)createGauges:(CGPoint)startPoint
{
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y);
//External arch
CGPathAddLineToPoint(path, NULL, (self.center.x + (self.radius) * cosf(self.startAngle)),
self.center.y + (self.radius) * sinf(self.startAngle));
//Draw external arch
CGPathAddArc(path, NULL, self.center.x, self.center.y, self.radius, self.startAngle, self.stopAngle, NO);
CGPathAddLineToPoint(path, NULL, (self.center.x + (self.radius - self.thickness) * cosf(self.stopAngle)),
self.center.y + (self.radius - self.thickness) * sinf(self.stopAngle));
//Draw internal arch
CGPathAddArc(path, NULL, self.center.x, self.center.y, (self.radius - self.thickness) ,
self.stopAngle, self.startAngle, YES);
return path;
}
#pragma mark Draw forms in the layer
-(void)drawInContext:(CGContextRef)ctx
{
//Starting point
CGPoint startPoint = CGPointMake((self.center.x + (self.radius - self.thickness) * cosf(self.startAngle)),
self.center.y + (self.radius - self.thickness) * sinf(self.startAngle));
//Ending point
//CGPoint endPoint = CGPointMake((self.center.x + (self.radius - self.thickness) * cosf(self.stopAngle)),
//self.center.y + (self.radius - self.thickness) * sinf(self.stopAngle));
//Enable Antialias
CGContextSetShouldAntialias(ctx, YES);
//Draw the gauge background
CGContextSetFillColorWithColor(ctx, self.backgroudColor.CGColor);
CGContextAddPath(ctx, [self creteGaugesBackGroundForm:self.radius thickness:self.thickness]);
//Fill the form in EO mode
CGContextEOFillPath(ctx);
//Create the gauge path
CGContextAddPath(ctx, [self createGauges:startPoint]);
//Fill with color the main form
CGContextSetFillColorWithColor(ctx, self.color.CGColor);
//Draw the gauge
CGContextDrawPath(ctx, kCGPathFill);
}
@end