使用 CALayer 的 mask 畫一個漸變三彩圓弧

要實現上面這個三彩圓弧環(huán)姜凄,可以用三個步驟實現:

  1. 使用UIBezierPath畫出圓弧上的每個小矩形
  2. 新建一個形狀圖層CAShaperLayer吸祟,其路徑設置為上個步驟的路徑
  3. 新建一個漸變圖層CAGradientLayer棺妓,其mask設置為上個步驟的形狀圖層

首先褪那,初始化一個UIView

#define DEGREES_TO_RADIANS(x) (M_PI * (x) / 180.0)
static CGFloat const kCircleDiameter = 230;

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _startDegree = -130;
        _endDegree = 130;
        _totalSteps = 31;
               
        self.backgroundColor = [UIColor colorWithRed:44.0/255.0 green:62.0/255.0 blue:80.0/255.0 alpha:1.0];//[UIColor whiteColor];
    }
    
    return self;
}

畫圓弧的路徑鲤遥,每次先畫一個固定位置上的圓角小矩形斋日,然后進行旋轉變換得到不同位置上的矩形:

- (void)drawRect:(CGRect)rect {
    
    CGRect circleRect;
    if (rect.size.width > kCircleDiameter) {
        circleRect = CGRectInset(rect, (rect.size.width-kCircleDiameter)/2, 20);
    } else {
        circleRect = CGRectInset(rect, 20, 20);
    }
    
    // 初始化圓弧路徑饰恕,每個小矩形都添加到這個路徑中
    UIBezierPath *path = [[UIBezierPath alloc] init];
    
    CGFloat radius = MIN(circleRect.size.width, circleRect.size.height)/2;
    CGPoint center = CGPointMake(rect.size.width/2, rect.size.height/2);

    CGFloat stepDegree = (self.endDegree-self.startDegree)/(self.totalSteps-1);
    CGFloat squareWidth = 4;
    CGRect squareRect = CGRectMake((rect.size.width-squareWidth)/2, 20, squareWidth, 13);// CGRectInset(rect, rect.size.width*0.45, rect.size.height*.05);
    for (int i=0; i<self.totalSteps; i++) {
        // 畫一個帶圓角的小矩形
        UIBezierPath *squarePath = [UIBezierPath bezierPathWithRoundedRect:squareRect cornerRadius:squareWidth/2];
         // 計算需要旋轉的角度
        NSInteger degreeToRotate = self.startDegree+i*stepDegree;
        // 變換坐標
        [squarePath applyTransform:CGAffineTransformMakeTranslation(-center.x, -center.y)];
        // 旋轉
        [squarePath applyTransform:CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degreeToRotate))];
        // 還原坐標
        [squarePath applyTransform:CGAffineTransformMakeTranslation(center.x, center.y)];

        // 將當前得到的小矩形添加到圓弧路徑中
        [path appendPath:squarePath];
    }
    
    // 填色
    [[UIColor redColor] setFill];
    [path fill];

得到的圖形如下:


如何將漸變色填充到每個小矩形挠羔?CAGradientLayer是連續(xù)的漸變圖層,但由于小矩形并不連續(xù)埋嵌,所以可以使用圖層的蒙板mask破加。將圓弧路徑賦值給一個 CAShaperLayer,勾畫出圓弧的路徑形狀雹嗦,然后用這個形狀圖層作漸變層的蒙板范舀,從而得到我們需要的效果圖:

//  在上面的代碼中注釋掉以下兩行代碼
//    [[UIColor redColor] setFill];
//    [path fill];

    // 添加以下行  
    CAGradientLayer* grad = [[CAGradientLayer alloc] init];
    grad.frame = rect;
    grad.colors = @[(id)[UIColor colorWithRed:246.0/255.0 green:71.0/255.0 blue:71.0/255.0 alpha:1.0].CGColor,
                    (id)[UIColor colorWithRed:253.0/255.0 green:188.0/255.0 blue:51.0/255.0 alpha:1.0].CGColor,
                    (id)[UIColor colorWithRed:32.0/255.0 green:197.0/255.0 blue:102.0/255.0 alpha:1.0].CGColor];

    // 漸變的起始點為左上角
    grad.startPoint = CGPointMake(0, 0);
    // 漸變的終點為右上角合是,從左向右水平漸變
    grad.endPoint = CGPointMake(1, 0);
    // 漸變位置在0.15,0.55锭环,0.8聪全,漸變位置個數和colors的顏色個數保持一致
    grad.locations = @[@0.15, @0.55, @0.8];
   
   // 初始化 CAShapeLayer 為蒙板層
    CAShapeLayer* mask = [[CAShapeLayer alloc] init];
    mask.frame = rect;
    // mask路徑設置為上面的路徑
    mask.path = path.CGPath;
    mask.fillColor = [UIColor blackColor].CGColor;
    // 設置漸變層的 mask
    grad.mask = mask;
    
    [self.layer addSublayer:grad];

最終效果圖:


蘋果文檔中關于蒙板的解釋:

An optional layer whose alpha channel is used to mask the layer’s content. The layer’s alpha channel determines how much of the layer’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through but fully transparent pixels block that content.

蒙板也是一個圖層,蒙板圖層的alpha值決定了content圖層的顯示區(qū)域辅辩。alpha為1時顯示content难礼,alpha為0時不顯示content

知道如何使用圖層的蒙板玫锋,這篇如何用 Core Graphics 繪制一個漂亮的三彩圓弧提到的方法可以簡化成以下代碼蛾茉,這里加了一個小改動,讓圓弧的邊緣有弧度:

CGFloat radius = rect.size.width/2;
    CGPoint center = CGPointMake(radius, radius);
    CGFloat startAngle = 0.9*M_PI;
    CGFloat endAngle = 0.1*M_PI;
    
    CAShapeLayer *arc = [CAShapeLayer layer];
    arc.frame = rect;
    arc.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius-20 startAngle:startAngle endAngle:endAngle clockwise:YES].CGPath;
    // 設置 fillColor 為 [UIColor clearColor]景醇,讓`alpha`為0
    arc.fillColor = [UIColor clearColor].CGColor;
    // 設置線條顏色為黑色臀稚,`alpha`為1,這個線條是我們需要顯示的區(qū)域
    arc.strokeColor = [UIColor blackColor].CGColor;
    arc.lineWidth = 15;
    // 圓弧的邊緣設為有弧度
    arc.lineCap = kCALineCapRound;
       
    CAGradientLayer* grad = [[CAGradientLayer alloc] init];
    grad.frame = rect;
    grad.colors = @[(id)[UIColor colorWithRed:246.0/255.0 green:71.0/255.0 blue:71.0/255.0 alpha:1.0].CGColor,
                    (id)[UIColor colorWithRed:253.0/255.0 green:188.0/255.0 blue:51.0/255.0 alpha:1.0].CGColor,
                    (id)[UIColor colorWithRed:32.0/255.0 green:197.0/255.0 blue:102.0/255.0 alpha:1.0].CGColor];
    grad.startPoint = CGPointMake(0, 1);
    grad.endPoint = CGPointMake(1, 0);
    grad.mask = arc;
    
    [self.layer addSublayer:grad];

效果如圖


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末三痰,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子窜管,更是在濱河造成了極大的恐慌散劫,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幕帆,死亡現場離奇詭異获搏,居然都是意外死亡,警方通過查閱死者的電腦和手機失乾,發(fā)現死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門常熙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碱茁,你說我怎么就攤上這事裸卫。” “怎么了纽竣?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵墓贿,是天一觀的道長。 經常有香客問我蜓氨,道長聋袋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任穴吹,我火速辦了婚禮幽勒,結果婚禮上,老公的妹妹穿的比我還像新娘港令。我一直安慰自己啥容,他們只是感情好棘钞,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著干毅,像睡著了一般宜猜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上硝逢,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天姨拥,我揣著相機與錄音,去河邊找鬼渠鸽。 笑死叫乌,一個胖子當著我的面吹牛,可吹牛的內容都是我干的徽缚。 我是一名探鬼主播憨奸,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼凿试!你這毒婦竟也來了排宰?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤那婉,失蹤者是張志新(化名)和其女友劉穎板甘,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體详炬,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡盐类,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了呛谜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片在跳。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖隐岛,靈堂內的尸體忽然破棺而出猫妙,到底是詐尸還是另有隱情,我是刑警寧澤礼仗,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布吐咳,位于F島的核電站,受9級特大地震影響元践,放射性物質發(fā)生泄漏韭脊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一单旁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦蔫饰、人聲如沸琅豆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杖剪。三九已至冻押,卻和暖如春盛嘿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背次兆。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芥炭,地道東北人漓库。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓蚤认,卻偏偏與公主長得像,于是被迫代替她去往敵國和親砰琢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容

  • 在iOS中隨處都可以看到絢麗的動畫效果陪汽,實現這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌挚冤。在這里你可以看...
    F麥子閱讀 5,113評論 5 13
  • 轉載:http://www.reibang.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,210評論 0 13
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜赞庶,今天將帶大家一窺ios動畫全貌训挡。在這里你可以看...
    每天刷兩次牙閱讀 8,495評論 6 30
  • 每個UIView有一個伙伴稱為layer,一個CALayer歧强。UIView實際上并沒有把自己畫到屏幕上;它繪制本身...
    shenzhenboy閱讀 3,110評論 0 17
  • -1-時間 “我哪有時間可以看書摊册?”肤京,相信這是大多數人不愿意閱讀的一個借口。 工作太忙茅特,學習太忙忘分,根本就沒有時間可...
    KaTing閱讀 674評論 1 1