一逝淹、CAShapeLayer簡(jiǎn)介
CAShapeLayer
屬于QuartzCore框架忘渔,繼承自CALayer萌抵。CAShapeLayer
是在坐標(biāo)系內(nèi)繪制貝塞爾曲線的,通過(guò)繪制貝塞爾曲線舔稀,設(shè)置shape(形狀)的path(路徑)乳丰,從而繪制各種各樣的圖形以及不規(guī)則圖形。因此内贮,使用CAShapeLayer
需要與UIBezierPath
一起使用产园。
UIBezierPath
類允許你在自定義的 View 中繪制和渲染由直線和曲線組成的路徑.。你可以在初始化的時(shí)候直接為你的UIBezierPath
指定一個(gè)幾何圖形夜郁。
通俗點(diǎn)就是UIBezierPath
用來(lái)指定繪制圖形路徑什燕,而CAShapeLayer
就是根據(jù)路徑來(lái)繪圖的。
二竞端、CAShapeLayer屬性介紹
1屎即、[CAShapeLayer layer].path
@property(nullable) CGPathRef path;
官方的解釋是定義要呈現(xiàn)的形狀的路徑。如果路徑擴(kuò)展到層邊界之外事富,只有當(dāng)正常層屏蔽規(guī)則導(dǎo)致該條線時(shí)技俐,它才會(huì)自動(dòng)被剪輯到該層。賦值時(shí)统台,路徑被復(fù)制雕擂。默認(rèn)為null。(注意饺谬,雖然路徑屬性的動(dòng)畫捂刺,不隱將動(dòng)畫時(shí)創(chuàng)建的屬性發(fā)生了變化谣拣。)
2募寨、[CAShapeLayer layer].fillColor
@property(nullable) CGColorRef fillColor;
官方解釋是填充路徑的顏色族展,或不需要填充。默認(rèn)顏色為不透明的黑色拔鹰。
3仪缸、[CAShapeLayer layer].fillRule
@property(copy) NSString *fillRule;
官方解釋是當(dāng)在填充顏色的時(shí)候則就需要這種填充規(guī)則,值有兩種列肢,非零和奇偶數(shù)恰画,但默認(rèn)是非零值。
4瓷马、[CAShapeLayer layer].strokeColor
@property(nullable) CGColorRef strokeColor;
官方解釋是設(shè)置描邊色拴还,默認(rèn)無(wú)色。
5欧聘、[CAShapeLayer layer].strokeStart與[CAShapeLayer layer].strokeEnd
@property CGFloat strokeStart;
@property CGFloat strokeEnd;
官方解釋是這兩個(gè)值被定義用于繪制邊線輪廓路徑的子區(qū)域片林。該值必須在[0,1]范圍,0代表路徑的開始怀骤,1代表路徑的結(jié)束费封。在0和1之間的值沿路徑長(zhǎng)度進(jìn)行線性插值。strokestart默認(rèn)為0蒋伦,strokeend默認(rèn)為1弓摘。
6、[CAShapeLayer layer]. lineWidth與[CAShapeLayer layer].miterLimit
@property CGFloat lineWidth;
@property CGFloat miterLimit;
官方解釋是lineWidth為線的寬度痕届,默認(rèn)為1韧献;miterLimit為最大斜接長(zhǎng)度。斜接長(zhǎng)度指的是在兩條線交匯處和外交之間的距離研叫。只有l(wèi)ineJoin屬性為kCALineJoinMiter時(shí)miterLimit才有效势决。邊角的角度越小,斜接長(zhǎng)度就會(huì)越大蓝撇。為了避免斜接長(zhǎng)度過(guò)長(zhǎng)果复,我們可以使用miterLimit屬性。如果斜接長(zhǎng)度超過(guò)miterLimit的值渤昌,邊角會(huì)以lineJoin的“bevel”即kCALineJoinBevel類型來(lái)顯示虽抄。
7、[CAShapeLayer layer]. lineCap與[CAShapeLayer layer].lineJoin
@property(copy) NSString *lineCap;
@property(copy) NSString *lineJoin;
lineCap為線端點(diǎn)類型独柑,值有三個(gè)類型迈窟,分別為kCALineCapButt 、kCALineCapRound 忌栅、kCALineCapSquare车酣,默認(rèn)值為Butt曲稼;lineJoin為線連接類型,其值也有三個(gè)類型湖员,分別為kCALineJoinMiter贫悄、kCALineJoinRound、kCALineJoinBevel娘摔,默認(rèn)值是Miter窄坦。
8、[CAShapeLayer layer]. lineDashPhase與[CAShapeLayer layer]. lineDashPattern
@property CGFloat lineDashPhase;
@property(nullable, copy) NSArray<NSNumber *> *lineDashPattern;
官方解釋是lineDashPhase為線型模版的起始位置凳寺;lineDashPattern為線性模版鸭津,這是一個(gè)NSNumber的數(shù)組,索引從1開始記肠缨,奇數(shù)位數(shù)值表示實(shí)線長(zhǎng)度逆趋,偶數(shù)位數(shù)值表示空白長(zhǎng)度。
注:fillColor與strokeColor都是在有UIBezierPath參數(shù)配置的情況下才能發(fā)生作用
三晒奕、開始繪制
1闻书、顏色說(shuō)明---矩形為例
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = CGRectMake(375/2-50, 667/2-50, 100, 100);
//設(shè)置背景色
layer.backgroundColor = [UIColor cyanColor].CGColor;
//設(shè)置描邊色
layer.strokeColor = [UIColor blackColor].CGColor;
//設(shè)置填充色
layer.fillColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:layer];
效果如圖顯示一個(gè)青色的矩形圖:
讀者估計(jì)會(huì)納悶,為啥設(shè)置的描邊色與填充色沒(méi)有作用吴汪,這是因?yàn)檫@兩種顏色需要
UIBezierPath
來(lái)繪制路徑惠窄,然后使用CAShapeLayer
進(jìn)行渲染,所以接下來(lái)就就在上面的那段代碼下簡(jiǎn)單的添加一個(gè)UIBezierPath類路徑(溫馨提示漾橙,layer的背景與這兩種顏色最好不要共用)杆融。
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
layer.path = path.CGPath;
可以發(fā)現(xiàn)填充色與描邊色有效果了。
2霜运、繪制shape
//繪制矩形
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
//繪制圓形路徑
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)];
//繪制自帶圓角的路徑
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 100, 100) cornerRadius:30];
//指定矩形某一個(gè)角加圓角(代碼示例為左上角)
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 100, 100) byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(50, 50)];
3脾歇、繪制曲線(正弦曲線為例)
先來(lái)兩張效果圖:
說(shuō)明:圖4只是比圖5多了填充色而已。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIBezierPath *path = [self startPoint:CGPointMake(50, 300) endPoint:CGPointMake(200, 300) controlPoint:CGPointMake(125, 200)];
UIBezierPath *path1 = [self startPoint:CGPointMake(200, 300) endPoint:CGPointMake(350, 300) controlPoint:CGPointMake(275, 400)];
CAShapeLayer *layer = [self createShapeLayer:[UIColor orangeColor]];
layer.path = path.CGPath;
CAShapeLayer *layer1 = [self createShapeLayer:[UIColor greenColor]];
layer1.path = path1.CGPath;
}
/**
配置貝塞爾曲線
@param startPoint 起始點(diǎn)
@param endPoint 結(jié)束點(diǎn)
@param controlPoint 控制點(diǎn)
@return UIBezierPath對(duì)象
*/
- (UIBezierPath *)startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:startPoint];
[path addQuadCurveToPoint:endPoint controlPoint:controlPoint];
return path;
}
- (CAShapeLayer *)createShapeLayer:(UIColor *)color
{
CAShapeLayer *layer = [CAShapeLayer layer];
// layer.frame = CGRectMake(0, 0, 50, 50);
//設(shè)置背景色
// layer.backgroundColor = [UIColor cyanColor].CGColor;
//設(shè)置描邊色
layer.strokeColor = [UIColor blackColor].CGColor;
//設(shè)置填充色
layer.fillColor = color.CGColor;
[self.view.layer addSublayer:layer];
return layer;
}
4淘捡、曲線動(dòng)畫
1)藕各、直線
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 667/2)];
[path addLineToPoint:CGPointMake(375/2, 667/2)];
[path addLineToPoint:CGPointMake(300, 667/2)];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
//每次動(dòng)畫的持續(xù)時(shí)間
animation.duration = 5;
//動(dòng)畫起始位置
animation.fromValue = @(0);
//動(dòng)畫結(jié)束位置
animation.toValue = @(1);
//動(dòng)畫重復(fù)次數(shù)
animation.repeatCount = 100;
CAShapeLayer *layer = [self createShapeLayerNoFrame:[UIColor orangeColor]];
layer.path = path.CGPath;
layer.lineWidth = 2.0;
//設(shè)置圖形的弧度
// layer.strokeStart = 0;
// layer.strokeEnd = 0;
[layer addAnimation:animation forKey:@"strokeEndAnimation"];
//注:由于UIBezierPath已經(jīng)設(shè)置路徑,所以動(dòng)畫的路徑就不需要再次設(shè)置焦除,只需要設(shè)置起始0與結(jié)束1就行激况,有需要可以設(shè)置動(dòng)畫結(jié)束后是否需要返回原位置。
2)膘魄、曲線
UIBezierPath *path = [UIBezierPath bezierPath];
//起始點(diǎn)
[path moveToPoint:CGPointMake(50, 667/2)];
//結(jié)束點(diǎn)乌逐、兩個(gè)控制點(diǎn)
[path addCurveToPoint:CGPointMake(330, 667/2) controlPoint1:CGPointMake(125, 200) controlPoint2:CGPointMake(185, 450)];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 5;
animation.fromValue = @(0);
animation.toValue = @(1);
animation.repeatCount = 100;
CAShapeLayer *layer = [self createShapeLayerNoFrame:[UIColor clearColor]];
layer.path = path.CGPath;
layer.lineWidth = 2.0;
[layer addAnimation:animation forKey:@"strokeEndAnimation"];
3)、圓形
筆者目前的一個(gè)項(xiàng)目中就用到了這個(gè)功能创葡。直接貼一張效果圖:
其實(shí)實(shí)現(xiàn)效果很簡(jiǎn)單浙踢,只是把邊線加粗了然后實(shí)現(xiàn)動(dòng)畫就可以了,還有一種思路就是畫兩個(gè)圓灿渴,截取中間的環(huán)洛波,對(duì)大圓進(jìn)行顏色漸變填充胰舆,小圓clear所有顏色再去實(shí)現(xiàn)動(dòng)畫也能達(dá)到這樣的效果。
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(375/2-100, 667/2-100, 200, 200)];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 3.0;
animation.fromValue = @(0);
animation.toValue = @(1);
animation.repeatCount = 100;
CAShapeLayer *layer = [self createShapeLayerNoFrame:[UIColor clearColor]];
layer.path = path.CGPath;
layer.lineWidth = 25.0;
//圓的起始位置蹬挤,默認(rèn)為0
layer.strokeStart = 0;
//圓的結(jié)束位置缚窿,默認(rèn)為1,如果值為0.75闻伶,則顯示3/4的圓
layer.strokeEnd = 1;
[layer addAnimation:animation forKey:@"strokeEndAnimation"];
四滨攻、小結(jié)
iOS中畫圖類還有CoreGraphics
够话,但筆者比較喜歡使用CAShapeLayer
蓝翰,且CAShapeLayer
一般是與UIBezierPath
連用的,如果有動(dòng)畫功能的話女嘲,還可以加上CABasicAnimation
畜份。這篇文章只是對(duì)CAShapeLayer
和UIBezierPath
類如何使用和主要功能實(shí)現(xiàn)做了簡(jiǎn)要的說(shuō)明,還有一些項(xiàng)目中可能經(jīng)常用到的圓形進(jìn)度圈欣尼、下載圈爆雹,或者某些特效的實(shí)現(xiàn),筆者可能在下一篇文章中簡(jiǎn)析封裝步驟與代碼實(shí)現(xiàn)愕鼓,有需要的讀者多多關(guān)注钙态。
五、筆者V587
筆者已入坑菇晃,文章有不妥之處請(qǐng)大家指出册倒,謝謝各位。勞動(dòng)不易磺送,轉(zhuǎn)載須注明出處驻子。