IOS上实现的自定义仪表盘示例

 更新时间:2017年01月21日 14:10:51   作者:念风2012  
本篇文章主要介绍了IOS上实现的自定义仪表盘示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

今天给大家带来一个自定义的仪表盘,效果图如下。

Demo中用到了 QuartzCore类 首先继承一个UIView。

// Gauge.h 
// GaugeDemo 
// 
// Created by 海锋 周 on 12-3-27. 
// Copyright (c) 2012年 CJLU rights reserved. 
// 
 
#import <UIKit/UIKit.h> 
#import <QuartzCore/QuartzCore.h> 
 
@interface Gauge : UIView 
{ 
  UIImage *gaugeView; 
  UIImageView *pointer; 
   
  CGFloat maxNum; 
  CGFloat minNum; 
   
  CGFloat maxAngle; 
  CGFloat minAngle; 
   
  CGFloat gaugeValue; 
  CGFloat gaugeAngle; 
   
  CGFloat angleperValue; 
  CGFloat scoleNum; 
   
  NSMutableArray *labelArray; 
  CGContextRef context; 
} 
 
@property (nonatomic,retain) UIImage *gaugeView; 
@property (nonatomic,retain) UIImageView *pointer; 
@property (nonatomic,retain) NSMutableArray *labelArray; 
@property (nonatomic) CGContextRef context; 
-(void)setGaugeValue:(CGFloat)value animation:(BOOL)isAnim; 
 
@end

指针的旋转是通过QuartzCore.framework中的CATransform3DRotate 来实现的,所以一定要记得把框架添加进来。当然在旋转之前,我们还需要把指针的中心pointer.layer.anchorPoint 移动到你需要的转动中心。

在设置旋转动画的时候,我们用的不是CABaseAnimiation 而是用  CAKeyframeAnimation。这是因为如果使用中的 toValue 来实现旋转的话,它默认是以最小的旋转的,如果要实现控制旋转的方向的话,我们就只能用关键帧来设置旋转的路径。用关键帧的好处还有一个,就是可以给指针添加,旋转到指定位置以后的左右摆动的效果。

绘制仪表盘是通过Quartz2D来实现的,首先我们需要用UIGraphicsGetCurrentContext函数来获取一个Context上下文,就是相当于获取一个画布。然后就可以在上面通过三角函数的计算,画出背景图片,和上面的刻度线了。

// Gauge.m 
// GaugeDemo 
// 
// Created by 海锋 周 on 12-3-27. 
// Copyright (c) 2012年 CJLU. All rights reserved. 
// 
 
#import "Gauge.h" 
#import <QuartzCore/QuartzCore.h> 
 
#define MAXOFFSETANGLE 120.0f 
#define POINTEROFFSET 90.0f 
#define MAXVALUE    120.0f 
#define CELLMARKNUM  5 
#define CELLNUM    12 
#define GAUGESTRING  @"单位:Km/h" 
#define DEFLUATSIZE  300     
/************************************************ 
  仪表盘的大小不建议设置的太小。 
  长宽都是300是最适合的 
  如果要更小的需要自行修改刻度长度和文字大小 
              ---powered by 周海锋 
                2012-3-29 
 ***********************************************/ 
 
 
@implementation Gauge 
 
@interface Gauge (private) 
- (CGFloat) parseToX:(CGFloat) radius Angle:(CGFloat)angle; 
- (CGFloat) parseToY:(CGFloat) radius Angle:(CGFloat)angle; 
- (CGFloat) transToRadian:(CGFloat)angel; 
- (CGFloat) parseToAngle:(CGFloat) val; 
- (CGFloat) parseToValue:(CGFloat) val; 
- (void)setTextLabel:(NSInteger)labelNum; 
- (void)setLineMark:(NSInteger)labelNum; 
- (void) pointToAngle:(CGFloat) angle Duration:(CGFloat) duration; 
@end 
 
@synthesize gaugeView,pointer,context; 
@synthesize labelArray; 
 
- (id)initWithFrame:(CGRect)frame 
{ 
  self = [super initWithFrame:frame]; 
  if (self) { 
    //设置背景透明 
    [self setBackgroundColor:[UIColor clearColor]]; 
     
    scoleNum = DEFLUATSIZE/frame.size.width; 
    maxNum = MAXVALUE; 
    minNum = 0.0f; 
    minAngle = -MAXOFFSETANGLE; 
    maxAngle = MAXOFFSETANGLE; 
    gaugeValue = 0.0f; 
    gaugeAngle = -MAXOFFSETANGLE; 
    angleperValue = (maxAngle - minAngle)/(maxNum - minNum); 
     
    gaugeView= [UIImage imageNamed:@"gaugeback.png"]; 
    //添加指针 
    UIImage *_pointer = [UIImage imageNamed:@"pointer2.png"]; 
    pointer = [[UIImageView alloc] initWithImage:_pointer]; 
    pointer.layer.anchorPoint = CGPointMake(0.5, 0.78); 
    pointer.center = self.center; 
    pointer.transform = CGAffineTransformMakeScale(scoleNum, scoleNum); 
    [self addSubview:pointer]; 
    //设置文字标签 
    [self setTextLabel:CELLNUM]; 
    //设置指针到0位置 
    pointer.layer.transform = CATransform3DMakeRotation([self transToRadian:-MAXOFFSETANGLE], 0, 0, 1); 
  } 
  return self; 
} 
 
/* 
 * setTextLabel 绘制刻度值 
 * @labelNum NSInteger 刻度值的数目 
 */ 
-(void)setTextLabel:(NSInteger)labelNum 
{ 
   labelArray = [NSMutableArray arrayWithCapacity:labelNum]; 
   
  CGFloat textDis = (maxNum - minNum)/labelNum; 
  CGFloat angelDis = (maxAngle - minAngle)/labelNum; 
  CGFloat radius = (self.center.x - 75)*scoleNum; 
  CGFloat currentAngle; 
  CGFloat currentText = 0.0f; 
  CGPoint centerPoint = self.center; 
   
  for(int i=0;i<=labelNum;i++) 
  { 
    currentAngle = minAngle + i * angelDis - POINTEROFFSET; 
    currentText = minNum + i * textDis; 
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0 , 0 , 30, 50)]; 
    label.autoresizesSubviews = YES; 
    label.textColor = [UIColor whiteColor]; 
    label.backgroundColor = [UIColor clearColor]; 
    //设置刻度的文字的格式 
    if(i<labelNum/2){ 
      label.textAlignment = UITextAlignmentLeft; 
    }else if (i==labelNum/2){ 
      label.textAlignment = UITextAlignmentCenter; 
    }else{ 
      label.textAlignment = UITextAlignmentRight; 
    } 
    label.text = [NSString stringWithFormat:@"%d",(int)currentText]; 
    label.center = CGPointMake(centerPoint.x+[self parseToX:radius Angle:currentAngle],centerPoint.y+[self parseToY:radius Angle:currentAngle]); 
     
    [labelArray addObject:label]; 
    [self addSubview:label];     
  } 
  // 设置刻度表的名称 
  UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0 , 0 ,100, 40)]; 
  label.autoresizesSubviews = YES; 
  label.textColor = [UIColor whiteColor]; 
  label.backgroundColor = [UIColor clearColor]; 
  label.textAlignment = UITextAlignmentCenter; 
  label.text = GAUGESTRING; 
  label.center = CGPointMake(centerPoint.x,centerPoint.y*3/2); 
  [self addSubview:label];   
} 
 
/* 
 * setLineMark 绘制刻度的标记 
 * @labelNum NSInteger 刻度是数目 
 */ 
-(void)setLineMark:(NSInteger)labelNum 
{ 
 
  CGFloat angelDis = (maxAngle - minAngle)/labelNum; 
  CGFloat radius = self.center.x; 
  CGFloat currentAngle; 
  CGPoint centerPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2); 
   
  for(int i=0;i<=labelNum;i++) 
  { 
    currentAngle = minAngle + i * angelDis - POINTEROFFSET; 
    //给刻度标记绘制不同的颜色 
    if(i>labelNum*2/3) 
    { 
      CGContextSetStrokeColorWithColor(context, [[UIColor colorWithRed:1 green:0 blue:0 alpha:0.8] CGColor]); 
    }else if(i>labelNum*1/3){ 
      CGContextSetStrokeColorWithColor(context, [[UIColor colorWithRed:1 green:1 blue:0 alpha:0.8] CGColor]); 
    }else{ 
      CGContextSetStrokeColorWithColor(context, [[UIColor colorWithRed:0 green:1 blue:0 alpha:0.8] CGColor]); 
    } 
    //绘制不同的长短的刻度 
    if(i%5==0) 
    {    
      CGContextSetLineCap(context, kCGLineCapSquare); 
      CGContextSetLineWidth(context, 3); 
      CGContextStrokePath(context);   
      CGContextMoveToPoint(context,centerPoint.x+[self parseToX:radius-25*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-25*scoleNum Angle:currentAngle]); 
      CGContextAddLineToPoint(context,centerPoint.x+[self parseToX:radius-65*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-65*scoleNum Angle:currentAngle]); 
    }else{ 
      CGContextSetLineWidth(context, 2); 
      CGContextSetLineCap(context, kCGLineCapSquare); 
      CGContextStrokePath(context);  
      CGContextMoveToPoint(context,centerPoint.x+[self parseToX:radius-25*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-25*scoleNum Angle:currentAngle]); 
      CGContextAddLineToPoint(context,centerPoint.x+[self parseToX:radius-40*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-40*scoleNum Angle:currentAngle]);   
    } 
  } 
} 
 
/* 
 * setGaugeValue 移动到某个数值 
 * @value CGFloat 移动到的数值 
 * @isAnim BOOL  是否执行动画 
 */ 
-(void)setGaugeValue:(CGFloat)value animation:(BOOL)isAnim 
{ 
  CGFloat tempAngle = [self parseToAngle:value]; 
  gaugeValue = value; 
  //设置转动时间和转动动画 
  if(isAnim){ 
    [self pointToAngle:tempAngle Duration:0.6f]; 
  }else 
  { 
    [self pointToAngle:tempAngle Duration:0.0f]; 
  } 
} 
 
/* 
 * pointToAngle 按角度旋转 
 * @angel CGFloat 角度 
 * @duration CGFloat 动画执行时间 
 */ 
- (void) pointToAngle:(CGFloat) angle Duration:(CGFloat) duration 
{ 
  CAKeyframeAnimation *anim=[CAKeyframeAnimation animationWithKeyPath:@"transform"];  
  NSMutableArray *values=[NSMutableArray array];  
  anim.duration = duration; 
  anim.autoreverses = NO; 
  anim.fillMode = kCAFillModeForwards; 
  anim.removedOnCompletion= NO; 
   
  CGFloat distance = angle/10; 
  //设置转动路径,不能直接用 CABaseAnimation 的toValue,那样是按最短路径的,转动超过180度时无法控制方向 
  int i = 1; 
  for(;i<=10;i++){ 
    [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*i)], 0, 0, 1)]]; 
    } 
  //添加缓动效果 
   [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*(i))], 0, 0, 1)]]; 
   [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*(i-2))], 0, 0, 1)]];    
   [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*(i-1))], 0, 0, 1)]]; 
                                       
  anim.values=values; ; 
  [pointer.layer addAnimation:anim forKey:@"cubeIn"]; 
   
  gaugeAngle = gaugeAngle+angle; 
   
} 
 
/* 
 * parseToX 角度转弧度 
 * @angel CGFloat 角度 
 */ 
-(CGFloat)transToRadian:(CGFloat)angel 
{ 
  return angel*M_PI/180; 
} 
 
 
/* 
 * parseToX 根据角度,半径计算X坐标 
 * @radius CGFloat 半径  
 * @angle CGFloat 角度 
 */ 
- (CGFloat) parseToX:(CGFloat) radius Angle:(CGFloat)angle 
{ 
  CGFloat tempRadian = [self transToRadian:angle]; 
  return radius*cos(tempRadian); 
} 
 
/* 
 * parseToY 根据角度,半径计算Y坐标 
 * @radius CGFloat 半径  
 * @angle CGFloat 角度 
 */ 
- (CGFloat) parseToY:(CGFloat) radius Angle:(CGFloat)angle 
{ 
  CGFloat tempRadian = [self transToRadian:angle]; 
  return radius*sin(tempRadian); 
} 
 
/* 
 * parseToAngle 根据数据计算需要转动的角度 
 * @val CGFloat 要移动到的数值 
 */ 
-(CGFloat) parseToAngle:(CGFloat) val 
{ 
  //异常的数据 
  if(val<minNum){ 
    return minNum; 
  }else if(val>maxNum){ 
    return maxNum; 
  } 
  CGFloat temp =(val-gaugeValue)*angleperValue; 
  return temp; 
} 
 
/* 
 * parseToValue 根据角度计算数值 
 * @val CGFloat 要移动到的角度 
 */ 
-(CGFloat) parseToValue:(CGFloat) val 
{ 
  CGFloat temp=val/angleperValue; 
  CGFloat temp2=maxNum/2+temp; 
  if(temp2>maxNum){ 
    return maxNum; 
  }else if(temp2<maxNum){ 
    return maxNum; 
  } 
  return temp2; 
} 
 
- (void)drawRect:(CGRect)rect  
{ 
  //获取上下文 
  context = UIGraphicsGetCurrentContext(); 
  //设置背景透明 
  CGContextSetFillColorWithColor(context,self.backgroundColor.CGColor); 
  CGContextFillRect(context, rect); 
  //绘制仪表背景   
  [[self gaugeView ]drawInRect:self.bounds]; 
  //绘制刻度 
  [self setLineMark:CELLNUM*CELLMARKNUM]; 
     
  CGContextStrokePath(context); 
} 
 
@end 

Demo的下载地址:http://xiazai.jb51.net/201701/yuanma/GaugeDemo_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • iOS代码瘦身实践之如何删除无用的类

    iOS代码瘦身实践之如何删除无用的类

    这篇文章主要给大家介绍了关于iOS代码瘦身实践之如何删除无用的类,文中通过示例代码介绍的非常详细,对大家各位iOS开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • iOS贝塞尔曲线画哆啦A梦的代码实例

    iOS贝塞尔曲线画哆啦A梦的代码实例

    本篇文章主要介绍了iOS贝塞尔曲线画哆啦A梦的代码实例,这里整理了详细的代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-07-07
  • 简介iOS开发中应用SQLite的模糊查询和常用函数

    简介iOS开发中应用SQLite的模糊查询和常用函数

    这篇文章主要介绍了iOS开发中应用SQLite的模糊查询和常用函数,SQLite是一个可作嵌入式的数据库非常适合小型应用使用,需要的朋友可以参考下
    2015-12-12
  • iOS实现播放远程网络音乐的核心技术点总结

    iOS实现播放远程网络音乐的核心技术点总结

    本篇文章主要介绍了iOS播放远程网络音乐的核心技术,采用ios系统自带的AVFoundation框架来实现,有需要的朋友可以了解一下。
    2016-11-11
  • iOS字体大小适配的3种方法示例代码

    iOS字体大小适配的3种方法示例代码

    这篇文章主要给大家介绍了关于iOS字体大小适配的3种方法,文中通过示例代码介绍的非常详细,对各位iOS开发者们具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • iPhone X官方文档的适配学习详解

    iPhone X官方文档的适配学习详解

    本篇文章主要介绍了iPhone X官方文档的适配学习详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • iOS常用组件之高效切圆角的方法汇总

    iOS常用组件之高效切圆角的方法汇总

    最近在研究切圆角的方法,也找了下网上的资料,所以下面这篇文章主要给大家总结介绍了关于iOS常用组件之高效切圆角的一些方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2018-01-01
  • iOS自带动画效果的实例代码

    iOS自带动画效果的实例代码

    本文给大家分享ios自带动画效果的实现代码,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2016-12-12
  • iOS中UIScrollerView的用法及基于AotoLayout的控件悬停

    iOS中UIScrollerView的用法及基于AotoLayout的控件悬停

    这篇文章主要介绍了iOS中UIScrollerView的用法及基于AotoLayout的控件悬停,文中对于UIScrollerView的方法及属性介绍地非常详细,十分推荐,示例代码为Objective-C,需要的朋友可以参考下
    2016-03-03
  • 详解iOS多线程GCD问题

    详解iOS多线程GCD问题

    本篇文章主要介绍了iOS多线程GCD问题,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11

最新评论