最近发现CALayer能实现的东西有很多,而且都很有意思,效果不错。今天写了一个遮罩的和一个图片渐变的功能。
先看效果。
跟舞台的聚光灯一样 随着时间移来移去的,遮罩住其他的地方。
直接上代码了。
```
@interface MaskViewController ()
@property (nonatomic, strong) CALayer *imageLayer;
@property (nonatomic, strong) CALayer *maskLayer;
@property (nonatomic, strong) UIImage *imageContents;
@property (nonatomic, strong) UIImage *maskContents;
@end
@implementation MaskViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
self.imageContents = [UIImage imageNamed:@"开始图片.jpg"];
self.maskContents = [UIImage imageNamed:@"maskLayerContents"];
//图片layer
self.imageLayer = [CALayer layer];
self.imageLayer.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
self.imageLayer.contents = (__bridge id _Nullable)(self.imageContents.CGImage);
[self.view.layer addSublayer:self.imageLayer];
//遮罩layer
self.maskLayer = [CALayer layer];
self.maskLayer.frame = CGRectMake(0, 64, 200, 200);
self.maskLayer.contents = (__bridge id _Nullable)(self.maskContents.CGImage);
// 这个不用图片也可以 用背景颜色 例如下面这段 但是效果没图片那样好看
// self.maskLayer.backgroundColor = [UIColor blackColor].CGColor;
// self.maskLayer.cornerRadius = 100;
// self.maskLayer.masksToBounds = YES;
// An optional layer whose alpha channel is used to mask the layer’s content.
// 根据alpha通道 来选择遮罩的地方 黑色全通过,白色全不通过
self.imageLayer.mask = self.maskLayer;
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(maskLayerAnimation:) userInfo:nil repeats:YES];
}
- (void)maskLayerAnimation:(NSTimer *)timer{
//要显示的区域可以自己在设定一下
CGFloat x = arc4random() % (375-200);
CGFloat y = arc4random() % (667-200-64);
self.maskLayer.frame = CGRectMake(x, y, 200, 200);
}
```
注释都有 另外还有一个图片的出现消失的组合动画,代码如下
#define ISSHOW YES
@interface ChangeViewController ()
@property (nonatomic, strong) CALayer *imageLayer;
@end
@implementation ChangeViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIImage *image1 = [UIImage imageNamed:@"开始图片.jpg"];
// self.view.layer.contents = (__bridge id _Nullable)(image.CGImage);
// 只要有前面这两句就可以显示图片了,可以得出layer是图片的载体 UIimageView可能是充分的利用了这个属性
//创建出图片的layer
self.imageLayer = [CALayer layer];
self.imageLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view.layer addSublayer:self.imageLayer];
// 将图片加载到layer的contents
self.imageLayer.contents = (__bridge id _Nullable)(image1.CGImage);
[self performSelector:@selector(layerAnimation) withObject:nil afterDelay:3.0];
}
- (void)layerAnimation{
UIImage *image2 = [UIImage imageNamed:@"结束图片.jpg"];
//隐式动画 比没有流畅仔细看
if (!ISSHOW) {
self.imageLayer.contents = (__bridge id _Nullable)(image2.CGImage);
}
else{
// keyPath就是imageLayer的contents属性 这个是图片动画
CABasicAnimation *contentsAnimation = [CABasicAnimation animationWithKeyPath:@"contents"];
// 起始图片
contentsAnimation.fromValue = self.imageLayer.contents;
// 结束图片
contentsAnimation.toValue = (__bridge id _Nullable)(image2.CGImage);
// 持续时间
contentsAnimation.duration = 2.0f;
// bounds动画
CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"];
// 因为bounds是CGRect类型 不是对象 所以要转一下
boundsAnimation.fromValue = [NSValue valueWithCGRect:self.imageLayer.bounds];
boundsAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(self.view.frame.size.width / 4, self.view.frame.size.width / 4, self.view.frame.size.width / 2, self.view.frame.size.height / 2)];
boundsAnimation.duration = 2.0f;
//将动画组合起来
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = @[contentsAnimation,boundsAnimation];
groupAnimation.duration = 2.0f;
// 执行完之后又会回到原来的状态,因为layer只是提交了动画,并没有修改layer的内容 只是一段过程 所以结束了之后要设定layer的内容
self.imageLayer.contents = (__bridge id _Nullable)(image2.CGImage);
self.imageLayer.bounds = CGRectMake(self.view.frame.size.width / 4, self.view.frame.size.width / 4, self.view.frame.size.width / 2, self.view.frame.size.height / 2);
[self.imageLayer addAnimation:groupAnimation forKey:nil];
}
}
@end
进度条代码如下:
@interface ProgressViewController ()
@property (nonatomic, strong) ProgressView *progressView;
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation ProgressViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.progressView = [[ProgressView alloc] initWithFrame:CGRectMake(20, 300, 300, 3)];
//设置进度条颜色
self.progressView.layerColor = [UIColor blueColor];
//设置边框大小
self.progressView.layer.borderWidth = 1.0;
//设置边框颜色
// self.progressView.layer.borderColor = [UIColor redColor].CGColor;
[self.view addSubview:self.progressView];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(layerAnimation) userInfo:nil repeats:YES];
}
- (void)layerAnimation{
//模拟下载进度
self.progressView.progress = arc4random() %100 / 100.f;
}
@end
.h
@interface ProgressView : UIView
@property (nonatomic, assign) CGFloat progress;//进度参数
@property (nonatomic, strong) UIColor *layerColor;//颜色
@end
.m
@interface ProgressView()
@property (nonatomic, strong) CALayer *progressLayer;
//这个记录当前这个进度条的宽度
@property (nonatomic, assign) CGFloat currentWidth;
@end
@implementation ProgressView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 如果是用View自带的layer设置则不会有隐式动画
// 创建出一个独立的layer则有
self.progressLayer = [CALayer layer];
self.progressLayer.frame = CGRectMake(0, 0, 0, frame.size.height);
self.progressLayer.backgroundColor = [UIColor redColor].CGColor;
[self.layer addSublayer:self.progressLayer];
self.currentWidth = frame.size.width;
}
return self;
}
#pragma mark ----set get
@synthesize progress = _progress;
- (void)setProgress:(CGFloat)progress{
_progress = progress;
if (progress <= 0) {
self.progressLayer.frame = CGRectMake(0, 0, 0, self.frame.size.height);
}else if (progress <= 1){
// 进度 * 总宽度 得到对应的宽度
self.progressLayer.frame = CGRectMake(0, 0, self.currentWidth * progress, self.frame.size.height);
}else{
self.progressLayer.frame = CGRectMake(0, 0, self.currentWidth, self.frame.size.height);
}
}
- (CGFloat)progress{
return _progress;
}
@synthesize layerColor = _layerColor;
- (void)setLayerColor:(UIColor *)layerColor{
_layerColor = layerColor;
self.progressLayer.backgroundColor = layerColor.CGColor;
}
- (UIColor *)layerColor{
return _layerColor;
}
@end
注意 遮罩图片最好是有透明通道的,没有的话也可以用背景颜色来设置。
源代码 和图片放在提示信息 - Code4App-iOS开发-iOS 开源代码库-iOS代码实例搜索-iOS特效示例-iOS代码例子下载-Code4App.com - Powered by Discuz!
代码参考了YouXianMing - 博客园大神写的
希望可以帮助到有需要的人,感谢开源。