// // GredientLayerView.m // GredientLayerView // // Created by City--Online on 15/10/26. // Copyright © 2015年 City--Online. All rights reserved. // #import "GredientLayerView.h" #define degreesToRadians(x) (M_PI*(x)/180.0) //把角度轉換成PI的方式 static const float kPROGRESS_LINE_WIDTH=4.0; @interface GredientLayerView () @property (nonatomic,strong) CAShapeLayer *progressLayer; @end @implementation GredientLayerView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //設置貝塞爾曲線 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:(frame.size.width-kPROGRESS_LINE_WIDTH)/2 startAngle:degreesToRadians(-210) endAngle:degreesToRadians(30) clockwise:YES]; //遮罩層 _progressLayer = [CAShapeLayer layer]; _progressLayer.frame = self.bounds; _progressLayer.fillColor = [[UIColor clearColor] CGColor]; _progressLayer.strokeColor=[UIColor redColor].CGColor; _progressLayer.lineCap = kCALineCapRound; _progressLayer.lineWidth = kPROGRESS_LINE_WIDTH; //漸變圖層 CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = _progressLayer.frame; [gradientLayer setColors:[NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor],(id)[[UIColor yellowColor] CGColor],(id)[[UIColor blueColor] CGColor], nil]]; [gradientLayer setLocations:@[@0,@0.6,@1]]; [gradientLayer setStartPoint:CGPointMake(0, 0)]; [gradientLayer setEndPoint:CGPointMake(1, 0)]; //用progressLayer來截取漸變層 遮罩 [gradientLayer setMask:_progressLayer]; [self.layer addSublayer:gradientLayer]; //增加動畫 CABasicAnimation *pathAnimation=[CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = 2; pathAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; pathAnimation.fromValue=[NSNumber numberWithFloat:0.0f]; pathAnimation.toValue=[NSNumber numberWithFloat:1.0f]; pathAnimation.autoreverses=NO; _progressLayer.path=path.CGPath; [_progressLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; } return self; } @end
二 .使用CAGradientLayer+UIBezierPath實現圓形漸變 1.自定義GredientLayerView #import <UIKit/UIKit.h> @interface GredientLayerView : UIView @end
// // GredientLayerView.m // GredientLayerView // // Created by City--Online on 15/10/26. // Copyright © 2015年 City--Online. All rights reserved. // #import "GredientLayerView.h" #define degreesToRadians(x) (M_PI*(x)/180.0) //把角度轉換成PI的方式 static const float kPROGRESS_LINE_WIDTH=4.0; @interface GredientLayerView () @property (nonatomic,strong) CAShapeLayer *progressLayer; @end @implementation GredientLayerView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //設置貝塞爾曲線 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:(frame.size.width-kPROGRESS_LINE_WIDTH)/2 startAngle:degreesToRadians(-210) endAngle:degreesToRadians(30) clockwise:YES]; //遮罩層 _progressLayer = [CAShapeLayer layer]; _progressLayer.frame = self.bounds; _progressLayer.fillColor = [[UIColor clearColor] CGColor]; _progressLayer.strokeColor=[UIColor redColor].CGColor; _progressLayer.lineCap = kCALineCapRound; _progressLayer.lineWidth = kPROGRESS_LINE_WIDTH; //漸變圖層 CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = _progressLayer.frame; [gradientLayer setColors:[NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor],(id)[[UIColor yellowColor] CGColor],(id)[[UIColor blueColor] CGColor], nil]]; [gradientLayer setLocations:@[@0,@0.6,@1]]; [gradientLayer setStartPoint:CGPointMake(0, 0)]; [gradientLayer setEndPoint:CGPointMake(1, 0)]; //用progressLayer來截取漸變層 遮罩 [gradientLayer setMask:_progressLayer]; [self.layer addSublayer:gradientLayer]; //增加動畫 CABasicAnimation *pathAnimation=[CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = 2; pathAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; pathAnimation.fromValue=[NSNumber numberWithFloat:0.0f]; pathAnimation.toValue=[NSNumber numberWithFloat:1.0f]; pathAnimation.autoreverses=NO; _progressLayer.path=path.CGPath; [_progressLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; } return self; } @end
2.調用
// // ViewController.m // Gredientlayer // // Created by City--Online on 15/10/26. // Copyright © 2015年 City--Online. All rights reserved. // #import "ViewController.h" #import "GredientLayerView.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; GredientLayerView *gredientLayerView=[[GredientLayerView alloc]initWithFrame:CGRectMake(30, 100, 200, 200)]; [self.view addSubview:gredientLayerView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
3.效果 遮罩層必須至少有兩個圖層,上面的一個圖層為“遮罩層”,下面的稱“被遮罩層”;這兩個圖層中只有相重疊的地方才會被顯示。也就是說在遮罩層中有對象的地方就是“透明”的,可以看到被遮罩層中的對象,而沒有對象的地方就是不透明的,被遮罩層中相應位置的對象是看不見的。 它的原理是:上面一層是遮罩層,下面一層是被遮罩層。遮罩層上的圖,自己是不顯示的。它只起到一個透光的作用。假定遮罩層上是一個正圓,那麼光線就會透過這個圓形,射到下面的被遮罩層上,只會顯示一個圓形的圖形。如果遮罩層上什麼都沒有,那麼光線就無法透到下面來,那麼下面的被遮罩層什麼也顯示不出來。 之前一直疑惑當設置遮罩後,遮罩層並不顯示自身的樣式,例如我設置了遮罩層的strokeColor為紅色時,顯示的是被遮罩層,當設置為透明時被遮罩層也不顯示了,具體透明是什麼樣的一個原理,暫且還沒弄明白,這裡根據上面的遮罩層的原理就認為設置透明則就是上面的什麼都沒有