IOS上實現(xiàn)的自定義儀表盤示例
今天給大家?guī)硪粋€自定義的儀表盤,效果圖如下。
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
指針的旋轉(zhuǎn)是通過QuartzCore.framework中的CATransform3DRotate 來實現(xiàn)的,所以一定要記得把框架添加進(jìn)來。當(dāng)然在旋轉(zhuǎn)之前,我們還需要把指針的中心pointer.layer.anchorPoint 移動到你需要的轉(zhuǎn)動中心。
在設(shè)置旋轉(zhuǎn)動畫的時候,我們用的不是CABaseAnimiation 而是用 CAKeyframeAnimation。這是因為如果使用中的 toValue 來實現(xiàn)旋轉(zhuǎn)的話,它默認(rèn)是以最小的旋轉(zhuǎn)的,如果要實現(xiàn)控制旋轉(zhuǎn)的方向的話,我們就只能用關(guān)鍵幀來設(shè)置旋轉(zhuǎn)的路徑。用關(guān)鍵幀的好處還有一個,就是可以給指針添加,旋轉(zhuǎn)到指定位置以后的左右擺動的效果。
繪制儀表盤是通過Quartz2D來實現(xiàn)的,首先我們需要用UIGraphicsGetCurrentContext函數(shù)來獲取一個Context上下文,就是相當(dāng)于獲取一個畫布。然后就可以在上面通過三角函數(shù)的計算,畫出背景圖片,和上面的刻度線了。
// 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 /************************************************ 儀表盤的大小不建議設(shè)置的太小。 長寬都是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) { //設(shè)置背景透明 [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]; //設(shè)置文字標(biāo)簽 [self setTextLabel:CELLNUM]; //設(shè)置指針到0位置 pointer.layer.transform = CATransform3DMakeRotation([self transToRadian:-MAXOFFSETANGLE], 0, 0, 1); } return self; } /* * setTextLabel 繪制刻度值 * @labelNum NSInteger 刻度值的數(shù)目 */ -(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]; //設(shè)置刻度的文字的格式 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]; } // 設(shè)置刻度表的名稱 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 繪制刻度的標(biāo)記 * @labelNum NSInteger 刻度是數(shù)目 */ -(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; //給刻度標(biāo)記繪制不同的顏色 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 移動到某個數(shù)值 * @value CGFloat 移動到的數(shù)值 * @isAnim BOOL 是否執(zhí)行動畫 */ -(void)setGaugeValue:(CGFloat)value animation:(BOOL)isAnim { CGFloat tempAngle = [self parseToAngle:value]; gaugeValue = value; //設(shè)置轉(zhuǎn)動時間和轉(zhuǎn)動動畫 if(isAnim){ [self pointToAngle:tempAngle Duration:0.6f]; }else { [self pointToAngle:tempAngle Duration:0.0f]; } } /* * pointToAngle 按角度旋轉(zhuǎn) * @angel CGFloat 角度 * @duration CGFloat 動畫執(zhí)行時間 */ - (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; //設(shè)置轉(zhuǎn)動路徑,不能直接用 CABaseAnimation 的toValue,那樣是按最短路徑的,轉(zhuǎn)動超過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 角度轉(zhuǎn)弧度 * @angel CGFloat 角度 */ -(CGFloat)transToRadian:(CGFloat)angel { return angel*M_PI/180; } /* * parseToX 根據(jù)角度,半徑計算X坐標(biāo) * @radius CGFloat 半徑 * @angle CGFloat 角度 */ - (CGFloat) parseToX:(CGFloat) radius Angle:(CGFloat)angle { CGFloat tempRadian = [self transToRadian:angle]; return radius*cos(tempRadian); } /* * parseToY 根據(jù)角度,半徑計算Y坐標(biāo) * @radius CGFloat 半徑 * @angle CGFloat 角度 */ - (CGFloat) parseToY:(CGFloat) radius Angle:(CGFloat)angle { CGFloat tempRadian = [self transToRadian:angle]; return radius*sin(tempRadian); } /* * parseToAngle 根據(jù)數(shù)據(jù)計算需要轉(zhuǎn)動的角度 * @val CGFloat 要移動到的數(shù)值 */ -(CGFloat) parseToAngle:(CGFloat) val { //異常的數(shù)據(jù) if(val<minNum){ return minNum; }else if(val>maxNum){ return maxNum; } CGFloat temp =(val-gaugeValue)*angleperValue; return temp; } /* * parseToValue 根據(jù)角度計算數(shù)值 * @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(); //設(shè)置背景透明 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
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS多線程應(yīng)用開發(fā)中使用NSOperation類的基本方法
這篇文章主要介紹了iOS多線程應(yīng)用開發(fā)中使用NSOperation類的基本方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-11-11iOS開發(fā)之統(tǒng)計Xcode工程的代碼行數(shù)
這篇文章主要給大家介紹了在iOS開發(fā)中,如果想要統(tǒng)計Xcode工程的代碼行數(shù)該如何實現(xiàn),文章給出了詳細(xì)的方法和示例代碼,對大家的理解和學(xué)習(xí)很有幫助,本文中還分享了統(tǒng)計java文件和xml文件的代碼,有需要的朋友們下面來一起看看吧。2016-10-10iOS實現(xiàn)支持小數(shù)的星星評分組件實例代碼
程序中需要打分的功能,在網(wǎng)上找了幾個,都不是很滿意。所以自己動手實現(xiàn)了一個,下面這篇文章主要給大家介紹了關(guān)于利用iOS實現(xiàn)支持小數(shù)的星星評分組件的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-08-08iOS自定義UITableView實現(xiàn)不同系統(tǒng)下的左滑刪除功能詳解
關(guān)于左滑刪除這塊,相信不少朋友都遇到過。下面這篇文章主要給大家介紹了關(guān)于iOS如何自定義UITableView實現(xiàn)不同系統(tǒng)下的左滑刪除功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09iOS使用pageViewController實現(xiàn)多視圖滑動切換
這篇文章主要為大家詳細(xì)介紹了iOS使用pageViewController實現(xiàn)多視圖滑動切換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06