先看下效果:
功能:
支持设置表盘最大值,表盘动画,指针指向,颜色渐变。
1.画基本结构,包括灰色环、渐变夜色,箭头和内层虚线。
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self createSubLayers];
[self addSubview:self.currentRateLabel];
self.backgroundColor = [UIColor blackColor];
}
return self;
}
- (void)createSubLayers
{
//外层环
UIBezierPath *grayPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(Radius+LineWidth/2, self.frame.size.height) radius:Radius startAngle:M_PI endAngle:0 clockwise:YES];
self.arcLayer = [CAShapeLayer layer];
self.arcLayer.path = grayPath.CGPath;
self.arcLayer.lineWidth = LineWidth;
self.arcLayer.strokeColor = [UIColor lightGrayColor].CGColor;
// [self.layer addSublayer:self.arcLayer];
self.arcLayer.fillColor = [UIColor clearColor].CGColor;
CAShapeLayer *grayLayer = [CAShapeLayer layer];
grayLayer.path = grayPath.CGPath;
grayLayer.lineWidth = LineWidth;
grayLayer.strokeColor = [UIColor lightGrayColor].CGColor;
grayLayer.fillColor = [UIColor clearColor].CGColor;
[self.layer addSublayer:grayLayer];
//渐变色
CALayer *gradientLayer = [CALayer layer];
CAGradientLayer *gradientLayer1 = [CAGradientLayer layer];
gradientLayer1.frame = CGRectMake(0, 0, self.frame.size.width/2, self.frame.size.height);
[gradientLayer1 setColors:[NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor],(id)[[UIColor colorWithRed:255/255.0 green:220/255.0 blue:2/255.0 alpha:1.0] CGColor], nil]];
[gradientLayer1 setLocations:@[@0.1,@0.9]];
[gradientLayer1 setStartPoint:CGPointMake(0 ,1)];
[gradientLayer1 setEndPoint:CGPointMake(1, 0)];
[gradientLayer addSublayer:gradientLayer1];
CAGradientLayer *gradientLayer2 = [CAGradientLayer layer];
[gradientLayer2 setLocations:@[@0.1,@0.9]];
gradientLayer2.frame = CGRectMake(self.frame.size.width/2, 0, self.frame.size.width/2, self.frame.size.height);
[gradientLayer2 setColors:[NSArray arrayWithObjects:(id)[[UIColor colorWithRed:255/255.0 green:220/255.0 blue:2/255.0 alpha:1.0] CGColor],(id)[UIColor greenColor].CGColor, nil]];
[gradientLayer2 setStartPoint:CGPointMake(0, 0)];
[gradientLayer2 setEndPoint:CGPointMake(1, 1)];
[gradientLayer addSublayer:gradientLayer2];
[gradientLayer setMask:self.arcLayer];
[self.layer addSublayer:gradientLayer];
//虚线
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(Radius+LineWidth/2, self.frame.size.height) radius:Radius/2 startAngle:M_PI endAngle:0 clockwise:YES];
CAShapeLayer *dashLayer = [CAShapeLayer layer];
dashLayer.lineWidth = 1.0;
dashLayer.strokeColor = [UIColor grayColor].CGColor;
dashLayer.fillColor = [UIColor clearColor].CGColor;
dashLayer.path = path.CGPath;
[dashLayer setLineDashPattern:@[@(2),@(3)]];
[self.layer addSublayer:dashLayer];
//箭头
self.pointerLayer = [CAShapeLayer layer];
self.pointerLayer.strokeColor = [UIColor grayColor].CGColor;
self.pointerLayer.fillColor = [UIColor grayColor].CGColor;
self.pointerLayer.lineWidth = 0.5;
[self.layer addSublayer:self.pointerLayer];
}
2.表盘刻度根据外部参数(最大值)来确定,所以每次跳整最大值,表盘刻度会发生变化。
- (void)setTotal:(CGFloat)total
{
_total = total;
//添加坐标
NSUInteger floorTotal = floor(total);
NSUInteger puer = 0,coordinateNum = 0;
if (floorTotal == 0) {
}else if (floorTotal <= 4 && floorTotal >= 1){
puer = 1;
coordinateNum = floorTotal;
}else if (floorTotal <= 16 && floorTotal > 4){
puer = floorTotal/4;
coordinateNum = 4;
}else if (floorTotal < 40 && floorTotal >= 16){
puer = 10;
coordinateNum = floorTotal/10;
}else if (floorTotal < 100 && floorTotal >= 40){
puer = floorTotal/40*10;
coordinateNum = 4;
}else if (floorTotal < 400 && floorTotal >= 100){
puer = 100;
coordinateNum = floorTotal/100;
}else if (floorTotal <= 1000 && floorTotal >= 400){
puer = floorTotal/400*100;
coordinateNum = 4;
}else{
}
//表盘刻度
for (NSUInteger i = 0; i< coordinateNum + 1; i++) {
CGFloat startX = self.frame.size.width/2 - Radius*cos(M_PI*puer*i/total);
CGFloat startY = self.frame.size.height - Radius*sin(M_PI*puer*i/total);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(startX, startY)];
[path addLineToPoint:CGPointMake(self.frame.size.width/2 - (Radius+15)*cos(M_PI*puer*i/total), self.frame.size.height - (Radius+15)*sin(M_PI*puer*i/total))];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.lineWidth = 2.0;
layer.strokeColor = [UIColor whiteColor].CGColor;
layer.path = path.CGPath;
[self.layer addSublayer:layer];
//小刻度
CGFloat angle = M_PI*puer/total;
for (NSUInteger j = 0; j < 9; j++) {
CGFloat startX0 = self.frame.size.width/2 - (Radius+15)*cos(M_PI*puer*i/total + angle*j/10.0);
CGFloat startY0 = self.frame.size.height - (Radius+15)*sin(M_PI*puer*i/total + angle*j/10.0);
CGFloat toX = self.frame.size.width/2 - (Radius +8)*cos(M_PI*puer*i/total + angle*j/10.0);
CGFloat toY = self.frame.size.height - (Radius +8)*sin(M_PI*puer*i/total + angle*j/10.0);
UIBezierPath *path0 = [UIBezierPath bezierPath];
[path0 moveToPoint:CGPointMake(startX0, startY0)];
[path0 addLineToPoint:CGPointMake(toX, toY)];
CAShapeLayer *layer0 = [CAShapeLayer layer];
layer0.path = path0.CGPath;
layer0.lineWidth = 1.0;
layer0.strokeColor = [UIColor whiteColor].CGColor;
[self.layer addSublayer:layer0];
}
}
CGFloat r = Radius-25;
for (NSInteger i = 0; i< coordinateNum + 1; i++) {
//如果最后一个和totalLabel距离太近,去掉
if (M_PI*puer*i/total < M_PI*9/10) {
CGFloat positionX = self.frame.size.width/2 - r*cos(M_PI*puer*i/total);
CGFloat positionY = self.frame.size.height - r*sin(M_PI*puer*i/total);
UILabel *coordinateLabel = [[UILabel alloc]init];
coordinateLabel.textColor = [UIColor colorWithRed:0.2 green:0.5 blue:0.8 alpha:1.0];
coordinateLabel.textAlignment = NSTextAlignmentCenter;
coordinateLabel.frame = CGRectMake(positionX,positionY , 38, 20);
coordinateLabel.text = [NSString stringWithFormat:@"%ld",puer*i];
coordinateLabel.font = [UIFont systemFontOfSize:12];
coordinateLabel.center = CGPointMake(positionX, positionY);
[self addSubview:coordinateLabel];
}
}
UILabel *totalLabel = [[UILabel alloc]init];
totalLabel.textColor = [UIColor colorWithRed:0.2 green:0.5 blue:0.8 alpha:1.0];
totalLabel.textAlignment = NSTextAlignmentCenter;
totalLabel.frame = CGRectMake(Radius*2-30-20, self.frame.size.height - 10, 50, 20);
totalLabel.center = CGPointMake(self.frame.size.width/2 + r, self.frame.size.height);
totalLabel.text = [NSString stringWithFormat:@"%.1f",total];
totalLabel.font = [UIFont systemFontOfSize:12];
[self addSubview:totalLabel];
}
3.当前值用来确定箭头指向。
- (void)setCurrentValue:(CGFloat)currentValue
{
_currentValue = currentValue;
CGFloat rote = currentValue/_total;
_currentRateLabel.text = [NSString stringWithFormat:@"%.1f",currentValue];
_currentRateLabel.textColor = [self getBgColor:MIN(floor(50*rote), 50)];
//动画
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
[animation setDuration:3.0];
animation.fromValue = @0.0;
animation.toValue = @(rote);
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.arcLayer addAnimation:animation forKey:@"strokeEnd"];
//调整箭头位置
CGFloat arrorAngle = rote*M_PI;
CGFloat startPointX = self.frame.size.width/2 - (Radius/2-15)*cos(arrorAngle);
CGFloat startPointY = self.frame.size.height - (Radius/2-15)*sin(arrorAngle);
CGFloat pointX1 = startPointX - ArrorWidth*cos(arrorAngle);
CGFloat pointY1 = startPointY - ArrorWidth*sin(arrorAngle);
CGFloat pointX2 = pointX1 - 3*sin(arrorAngle);
CGFloat pointY2 = pointY1 + 3*cos(arrorAngle);
CGFloat pointX3 = pointX1 + sin(arrorAngle) - 10*cos(arrorAngle);
CGFloat pointY3 = pointY1 - cos(arrorAngle) - 10*sin(arrorAngle);
CGFloat pointX4 = pointX1 + 5*sin(arrorAngle);
CGFloat pointY4 = pointY1 - 5*cos(arrorAngle);
CGFloat pointX5 = pointX1 + 2*sin(arrorAngle);
CGFloat pointY5 = pointY1 - 2*cos(arrorAngle);
CGFloat pointX6 = startPointX + 2*sin(arrorAngle);
CGFloat pointY6 = startPointY - 2*cos(arrorAngle);
UIBezierPath *pointPath = [UIBezierPath bezierPath];
[pointPath moveToPoint:CGPointMake(startPointX, startPointY)];
[pointPath addLineToPoint:CGPointMake(pointX1, pointY1)];
[pointPath addLineToPoint:CGPointMake(pointX2, pointY2)];
[pointPath addLineToPoint:CGPointMake(pointX3, pointY3)];
[pointPath addLineToPoint:CGPointMake(pointX4, pointY4)];
[pointPath addLineToPoint:CGPointMake(pointX5, pointY5)];
[pointPath addLineToPoint:CGPointMake(pointX6, pointY6)];
[pointPath closePath];
self.pointerLayer.path = pointPath.CGPath;
}
4.最后,显示表盘指示的值(字体颜色会变)
- (UIColor *)getBgColor:(NSUInteger)index
{
int r=0,g=0,b=0;
// r = 255-255.0/50*index;
// g = 255.0/50*index;
float one = (255 + 255) / 60;//(255+255)除以最大取值的三分之二
if (index < 30)//第一个三等分
{
r = 255;
g = (int)(one * index);
}
else if (index >= 30 && index < 60)//第二个三等分
{
r = 255 - (int)((index - 30) * one);//val减最大取值的三分之一;
g = 255;
}
else { g = 255; }//最后一个三等分
return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0];
}
- (UILabel *)currentRateLabel
{
if (!_currentRateLabel) {
_currentRateLabel = [[UILabel alloc]initWithFrame:CGRectMake(self.frame.size.width/2 - 40, self.frame.size.height - 30, 80, 30)];
_currentRateLabel.font = [UIFont systemFontOfSize:18];
_currentRateLabel.textAlignment = NSTextAlignmentCenter;
}
return _currentRateLabel;
}
外部调用:
DashBoard *dashBoard = [[DashBoard alloc]initWithFrame:CGRectMake(30, 100, 300, 150)];
dashBoard.total = 50;
dashBoard.currentValue = 43;
[self.view addSubview:dashBoard];
网友评论