要實現上面這個三彩圓弧環(huán)姜凄,可以用三個步驟實現:
- 使用
UIBezierPath
畫出圓弧上的每個小矩形 - 新建一個形狀圖層
CAShaperLayer
吸祟,其路徑設置為上個步驟的路徑 - 新建一個漸變圖層
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];
效果如圖