iOS 動態繪製漸變色圓環

思路

  • 畫靜態圓的方法有不少,例如UIBezierPath或者UIBezierPath + CAShapeLayer等等,本文也會用到.git

  • 動態效果即不斷的更新圓環的角度(弧度),而後不斷的繪製圓,達到動態效果,使用Quartz2d在drawRect中繪製github

  • CGContextDrawLinearGradient畫圓,參數CGGradientRef設置漸變色,startPoint和endPoint設置漸變色方向數組

  • 封裝到一個自定義View,快速使用(文章末尾附Demo)bash

最終效果

手動繪製ide

手動畫圓效果圖.gif
手動畫圓效果圖.gif

使用:

//1.建立圓環
    TYCircleViewConfigure *configure = [[TYCircleViewConfigure alloc]init];
    
    configure.lineColor = [UIColor lightGrayColor];//圓環背景色
    configure.circleLineWidth = 10;//圓環寬度
    configure.isClockwise = YES;//設置順時針方向畫圓
    
    configure.startPoint = CGPointMake(width / 2, 0);
    configure.endPoint   = CGPointMake(width / 2 , width);//漸變色分佈方向
    //漸變色的顏色
    configure.colorArr = @[
                            (id)TYColorFromRGB(0x349CF7).CGColor,//淺藍色
                            (id)TYColorFromRGB(0xFE5858).CGColor,//深橙色
                            (id)TYColorFromRGB(0x72DC4F).CGColor //淺綠色
                            ];
    //每一個顏色區域值
    configure.colorSize = @[@0,@0.3,@0.8];
    
    TYCircleView *circleView = [[TYCircleView alloc]initWithFrame:CGRectMake(x , y, width, width) configure:configure];

    [self.view addSubview:circleView];
  
複製代碼

自動繪製動畫

  • 自動繪製圓環其實只要把slider的value和圓環中心label的顯示數值結合起來就能夠,即動態改變圓環中心label的數值
  • 怎麼動態改變label的數值呢,推薦輪子:UICountingLabel,具體實現相對簡單,再也不介紹,結合中有坑不能逾越的,歡迎評論下方留言~

主要過程

1.文件.h中建立須要用到的屬性的配置類ui

//配置屬性
/*********************  TYCircleViewConfigure ************************/

@interface TYCircleViewConfigure : NSObject

/** 圓環線條寬度 */
@property (nonatomic, assign) CGFloat circleLineWidth;
/** 圓環的顏色 */
@property (nonatomic, strong) UIColor *lineColor;
/** 是不是順時針 默認是NO:逆時針 */
@property (nonatomic, assign) BOOL isClockwise;
/** 漸變色方向 起始座標 */
@property (nonatomic, assign) CGPoint startPoint;
/** 漸變色方向 結束座標 */
@property (nonatomic, assign) CGPoint endPoint;
/** 漸變色的顏色數組 */
@property (nonatomic, strong) NSArray *colorArr;
/** 每一個顏色的起始位置數組 注:每一個元素 0 <= item < 1 */
@property (nonatomic, strong) NSArray *colorSize;

//注意: colorArr.count 和 colorSize.count 必須相等
//不相等時,漸變色最終顯示出來的樣子和指望的會有差別

@end
複製代碼
  1. 繪製灰色的背景圓環
//繪製背景圓
- (void)drawBackCircleView {
    
    //1.UIBezierPath建立一個圓環路徑
    //圓心
    CGPoint arcCenter = CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0);
    //半徑 , circleLineWidth = 圓環線條寬度
    CGFloat radius = (self.frame.size.width - _configure.circleLineWidth)/2.0;
    //開始弧度:-M_PI_2,豎直向上; 結束弧度:-M_PI_2 + M_PI*2,一圈 clockwise:YES逆時針 NO順時針
    //clockwise = NO時,若結束弧度 = -M_PI_2 + M_PI*2, 則圓環消失歸零
    UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:radius  startAngle:-M_PI_2 endAngle:-M_PI_2 + M_PI*2 clockwise:YES];
    
    //2.建立一個ShapeLayer
    CAShapeLayer *bgLayer = [CAShapeLayer layer];
    bgLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width);
    bgLayer.fillColor = [UIColor clearColor].CGColor;//圓環路徑填充顏色
    bgLayer.lineWidth = _configure.circleLineWidth;//圓環寬度
    bgLayer.strokeColor = _configure.lineColor.CGColor;//路徑顏色
    bgLayer.strokeStart = 0.f;//路徑開始位置
    bgLayer.strokeEnd = 1.f;//路徑結束位置
    bgLayer.path = circle.CGPath;
    
    //3.把路徑設置到layer上,換出背景圓環
    [self.layer addSublayer:bgLayer];
    
}
複製代碼
  • 關於弧度的起始位置的弧度值(開始弧度和結束弧度)咱們能夠用一張圖來描述,這個圖描述了順時針方向的弧度值,那麼若是是逆時針的話,則-M_PI_2即表明正上方
    angles_location

3.在TYDrawCircleView的實現中,重寫drawRect,繪製圓環atom

- (void)drawRect:(CGRect)rect {
   
    //獲取圖形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //設置線的寬度
    CGContextSetLineWidth(ctx, _configure.circleLineWidth);
    //設置圓環線條的兩個端點作圓滑處理
    CGContextSetLineCap(ctx, kCGLineCapRound);
    //設置畫筆顏色
    CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
    //設置圓心
    CGFloat originX = rect.size.width / 2;
    CGFloat originY = rect.size.height / 2;
    //計算半徑
    CGFloat radius = MIN(originX, originY) - _configure.circleLineWidth/2.0;
    //創建一個最小初始弧度值,避免進度progress爲0或1時圓環消失
    CGFloat minAngle = M_PI/90 - self.progress * M_PI/80;
    //逆時針畫一個圓弧
    if (self.configure.isClockwise) {

        CGContextAddArc(ctx, rect.size.width / 2, rect.size.height / 2, radius, -M_PI_2, -M_PI_2 + minAngle + (2 * M_PI)*self.progress, NO);
    }else{
        
        CGContextAddArc(ctx, rect.size.width / 2, rect.size.height / 2, radius, -M_PI_2, -M_PI_2 - minAngle + (2 * M_PI)*(1-self.progress), YES);
    }
    
    //2. 建立一個漸變色
    CGFloat locations[_configure.colorSize.count];
    for (NSInteger index = 0; index < _configure.colorSize.count; index++) {
        locations[index] = [_configure.colorSize[index] floatValue];
    }
    
    //建立RGB色彩空間,建立這個之後,context裏面用的顏色都是用RGB表示
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,(__bridge CFArrayRef _Nonnull)_configure.colorArr, _configure.colorSize.count==0?NULL:locations);

    //釋放色彩空間
    CGColorSpaceRelease(colorSpace);
    colorSpace = NULL;
    
    //3.畫出圓環路徑
    CGContextReplacePathWithStrokedPath(ctx);
    //剪裁路徑
    CGContextClip(ctx);
    
    //4.用漸變色填充,修改填充色的方向
    CGContextDrawLinearGradient(ctx, gradient, _configure.startPoint, _configure.endPoint, 1);
    
    //釋放漸變色
    CGGradientRelease(gradient);
    
}
複製代碼
  1. 動態畫圓
  • 利用slider手動改變其value,關聯slider的value到progress,當progress改變時:
- (void)setProgress:(CGFloat)progress {
    _progress = progress;
    _circleView.progress = progress;
  
    [_circleView setNeedsDisplay];  //重繪TYDrawCircleView,即調用TYDrawCircleView的DrawRect方法
}
複製代碼

漸變色講解

  • 漸變色方向

咱們在TYDrawCircleView的重DrawRect方法中用CGContextDrawLinearGradient方法來畫出圓環,並設置圓環的漸變色gradient和漸變色分佈方向, startPoint即漸變色的起始點位置, endPoint即漸變色的終點位置 spa

image.png
在"使用"中:

//width = 圓的直徑
    configure.startPoint = CGPointMake(width / 2, 0);
    configure.endPoint   = CGPointMake(width / 2 , width);//漸變色分佈方向
複製代碼

咱們設置tartPoint = CGPointMake(width / 2, 0)即點A的位置,configure.endPoint = CGPointMake(width / 2 , width)即點B的位置,其餘位置的話你們能夠自行嘗試code

  • 漸變色分佈區域

咱們在"使用"中,設置了三種漸變色

//漸變色的顏色
    configure.colorArr = @[
                            (id)TYColorFromRGB(0x349CF7).CGColor,//淺藍色
                            (id)TYColorFromRGB(0xFE5858).CGColor,//深橙色
                            (id)TYColorFromRGB(0x72DC4F).CGColor //淺綠色
                            ];
複製代碼

在不設置configure.colorSize (每一個顏色區域值)時,三個顏色根據漸變色方向,依次均等分佈 當咱們不須要三個顏色均等分佈時,能夠經過設置configure.colorSize分別給三個顏色設置起始位置和結束位置

//每一個顏色區域值
    configure.colorSize = @[@0,@0.3,@0.8];
複製代碼

顏色分佈.png

注意:

1.configure.colorSize數組中元素個數要和configure.colorArr相等,即顏色的個數和顏色區域值要一一對應,不然最終繪製的漸變色效果可能和指望的不一樣

2.configure.colorSize數組中每一個元素表明了對應顏色的從分佈方向(本demo中即Y軸方向)的起始位置,整個區域的值爲1,顏色的區域值必須介於0和1之間纔有效

3.若是configure.colorSize數組中的元素沒有按照必定的大小順序排列,顏色的位置就會出現錯亂的現象

結語

1.關於其餘解釋代碼中的註釋也比較詳細,有不懂的地方能夠留言和我交流

2.Demo地址:github.com/TynnPassBy/…

3.碼字不易,若是幫助到你得話,請點個贊吧~

表情包.jpeg
相關文章
相關標籤/搜索