一失球、CAShapeLayer
- CAShapeLayer 繼承與CALayer( 主要用于設(shè)置圖層的形狀)
屬性名 | 描述 |
---|---|
path | CGPathRef 對(duì)象,圖形邊線(xiàn)路徑 |
lineWidth | 邊線(xiàn)的寬度 |
strokeColor | 邊線(xiàn)的顏色 |
lineDashPattern | 設(shè)置邊線(xiàn)的樣式帮毁,默認(rèn)為實(shí)線(xiàn)实苞,該數(shù)組為一個(gè)NSNumber數(shù)組,數(shù)組中的數(shù)值依次表示虛線(xiàn)中烈疚,單個(gè)線(xiàn)的長(zhǎng)度黔牵,和空白的長(zhǎng)度,如:數(shù)組@[2,2,3,4] 表示 有長(zhǎng)度為2的線(xiàn)爷肝,長(zhǎng)度為2的空白猾浦,長(zhǎng)度為3的線(xiàn),長(zhǎng)度為4的空白 不斷循環(huán)后組成的虛線(xiàn)灯抛。 |
lineCap | 線(xiàn)終點(diǎn)的樣式: |
lineJoin | 線(xiàn)拐點(diǎn)處的樣式: |
strokeStart strokeEnd | CGFloat類(lèi)型金赦,[0,1] 表示畫(huà)邊線(xiàn)的起點(diǎn)和終點(diǎn)(即在路徑上的百分比) |
fillColor | CGColorRef對(duì)象,圖形填充色牧愁,默認(rèn)為黑色 |
二素邪、UIBezierPath 和 貝塞爾曲線(xiàn)
2.1什么是貝塞爾曲線(xiàn)?
法國(guó)數(shù)學(xué)家 Paul de Casteljau 在1959年提供的一種 算法猪半。根據(jù)這個(gè)算法兔朦,就可以只通過(guò)很少的控制點(diǎn),去生成復(fù)雜的平滑曲線(xiàn)磨确,也就是貝塞爾曲線(xiàn)沽甥。
2.2貝塞爾曲線(xiàn)是怎么畫(huà)出來(lái)的?
首先乏奥,我們?cè)谄矫鎯?nèi)選3個(gè)不同線(xiàn)的點(diǎn)并且依次用線(xiàn)段連接摆舟。如下所示..
接著,我們?cè)贏B和BC線(xiàn)段上找出點(diǎn)D和點(diǎn)E邓了,使得AD/AB = BE/BC恨诱。
再接著,連接DE骗炉,并在DE上找出一點(diǎn)F照宝,使得DF/DE = AD/AB = BE/BC。
然后句葵,根據(jù)我們高中所學(xué)的極限的知識(shí)厕鹃,讓選取的點(diǎn)D在第一條線(xiàn)段上從起點(diǎn)A兢仰,移動(dòng)到終點(diǎn)B,找出所有點(diǎn)F剂碴,并將它們連起來(lái)把将。最后你會(huì)發(fā)現(xiàn),你得到了一條非常光滑的曲線(xiàn)忆矛,這條就是傳說(shuō)中的察蹲,貝塞爾曲線(xiàn)。
下面是三階四階和五階洪碳。
最后提下一递览,這個(gè)是一階
2.3怎么使用貝塞爾曲線(xiàn)?
首先瞳腌,要明確的一點(diǎn)是绞铃,對(duì)于貝塞爾曲線(xiàn)來(lái)說(shuō),最重要的點(diǎn)是嫂侍,數(shù)據(jù)點(diǎn)和控制點(diǎn)儿捧。
- 數(shù)據(jù)點(diǎn): 指一條路徑的起始點(diǎn)和終止點(diǎn)。
- 控制點(diǎn):控制點(diǎn)決定了一條路徑的彎曲軌跡挑宠,根據(jù)控制點(diǎn)的個(gè)數(shù)菲盾,貝塞爾曲線(xiàn)被分為一階貝塞爾曲線(xiàn)(0個(gè)控制點(diǎn))、二階貝塞爾曲線(xiàn)(1個(gè)控制點(diǎn))各淀、三階貝塞爾曲線(xiàn)(2個(gè)控制點(diǎn))等等懒鉴。
系統(tǒng)給我們提供了一個(gè)叫做UIBezierPath類(lèi),用它可以畫(huà)簡(jiǎn)單的圓形碎浇,橢圓临谱,矩形,圓角矩形奴璃,也可以通過(guò)添加點(diǎn)去生成任意的圖形悉默,還可以簡(jiǎn)單的創(chuàng)建一條二階貝塞爾曲線(xiàn)和三階貝塞爾曲線(xiàn)。
用法一:UIBezierPath+CAShapeLayer畫(huà)線(xiàn)苟穆,畫(huà)圖
CAShapeLayer的path屬性可以由UIBezierPath來(lái)提供抄课,從而可以畫(huà)線(xiàn)畫(huà)圖。
CAShapeLayer *animLayer = [CAShapeLayer layer];
//UIBezierPath提供路徑!!!!!!
animLayer.path = _path.CGPath;
//路徑寬度
animLayer.lineWidth = 5.f;
//路徑顏色
animLayer.strokeColor = [UIColor redColor].CGColor;
//圖形填充顏色
animLayer.fillColor = [UIColor orangeColor].CGColor;
//起點(diǎn)
animLayer.strokeStart = 0;
//終點(diǎn)
animLayer.strokeEnd = 1.;
//設(shè)置虛線(xiàn)
animLayer.lineDashPattern = @[@20,@20];
//線(xiàn)拐點(diǎn)處的樣式:
animLayer.lineJoin = kCALineJoinRound;
//線(xiàn)終點(diǎn)的樣式
animLayer.lineCap = kCALineCapRound;
[self.view.layer addSublayer:animLayer];
//添加路徑動(dòng)畫(huà)
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.fromValue = @(0);
animation.toValue = @(1.f);
animation.duration = 2.0f;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[animLayer addAnimation:animation forKey:@"strokeEnd"];
折線(xiàn)
// 線(xiàn)的路徑
_path = [UIBezierPath bezierPath];
// 起點(diǎn)
[_path moveToPoint:CGPointMake(20, 20)];
// 其他點(diǎn)
[_path addLineToPoint:CGPointMake(160, 160)];
[_path addLineToPoint:CGPointMake(180, 50)];
多邊形
_path = [UIBezierPath bezierPath];
//這是起點(diǎn)
[_path moveToPoint:CGPointMake(100.0, 200.0)];
//添加點(diǎn)
[_path addLineToPoint:CGPointMake(200.0, 240.0)];
[_path addLineToPoint:CGPointMake(160, 340)];
[_path addLineToPoint:CGPointMake(40.0, 340)];
[_path addLineToPoint:CGPointMake(10.0, 240.0)];
[_path closePath]; //第五條線(xiàn)通過(guò)調(diào)用closePath方法得到的
矩形
_path = [UIBezierPath bezierPathWithRect:CGRectMake(100, 100, 100, 100)];
圓角矩形
_path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 200, 100) cornerRadius:25];
自定義圓角矩形
_path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 200, 100) byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(25, 25)];
圓或橢圓
_path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 200, 100)];
圓弧
// center 圓心
// radius 半徑
// startAngle 開(kāi)始角度
// endAngle 結(jié)束角度
// clockwise 順時(shí)針or逆時(shí)針
_path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:100 startAngle:0 endAngle:M_PI clockwise:YES];
折線(xiàn)和弧線(xiàn)構(gòu)成的曲線(xiàn)
// 畫(huà)弧的中心點(diǎn)
CGPoint viewCenter = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0);
_path = [UIBezierPath bezierPath];
[_path moveToPoint:viewCenter];
[_path addArcWithCenter:viewCenter radius:50 startAngle:0 endAngle:M_PI/4*3 clockwise:YES]; // 添加一條弧線(xiàn)
[_path closePath];
//一階曲線(xiàn)
_path = [UIBezierPath bezierPath];
_path.lineWidth = 5.0;//寬度
//起始點(diǎn)
[_path moveToPoint:CGPointMake(20, 200)];
//添加終點(diǎn)和控制點(diǎn)
[twoPath addQuadCurveToPoint:CGPointMake(220, 200) controlPoint:CGPointMake(120, 0)];
//二階曲線(xiàn)
_path = [UIBezierPath bezierPath];
_path.lineWidth = 5.0;
//起始點(diǎn)
[ _path moveToPoint:CGPointMake(0, 200)];
//添加兩個(gè)控制點(diǎn)
[ _path addCurveToPoint:CGPointMake(360, 200) controlPoint1:CGPointMake(135, 0) controlPoint2:CGPointMake(225, 400)];
用法二:UIBezierPath+CAKeyframeAnimation 為關(guān)鍵幀動(dòng)畫(huà)提供動(dòng)畫(huà)路徑
可以參考iOS動(dòng)畫(huà)梳理與總結(jié) (一) 核心動(dòng)畫(huà)雳旅。
用法三:用貝塞爾曲線(xiàn)做變形
可參考本節(jié)提供的demo跟磨。
用法四:用貝塞爾曲線(xiàn)做緩沖動(dòng)畫(huà)
做動(dòng)畫(huà)最主要的一點(diǎn),就是要讓動(dòng)畫(huà)達(dá)到很自然的效果攒盈。所以就需要我們給動(dòng)畫(huà)設(shè)置一條順滑的速率曲線(xiàn)抵拘。
這個(gè)時(shí)候就不得不提到 CAMediaTimingFunction
。
CAMediaTimingFunction
的主要用法可以理解為我們?cè)谝粋€(gè)二維坐標(biāo)系上建議一條或曲線(xiàn)或直線(xiàn)的函數(shù)沦童,這個(gè)函數(shù)的斜率就是動(dòng)畫(huà)的速度仑濒,斜率的改變量也就是導(dǎo)數(shù)則為加速度。理論上來(lái)說(shuō)偷遗,這個(gè)坐標(biāo)系上的任何曲線(xiàn)都可以用來(lái)當(dāng)做加速動(dòng)畫(huà)墩瞳。然而CAMediaTimingFunction 只給我們提供了一個(gè)三次貝塞爾曲線(xiàn)的函數(shù),它可以生成三次貝塞爾曲線(xiàn)所能生成的所有緩沖函數(shù)氏豌。
這里剛好可以介紹 一個(gè) 兩個(gè)好用的網(wǎng)站: http://www.roblaplaca.com/examples/bezierBuilder
這個(gè)網(wǎng)站可以做到可視化的修改兩個(gè)控制點(diǎn)喉酌,來(lái)達(dá)到生成一條三階貝塞爾曲線(xiàn),并且還會(huì)給出兩個(gè)控制點(diǎn)的具體坐標(biāo)泵喘,以及右邊還可以看到這條曲線(xiàn)產(chǎn)生的動(dòng)畫(huà)會(huì)做怎樣的速度改變泪电。也就是說(shuō),只要我們能拿到兩個(gè)控制點(diǎn)的坐標(biāo)纪铺,就可以用來(lái)控制動(dòng)畫(huà)了相速。
這個(gè)網(wǎng)站提供了豐富的曲線(xiàn)類(lèi)型可供選擇,圖表旁還有一個(gè)小動(dòng)畫(huà)預(yù)覽鲜锚,非常直觀(guān)突诬。
UIView *demoView = [[UIView alloc] initWithFrame:CGRectMake(0, 300,100 ,100 )];
demoView.backgroundColor = [UIColor redColor];
[self.view addSubview:demoView];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = @(CGPointMake(50, 300));
animation.toValue = @(CGPointMake(WIDTH-50, 300));
animation.duration = 5.0f;
animation.autoreverses = YES;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
//設(shè)置速率曲線(xiàn)
animation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.48 :0.01 :0.48 :1.01];
[demoView.layer addAnimation:animation forKey:@"position"];