• IOS自定义仪表盘


     
     

    [置顶] 【IOS】IOS上实现的自定义仪表盘(可以用在流量监控之类的应用上)

    标签: iosdistanceanimationuiviewinterfacequartz
     分类:

     【原创作品, 欢迎转载,转载请在明显处注明! 谢谢。

                  原文地址:http://blog.csdn.net/toss156/article/details/7407770


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

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

    [cpp] view plain copy
     
    1. <span style="font-size:10px;">//  
    2. //  Gauge.h  
    3. //  GaugeDemo  
    4. //  
    5. //  Created by 海锋 周 on 12-3-27.  
    6. //  Copyright (c) 2012年 CJLU rights reserved.  
    7. //  
    8.   
    9. #import <UIKit/UIKit.h>  
    10. #import <QuartzCore/QuartzCore.h>  
    11.   
    12. @interface Gauge : UIView  
    13. {  
    14.     UIImage *gaugeView;  
    15.     UIImageView *pointer;  
    16.       
    17.     CGFloat maxNum;  
    18.     CGFloat minNum;  
    19.       
    20.     CGFloat maxAngle;  
    21.     CGFloat minAngle;  
    22.       
    23.     CGFloat gaugeValue;  
    24.     CGFloat gaugeAngle;  
    25.       
    26.     CGFloat angleperValue;  
    27.     CGFloat scoleNum;  
    28.       
    29.     NSMutableArray *labelArray;  
    30.     CGContextRef context;  
    31. }  
    32.   
    33. @property (nonatomic,retain) UIImage *gaugeView;  
    34. @property (nonatomic,retain) UIImageView *pointer;  
    35. @property (nonatomic,retain) NSMutableArray *labelArray;  
    36. @property (nonatomic) CGContextRef context;  
    37. -(void)setGaugeValue:(CGFloat)value animation:(BOOL)isAnim;  
    38.   
    39. @end</span><span style="font-size: 14px;">  
    40. </span>  
            指针的旋转是通过QuartzCore.framework中的CATransform3DRotate 来实现的,所以一定要记得把框架添加进来。当然在旋转之前,我们还需要把指针的中心pointer.layer.anchorPoint 移动到你需要的转动中心。

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

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


    [cpp] view plain copy
     
    1. //  
    2. //  Gauge.m  
    3. //  GaugeDemo  
    4. //  
    5. //  Created by 海锋 周 on 12-3-27.  
    6. //  Copyright (c) 2012年 CJLU. All rights reserved.  
    7. //  
    8.   
    9. #import "Gauge.h"  
    10. #import <QuartzCore/QuartzCore.h>  
    11.   
    12. #define MAXOFFSETANGLE 120.0f  
    13. #define POINTEROFFSET  90.0f  
    14. #define MAXVALUE       120.0f  
    15. #define CELLMARKNUM    5  
    16. #define CELLNUM        12  
    17. #define GAUGESTRING    @"单位:Km/h"  
    18. #define DEFLUATSIZE    300          
    19. /************************************************ 
    20.     仪表盘的大小不建议设置的太小。 
    21.     长宽都是300是最适合的 
    22.     如果要更小的需要自行修改刻度长度和文字大小 
    23.                             ---powered by 周海锋 
    24.                                 2012-3-29 
    25.  ***********************************************/  
    26.   
    27.   
    28. @implementation Gauge  
    29.   
    30. @interface Gauge (private)  
    31. - (CGFloat) parseToX:(CGFloat) radius Angle:(CGFloat)angle;  
    32. - (CGFloat) parseToY:(CGFloat) radius Angle:(CGFloat)angle;  
    33. - (CGFloat) transToRadian:(CGFloat)angel;  
    34. - (CGFloat) parseToAngle:(CGFloat) val;  
    35. - (CGFloat) parseToValue:(CGFloat) val;  
    36. - (void)setTextLabel:(NSInteger)labelNum;  
    37. - (void)setLineMark:(NSInteger)labelNum;  
    38. - (void) pointToAngle:(CGFloat) angle Duration:(CGFloat) duration;  
    39. @end  
    40.   
    41. @synthesize gaugeView,pointer,context;  
    42. @synthesize labelArray;  
    43.   
    44. - (id)initWithFrame:(CGRect)frame  
    45. {  
    46.     self = [super initWithFrame:frame];  
    47.     if (self) {  
    48.         //设置背景透明  
    49.         [self setBackgroundColor:[UIColor clearColor]];  
    50.           
    51.         scoleNum = DEFLUATSIZE/frame.size.width;  
    52.         maxNum = MAXVALUE;  
    53.         minNum = 0.0f;  
    54.         minAngle = -MAXOFFSETANGLE;  
    55.         maxAngle = MAXOFFSETANGLE;  
    56.         gaugeValue = 0.0f;  
    57.         gaugeAngle = -MAXOFFSETANGLE;  
    58.         angleperValue = (maxAngle - minAngle)/(maxNum - minNum);  
    59.           
    60.         gaugeView= [UIImage imageNamed:@"gaugeback.png"];  
    61.         //添加指针  
    62.         UIImage *_pointer = [UIImage imageNamed:@"pointer2.png"];  
    63.         pointer = [[UIImageView alloc] initWithImage:_pointer];  
    64.         pointer.layer.anchorPoint = CGPointMake(0.5, 0.78);  
    65.         pointer.center = self.center;  
    66.         pointer.transform = CGAffineTransformMakeScale(scoleNum, scoleNum);  
    67.         [self addSubview:pointer];  
    68.         //设置文字标签  
    69.         [self setTextLabel:CELLNUM];  
    70.         //设置指针到0位置  
    71.         pointer.layer.transform = CATransform3DMakeRotation([self transToRadian:-MAXOFFSETANGLE], 0, 0, 1);  
    72.     }  
    73.     return self;  
    74. }  
    75.   
    76. /* 
    77.  * setTextLabel 绘制刻度值 
    78.  * @labelNum NSInteger 刻度值的数目 
    79.  */  
    80. -(void)setTextLabel:(NSInteger)labelNum  
    81. {  
    82.      labelArray = [NSMutableArray arrayWithCapacity:labelNum];  
    83.       
    84.     CGFloat textDis = (maxNum - minNum)/labelNum;  
    85.     CGFloat angelDis = (maxAngle - minAngle)/labelNum;  
    86.     CGFloat radius = (self.center.x - 75)*scoleNum;  
    87.     CGFloat currentAngle;  
    88.     CGFloat currentText = 0.0f;  
    89.     CGPoint centerPoint = self.center;  
    90.       
    91.     for(int i=0;i<=labelNum;i++)  
    92.     {  
    93.         currentAngle = minAngle + i * angelDis - POINTEROFFSET;  
    94.         currentText = minNum + i * textDis;  
    95.         UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0 , 0 , 30, 50)];  
    96.         label.autoresizesSubviews = YES;  
    97.         label.textColor = [UIColor whiteColor];  
    98.         label.backgroundColor = [UIColor clearColor];  
    99.         //设置刻度的文字的格式  
    100.         if(i<labelNum/2){  
    101.             label.textAlignment = UITextAlignmentLeft;  
    102.         }else if (i==labelNum/2){  
    103.             label.textAlignment = UITextAlignmentCenter;  
    104.         }else{  
    105.             label.textAlignment = UITextAlignmentRight;  
    106.         }  
    107.         label.text = [NSString stringWithFormat:@"%d",(int)currentText];  
    108.         label.center = CGPointMake(centerPoint.x+[self parseToX:radius Angle:currentAngle],centerPoint.y+[self parseToY:radius Angle:currentAngle]);  
    109.           
    110.         [labelArray addObject:label];  
    111.         [self addSubview:label];          
    112.     }  
    113.     // 设置刻度表的名称  
    114.     UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0 , 0 ,100, 40)];  
    115.     label.autoresizesSubviews = YES;  
    116.     label.textColor = [UIColor whiteColor];  
    117.     label.backgroundColor = [UIColor clearColor];  
    118.     label.textAlignment = UITextAlignmentCenter;  
    119.     label.text = GAUGESTRING;  
    120.     label.center = CGPointMake(centerPoint.x,centerPoint.y*3/2);  
    121.     [self addSubview:label];      
    122. }  
    123.   
    124. /* 
    125.  * setLineMark 绘制刻度的标记 
    126.  * @labelNum NSInteger 刻度是数目 
    127.  */  
    128. -(void)setLineMark:(NSInteger)labelNum  
    129. {  
    130.   
    131.     CGFloat angelDis = (maxAngle - minAngle)/labelNum;  
    132.     CGFloat radius = self.center.x;  
    133.     CGFloat currentAngle;  
    134.     CGPoint centerPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);  
    135.       
    136.     for(int i=0;i<=labelNum;i++)  
    137.     {  
    138.         currentAngle = minAngle + i * angelDis - POINTEROFFSET;  
    139.         //给刻度标记绘制不同的颜色  
    140.         if(i>labelNum*2/3)  
    141.         {  
    142.             CGContextSetStrokeColorWithColor(context, [[UIColor colorWithRed:1 green:0 blue:0 alpha:0.8] CGColor]);  
    143.         }else if(i>labelNum*1/3){  
    144.             CGContextSetStrokeColorWithColor(context, [[UIColor colorWithRed:1 green:1 blue:0 alpha:0.8] CGColor]);  
    145.         }else{  
    146.             CGContextSetStrokeColorWithColor(context, [[UIColor colorWithRed:0 green:1 blue:0 alpha:0.8] CGColor]);  
    147.         }  
    148.         //绘制不同的长短的刻度  
    149.         if(i%5==0)  
    150.         {       
    151.             CGContextSetLineCap(context, kCGLineCapSquare);  
    152.             CGContextSetLineWidth(context, 3);  
    153.             CGContextStrokePath(context);     
    154.             CGContextMoveToPoint(context,centerPoint.x+[self parseToX:radius-25*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-25*scoleNum Angle:currentAngle]);  
    155.             CGContextAddLineToPoint(context,centerPoint.x+[self parseToX:radius-65*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-65*scoleNum Angle:currentAngle]);  
    156.         }else{  
    157.             CGContextSetLineWidth(context, 2);  
    158.             CGContextSetLineCap(context, kCGLineCapSquare);  
    159.             CGContextStrokePath(context);   
    160.             CGContextMoveToPoint(context,centerPoint.x+[self parseToX:radius-25*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-25*scoleNum Angle:currentAngle]);  
    161.             CGContextAddLineToPoint(context,centerPoint.x+[self parseToX:radius-40*scoleNum Angle:currentAngle], centerPoint.y+[self parseToY:radius-40*scoleNum Angle:currentAngle]);     
    162.         }  
    163.     }  
    164. }  
    165.   
    166. /* 
    167.  * setGaugeValue 移动到某个数值 
    168.  * @value CGFloat 移动到的数值 
    169.  * @isAnim BOOL   是否执行动画 
    170.  */  
    171. -(void)setGaugeValue:(CGFloat)value animation:(BOOL)isAnim  
    172. {  
    173.     CGFloat tempAngle = [self parseToAngle:value];  
    174.     gaugeValue = value;  
    175.     //设置转动时间和转动动画  
    176.     if(isAnim){  
    177.         [self pointToAngle:tempAngle Duration:0.6f];  
    178.     }else  
    179.     {  
    180.         [self pointToAngle:tempAngle Duration:0.0f];  
    181.     }  
    182. }  
    183.   
    184. /* 
    185.  * pointToAngle 按角度旋转 
    186.  * @angel CGFloat 角度 
    187.  * @duration CGFloat 动画执行时间 
    188.  */  
    189. - (void) pointToAngle:(CGFloat) angle Duration:(CGFloat) duration  
    190. {  
    191.     CAKeyframeAnimation *anim=[CAKeyframeAnimation animationWithKeyPath:@"transform"];   
    192.     NSMutableArray *values=[NSMutableArray array];   
    193.     anim.duration = duration;  
    194.     anim.autoreverses = NO;  
    195.     anim.fillMode = kCAFillModeForwards;  
    196.     anim.removedOnCompletion= NO;  
    197.       
    198.     CGFloat distance = angle/10;  
    199.     //设置转动路径,不能直接用 CABaseAnimation 的toValue,那样是按最短路径的,转动超过180度时无法控制方向  
    200.     int i = 1;  
    201.     for(;i<=10;i++){  
    202.         [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*i)], 0, 0, 1)]];  
    203.         }  
    204.     //添加缓动效果  
    205.      [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*(i))], 0, 0, 1)]];  
    206.      [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*(i-2))], 0, 0, 1)]];       
    207.      [values addObject:[NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, [self transToRadian:(gaugeAngle+distance*(i-1))], 0, 0, 1)]];  
    208.                                                                              
    209.     anim.values=values; ;  
    210.     [pointer.layer addAnimation:anim forKey:@"cubeIn"];  
    211.       
    212.     gaugeAngle = gaugeAngle+angle;  
    213.       
    214. }  
    215.   
    216. /* 
    217.  * parseToX 角度转弧度 
    218.  * @angel CGFloat 角度 
    219.  */  
    220. -(CGFloat)transToRadian:(CGFloat)angel  
    221. {  
    222.     return angel*M_PI/180;  
    223. }  
    224.   
    225.   
    226. /* 
    227.  * parseToX 根据角度,半径计算X坐标 
    228.  * @radius CGFloat 半径   
    229.  * @angle  CGFloat 角度 
    230.  */  
    231. - (CGFloat) parseToX:(CGFloat) radius Angle:(CGFloat)angle  
    232. {  
    233.     CGFloat tempRadian = [self transToRadian:angle];  
    234.     return radius*cos(tempRadian);  
    235. }  
    236.   
    237. /* 
    238.  * parseToY 根据角度,半径计算Y坐标 
    239.  * @radius CGFloat 半径   
    240.  * @angle  CGFloat 角度 
    241.  */  
    242. - (CGFloat) parseToY:(CGFloat) radius Angle:(CGFloat)angle  
    243. {  
    244.     CGFloat tempRadian = [self transToRadian:angle];  
    245.     return radius*sin(tempRadian);  
    246. }  
    247.   
    248. /* 
    249.  * parseToAngle 根据数据计算需要转动的角度 
    250.  * @val CGFloat 要移动到的数值 
    251.  */  
    252. -(CGFloat) parseToAngle:(CGFloat) val  
    253. {  
    254.     //异常的数据  
    255.     if(val<minNum){  
    256.         return minNum;  
    257.     }else if(val>maxNum){  
    258.         return maxNum;  
    259.     }  
    260.     CGFloat temp =(val-gaugeValue)*angleperValue;  
    261.     return temp;  
    262. }  
    263.   
    264. /* 
    265.  * parseToValue 根据角度计算数值 
    266.  * @val CGFloat 要移动到的角度 
    267.  */  
    268. -(CGFloat) parseToValue:(CGFloat) val  
    269. {  
    270.     CGFloat temp=val/angleperValue;  
    271.     CGFloat temp2=maxNum/2+temp;  
    272.     if(temp2>maxNum){  
    273.         return maxNum;  
    274.     }else if(temp2<maxNum){  
    275.         return maxNum;  
    276.     }  
    277.     return temp2;  
    278. }  
    279.   
    280. - (void)drawRect:(CGRect)rect   
    281. {  
    282.     //获取上下文  
    283.     context = UIGraphicsGetCurrentContext();  
    284.     //设置背景透明  
    285.     CGContextSetFillColorWithColor(context,self.backgroundColor.CGColor);  
    286.     CGContextFillRect(context, rect);  
    287.     //绘制仪表背景      
    288.     [[self gaugeView ]drawInRect:self.bounds];  
    289.     //绘制刻度  
    290.     [self setLineMark:CELLNUM*CELLMARKNUM];  
    291.           
    292.     CGContextStrokePath(context);  
    293. }  
    294.   
    295. @end  

    Demo的下载地址:http://download.csdn.net/detail/toss156/4183721
  • 相关阅读:
    Java学习日记Ⅰ
    docker 安装redis
    maven 打包 把第三方包也打进去
    wiki 配置数据源 编码要是utf8 不能是utf8mb4
    SCFT用公钥登录
    配置tomcat重启脚本
    tomcat
    centos7 搭建rabbitmq服务 3.7.15
    安装openoffice
    tomcat 日期切分
  • 原文地址:https://www.cnblogs.com/wcLT/p/5163341.html
Copyright © 2020-2023  润新知