iOS 雷達(dá)圖的繪制 貝塞爾曲線的使用UIBezierPath

之前一直抱著一種不很好的態(tài)度去寫(xiě)代碼竭恬,不求甚解脉顿,不會(huì)就google卜朗,現(xiàn)在感覺(jué)長(zhǎng)期這樣是不行的拔第,必須自己也依靠實(shí)踐經(jīng)驗(yàn)去寫(xiě)一寫(xiě)框架,發(fā)現(xiàn)并不難场钉,于是寫(xiě)了一個(gè)使用起來(lái)很舒服的圖表蚊俺,可隨意定制。后面還將上傳封裝清晰的“柱狀圖”上傳逛万,供大家交流學(xué)習(xí)泳猬。

QQ20170424-191250.png
需求效果圖
beisaierView.h
beisaierView.m
//  beisaierView.h
//  dxd_貝塞爾
//
//  Created by 竇心東 on 2017/4/20.
//  Copyright ? 2017年 竇心東. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface beisaierView : UIView

/** 頭像的圖片 */
@property (nonatomic,strong) UIImage *header_image;
/** 數(shù)據(jù)源數(shù)組 */
@property (nonatomic,strong) NSArray *value_array;
/** 數(shù)據(jù)元素的名稱(chēng) */
@property (nonatomic,strong) NSArray *title_array;
/** 圓半徑 */
@property (nonatomic,assign) CGFloat cirlR;
/** 頭像的半徑邊框的寬度 */
@property (nonatomic,assign) CGFloat headerimageBoderWidth;
/** 頭像的寬度 */
@property (nonatomic,assign) CGFloat headerimageWidth;
/** 小白點(diǎn) */
@property (nonatomic,assign) CGFloat whiteDianWdith;
/** 小白點(diǎn)邊框的寬度  */
@property (nonatomic,assign) CGFloat whiteDianBoderWdith;

/** label的寬度 */
@property (nonatomic,assign) CGFloat labelWidth;
/** label的寬度 */
@property (nonatomic,assign) CGFloat labelHeight;

/** 圖層的顏色 */
@property (nonatomic,strong) UIColor *TuCengColor;
/** 圓環(huán)的顏色 */
@property (nonatomic,strong) UIColor *cirlColor;
/** 圓環(huán)之間的間距 */
@property (nonatomic,assign) CGFloat cirlMargin;

/** 小圖層減少大圖層值得比例 百分比 small_percent*cirlR*/
@property (nonatomic,assign) CGFloat small_percent;
@end

//
//  beisaierView.m
//  dxd_貝塞爾
//
//  Created by 竇心東 on 2017/4/20.
//  Copyright ? 2017年 竇心東. All rights reserved.
//

#import "beisaierView.h"
#define ColorWithHEAL [UIColor colorWithRed:0/255.0f green:197/255.0f blue:188/255.0f alpha:1]//大圖層的顏色
#define ColorWithHEALa [UIColor colorWithRed:0/255.0f green:197/255.0f blue:188/255.0f alpha:0.3]//小圖層的顏色
#define P_M(x,y) CGPointMake(x, y)
@interface beisaierView (){
    
    
}

/** self 的寬度 */
@property (nonatomic,assign) CGSize beisaierView_size;

@end

@implementation beisaierView
-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self setUI];
        
    }
    return self;
    
}
- (void)setUI{
    
    _beisaierView_size = self.frame.size;
    _cirlR = _beisaierView_size.width/2;
    _whiteDianWdith = 5;
    _labelWidth = 50;
    _labelHeight = 30;
    _TuCengColor = ColorWithHEAL;
    _cirlColor = [UIColor lightGrayColor];
    _cirlMargin = 30;
    _value_array = @[@"40",@"50",@"80",@"50",@"90",@"50",@"70",@"90",@"30"];
    _title_array = @[@"陰虛",@"痰濕",@"溫?zé)?,@"血瘀",@"氣郁",@"特稟",@"平和",@"氣虛",@"陽(yáng)虛"];
    _headerimageWidth = 20;
    _small_percent = 0.2;
    _whiteDianBoderWdith = 1;
    _headerimageBoderWidth = 1;
    _header_image = [UIImage imageNamed:@"背景.jpg"];
}

-(void)setValue_array:(NSArray *)value_array{
    _value_array = value_array;
}
-(void)setTitle_array:(NSArray *)title_array{
    _title_array = title_array;
}
-(void)setCirlR:(CGFloat)cirlR{
    _cirlR = cirlR;
}
-(void)setWhiteDianWdith:(CGFloat)whiteDianWdith{
    _whiteDianWdith = whiteDianWdith;
}
-(void)setWhiteDianBoderWdith:(CGFloat)whiteDianBoderWdith{
    _whiteDianBoderWdith = whiteDianBoderWdith;
}
-(void)setLabelWidth:(CGFloat)labelWidth{
    _labelWidth = labelWidth;
}
-(void)setLabelHeight:(CGFloat)labelHeight{
    _labelHeight = labelHeight;
}
-(void)setCirlColor:(UIColor *)cirlColor{
    _cirlColor = cirlColor;
}
-(void)setTuCengColor:(UIColor *)TuCengColor{
    _TuCengColor = TuCengColor;
}
-(void)setCirlMargin:(CGFloat)cirlMargin{
    _cirlMargin = cirlMargin;
}
-(void)setHeaderimageWidth:(CGFloat)headerimageWidth{
    _headerimageWidth = headerimageWidth;
}
-(void)setHeaderimageBoderWidth:(CGFloat)headerimageBoderWidth{
    _headerimageBoderWidth = headerimageBoderWidth;
}
-(void)setSmall_percent:(CGFloat)small_percent{
    _small_percent = small_percent;
}
-(void)setHeader_image:(UIImage *)header_image{
    _header_image = header_image;
}
-(void)layoutSubviews{
    [super layoutSubviews];
    //設(shè)置frame
    
}


#pragma mark - 空心圓
- (void)drawRect:(CGRect)rect
{
    //畫(huà)虛線的
    CGFloat dashPattern[] = {2,1};// 實(shí)線長(zhǎng)為2,空白為1
    CGFloat lineWidth = 0.5;
    
    CGFloat _headerimageR = _headerimageWidth/2;//頭像的半徑
    
    //畫(huà)多少個(gè)圓環(huán)
    for (int i = 0; i<3; i++) {
        UIBezierPath* aPath_yuanhuan = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(i*_cirlMargin, i*_cirlMargin, _beisaierView_size.width-(i*_cirlMargin*2), _beisaierView_size.width-(i*_cirlMargin*2))];
        [aPath_yuanhuan setLineDash:dashPattern count:1 phase:1];
        aPath_yuanhuan.lineWidth = lineWidth;
        [_cirlColor set];
        aPath_yuanhuan.lineCapStyle = kCGLineCapRound; //線條拐角
        aPath_yuanhuan.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理
        [aPath_yuanhuan stroke];
    }
    float maxValue = [[_value_array valueForKeyPath:@"@max.intValue"] floatValue];//value array里面的最大值
    UIBezierPath* aPath = [UIBezierPath bezierPath];//??外邊的??大圖層
    aPath.lineWidth = 1.0;
    aPath.lineCapStyle = kCGLineCapRound; //線條拐角
    aPath.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理
    
    UIBezierPath* aPathsmall = [UIBezierPath bezierPath];//??里邊的??小圖層
    aPathsmall.lineWidth = 1.0;
    aPathsmall.lineCapStyle = kCGLineCapRound; //線條拐角
    aPathsmall.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理
    
    NSMutableArray *pointArray = [NSMutableArray array];//大圖層的頂點(diǎn)位置
    NSMutableArray *pointArraysmall = [NSMutableArray array];//小涂層的頂點(diǎn)位置
    
    //提取出大小圖層的point
    for (int i = 0; i<_value_array.count; i++) {
        
        NSValue *value = [NSValue valueWithCGPoint:[self calcCircleCoordinateWithCenter:CGPointMake(_cirlR, _cirlR) andWithAngle:i*(360/_value_array.count) andWithRadius:([_value_array[i] floatValue]/maxValue+(_headerimageR+_whiteDianWdith+_whiteDianBoderWdith+_headerimageBoderWidth)/_cirlR)*(_cirlR-_headerimageR-_whiteDianBoderWdith-_whiteDianWdith-_headerimageBoderWidth)]];//20為頭像的半徑
        
        [pointArray addObject:value];
        
        NSValue *valuesmall = [NSValue valueWithCGPoint:[self calcCircleCoordinateWithCenter:CGPointMake(_cirlR, _cirlR) andWithAngle:i*(360/_value_array.count) andWithRadius:([_value_array[i] floatValue]/maxValue+(_headerimageR+_whiteDianBoderWdith+_headerimageBoderWidth)/_cirlR-_small_percent)*(_cirlR-_headerimageR-_whiteDianBoderWdith-_whiteDianWdith-_headerimageBoderWidth)]];//20為頭像的半徑
        
        [pointArraysmall addObject:valuesmall];
        
        
        
    }
    
    for (int i = 0; i<pointArray.count; i++) {
        UIBezierPath *path3 = [UIBezierPath bezierPath];
        [path3 moveToPoint:CGPointMake(_cirlR,_cirlR)];
        CGPoint pointyuanshangde = [self calcCircleCoordinateWithCenter:CGPointMake(_cirlR,_cirlR) andWithAngle:i*(360/pointArray.count) andWithRadius:_cirlR];
        [path3 addLineToPoint:pointyuanshangde];
        [path3 setLineWidth:lineWidth];
        [path3 setLineDash:dashPattern count:1 phase:1];
        [[UIColor lightGrayColor] setStroke];
        [path3 stroke];//畫(huà)的圓環(huán)
        CGPoint p = [pointArray[i] CGPointValue];
        CGPoint psmall = [pointArraysmall[i] CGPointValue];
        
        if (i == 0) {
            [aPath moveToPoint:p];
            [aPathsmall moveToPoint:psmall];
        }else{
            //畫(huà)曲線 找出控制點(diǎn)
            //            CGPoint nextP = [pointArray[i-1] CGPointValue];
            //            CGPoint control1 = P_M(p.x + (nextP.x - p.x) / 2.0, nextP.y);
            //            CGPoint control2 = P_M(p.x + (nextP.x - p.x) / 2.0, p.y);
            //
            //            [aPath addCurveToPoint:p controlPoint1:control1 controlPoint2:control2];
        }
        
        [aPath addLineToPoint:p];
        [aPathsmall addLineToPoint:psmall];
        [ColorWithHEALa setFill];
        
        
        UIView *cile = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _whiteDianWdith, _whiteDianWdith)];
        cile.backgroundColor = [UIColor whiteColor];
        
        cile.layer.borderWidth = _whiteDianBoderWdith;
        cile.layer.borderColor = ColorWithHEAL.CGColor;
        cile.layer.masksToBounds = YES;
        cile.layer.cornerRadius = _whiteDianWdith/2;
        cile.center = p;
        [self addSubview:cile];
        
        
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, _labelWidth, _labelHeight)];
        label.text = _title_array[i];
        label.font = [UIFont systemFontOfSize:12];
        label.textColor = ColorWithHEAL;
        CGFloat selfWidth = self.frame.size.width;
        CGFloat selfHeight = self.frame.size.height;
        CGFloat labelWidth = label.frame.size.width;
        CGFloat labelHeight = label.frame.size.height;
        
        if (p.x<selfWidth/2-labelWidth) {
            CGFloat x = p.x - labelWidth/2;
            CGFloat y;
            if (p.y<(selfHeight/2-labelHeight)) {
                y = p.y - labelHeight/2;
                
            } else {
                y = p.y + labelHeight/2;
                
            }
            label.center = CGPointMake(x, y);
            
        } else {
            CGFloat x = p.x + labelWidth/2;
            
            CGFloat y;
            if (p.y<(selfHeight/2-labelHeight)) {
                y = p.y - labelHeight/2;
                
            } else {
                y = p.y + labelHeight/2;
                
            }
            label.center = CGPointMake(x, y);
        }
        if (p.y>(selfHeight/2-labelHeight/2)&&p.y<(selfHeight/2+labelHeight/2)) {
            if (p.x<selfWidth/2-labelHeight) {
                
                label.center = CGPointMake(p.x-labelWidth/2, p.y);
            }else{
                label.center = CGPointMake(p.x+labelWidth/2, p.y);
            }
        }else{
            if (p.x>(selfWidth/2-labelWidth/2)&&p.x<(selfWidth/2+labelWidth/2)) {
                if (p.y<selfHeight/2-labelWidth) {
                    label.center = CGPointMake(p.x, p.y-labelHeight/2);
                } else {
                    label.center = CGPointMake(p.x, p.y+labelHeight/2);
                }
            }
        }
        label.textAlignment = NSTextAlignmentCenter;
        
        [self addSubview:label];
    }
    
    [aPath fill];
    [aPathsmall fill];
    
    UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _headerimageWidth, _headerimageWidth)];
    [imageview setImage:_header_image];
    imageview.center = CGPointMake(_cirlR, _cirlR);
    imageview.layer.masksToBounds = YES;
    imageview.layer.cornerRadius = _headerimageR;
    imageview.layer.borderWidth = _headerimageBoderWidth;
    imageview.layer.borderColor = [UIColor whiteColor].CGColor;
    [self addSubview:imageview];
    
}
#pragma mark 計(jì)算圓圈上點(diǎn)在IOS系統(tǒng)中的坐標(biāo)
-(CGPoint) calcCircleCoordinateWithCenter:(CGPoint) center  andWithAngle : (CGFloat) angle andWithRadius: (CGFloat) radius{
    CGFloat x2 = radius*cosf(angle*M_PI/180);
    CGFloat y2 = radius*sinf(angle*M_PI/180);
    return CGPointMake(center.x+x2, center.y-y2);
}
/**
 :douxindong
 :2017-4-20 1:02:26
 : 1.0.0
 --------------------------------------------------------------
 功能說(shuō)明
 --------------------------------------------------------------
 根據(jù)IOS視圖中圓組件的中心點(diǎn)(x,y)、半徑(r)得封、圓周上某一點(diǎn)與圓心的角度這3個(gè)
 條件來(lái)計(jì)算出該圓周某一點(diǎn)在IOS中的坐標(biāo)(x2,y2)埋心。
 
 注意:
 (1)IOS坐標(biāo)體系與數(shù)學(xué)坐標(biāo)體系有差別,因此不能完全采用數(shù)學(xué)計(jì)算公式忙上。
 (2)數(shù)學(xué)計(jì)算公式:
 x2=x+r*cos(角度值*PI/180)
 y2=y+r*sin(角度值*PI/180)
 (3)IOS中計(jì)算公式:
 x2=x+r*cos(角度值*PI/180)
 y2=y-r*sin(角度值*PI/180)
 
 --------------------------------------------------------------
 參數(shù)說(shuō)明
 --------------------------------------------------------------
 @param (CGPoint) center
 
 圓圈在IOS視圖中的中心坐標(biāo)拷呆,即該圓視圖的center屬性
 
 @param (CGFloat) angle
 角度值,是0~360之間的值疫粥。
 注意:
 (1)請(qǐng)使用下面坐標(biāo)圖形進(jìn)行理解茬斧。
 (2)角度是逆時(shí)針轉(zhuǎn)的,從x軸中心(0,0)往右是0度角(或360度角)梗逮,往左是180度角项秉,往上是90度角,往下是270度角慷彤。
 
 (y)
 ^
 |
 |
 |
 |
 -----------------> (x)
 |(0,0)
 |
 |
 |
 
 @param (CGFloat) radius
 圓周半徑
 */

@end

//
//  ViewController.m
//  dxd_貝塞爾
//
//  Created by 竇心東 on 2017/4/20.
//  Copyright ? 2017年 竇心東. All rights reserved.
//

#import "ViewController.h"
#import "beisaierView.h"
@interface ViewController ()

{
    beisaierView *ber;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    
    ber = [[beisaierView alloc] initWithFrame:CGRectMake(30, 50, 350, 350)];
    
    ber.backgroundColor = [UIColor whiteColor];
    ber.header_image = [UIImage imageNamed:@"HEAL.jpg"];
    ber.headerimageWidth = 40;
    ber.value_array = @[@"40",@"50",@"80",@"50",@"90",@"50",@"70",@"90",@"30"];
    ber.title_array = @[@"陰虛",@"痰濕",@"溫?zé)?,@"血瘀",@"氣郁",@"特稟",@"平和",@"氣虛",@"陽(yáng)虛"];
    [self.view addSubview:ber];
    

    
    
    [self Da_Guang_Gao];
    
}
- (void)Da_Guang_Gao{

    CGFloat margin = 10;
    NSArray *imagearray = @[@"appStore.png",@"wechat.png",@"HEAL.jpg"];
    NSArray *imagearraytitle = @[@"appstore下載",@"微信公眾號(hào)",@"HEAL小程序"];
    for (int i = 0; i<imagearray.count; i++) {
        
        UIImageView *imageview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imagearray[i]]];
        imageview.frame = CGRectMake(margin+i*(120+margin), CGRectGetMaxY(ber.frame)+30, 120, 120);
        
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10+i*(120+margin),  CGRectGetMaxY(imageview.frame)+30, 120, 40)];
        label.textAlignment = NSTextAlignmentCenter;
        label.text = imagearraytitle[i];
        [self.view addSubview:label];
        [self.view addSubview:imageview];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

leida.gif

效果圖

Git倉(cāng)庫(kù)代碼demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末娄蔼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瞬欧,更是在濱河造成了極大的恐慌贷屎,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艘虎,死亡現(xiàn)場(chǎng)離奇詭異唉侄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)野建,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)属划,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人候生,你說(shuō)我怎么就攤上這事同眯。” “怎么了唯鸭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵须蜗,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我目溉,道長(zhǎng)明肮,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任缭付,我火速辦了婚禮柿估,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘陷猫。我一直安慰自己秫舌,他們只是感情好的妖,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著足陨,像睡著了一般嫂粟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钠右,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天赋元,我揣著相機(jī)與錄音,去河邊找鬼飒房。 笑死搁凸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狠毯。 我是一名探鬼主播护糖,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼嚼松!你這毒婦竟也來(lái)了嫡良?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤献酗,失蹤者是張志新(化名)和其女友劉穎寝受,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體罕偎,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡很澄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颜及。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甩苛。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俏站,靈堂內(nèi)的尸體忽然破棺而出讯蒲,到底是詐尸還是另有隱情,我是刑警寧澤肄扎,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布墨林,位于F島的核電站,受9級(jí)特大地震影響犯祠,放射性物質(zhì)發(fā)生泄漏萌丈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一雷则、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肪笋,春花似錦月劈、人聲如沸度迂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惭墓。三九已至,卻和暖如春而姐,著一層夾襖步出監(jiān)牢的瞬間腊凶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工拴念, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钧萍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓政鼠,卻偏偏與公主長(zhǎng)得像风瘦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子公般,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容