Mask动画深入学习
CALayer有一个属性叫做mask(对应UIView中maskView属性,下文说的maskView和mask是一个东西),mask图层定义了父图层的部分可见区域,功能类似于PS 中的图层蒙版。
mask图层的Color属性是无关紧要的,真正重要的是图层的轮廓。mask属性就像是一个饼干切割机,mask图层实心的部分会被保留下来,其他的则会被抛弃。(如图1.1)。
也可以这样理解,maskView将每个point的alpha赋值给View的重叠部分相对应的point,这样view的重叠每个point都有个alpha值了,view重叠部分就可能显示多种透明色。
就如图1.1 而言,由于maskView颜色的alpha为1.0,那么与view重叠部分的alpha也应该为1.0(即重叠部分没变化),与mask颜色没关系。
图1.1还是云里雾里的也没关系。您可以下载demo对照学习,注释非常详细,一看就懂。
demo中前三个例子可有帮助更深刻的体会mask属性的基本原理。
CALayer蒙板图层真正厉害的地方在于蒙板图不局限于静态图。任何有图层构成的都可以作为mask属性,这意味着你的蒙板可以通过代码甚至是动画实时生成。
-
利用maskView实现图片渐变切换动画
如图1.2 的图片切换效果,其实是使用了的alpha通道变化的maskView完成图片的切换。
图1.2
// 在底层的 图片 background(最后要显示出来)
UIImageView *background = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
background.image = [UIImage imageNamed:@"base"];
background.center = self.view.center;
[self.view addSubview:background];
// 在上层的 图片 upGround
UIImageView *upGround = [[UIImageView alloc] initWithFrame:background.frame];
upGround.image = [UIImage imageNamed:@"background"];
[self.view addSubview:upGround];
// maskView 由两个分别加载 “mask1” “mask” 的imageView拼接而成。加在 上层图片上 , 注意 两张透明度渐变的图片是重点。是它们使 上层图片upGround 显示 或者隐藏
UIView *mask = [[UIView alloc] initWithFrame:upGround.bounds];
upGround.maskView = mask;
UIImageView *picOne = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 400)];
picOne.image = [UIImage imageNamed:@"mask1"];
[mask addSubview:picOne];
UIImageView *picTwo = [[UIImageView alloc] initWithFrame:CGRectMake(100, -200, 100, 400)];
picTwo.image = [UIImage imageNamed:@"mask"];
[mask addSubview:picTwo];
// 两个imageView的动画 使maskView的alpha通道由 1 变成 0 ,导致 上层图片消失, 达到切换的效果
[UIView animateWithDuration:2.f delay:2.f options:0 animations:^{
picOne.y -= 400;
picTwo.y += 400;
} completion:^(BOOL finished) {
}];
-
maskView配合CAGradientLayer使用
这个例子实现了 iPhone的滑动解锁效果
1.首先构建一个 颜色渐变的layer,可以使用CAGradientLayer这个类,你也可以像上一个例子一样使用图片,看起来像图1.3.1就行。
关于CAGradientLayer的属性详细解析可参考CAGradientLayer的一些属性解析
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[self.view.layer addSublayer:gradientLayer];
gradientLayer.frame = CGRectMake(0, 200, self.view.width, 64);
gradientLayer.colors = @[
(__bridge id)[UIColor blackColor].CGColor,
(__bridge id)[UIColor whiteColor].CGColor,
(__bridge id)[UIColor blackColor].CGColor,
];
gradientLayer.locations = @[@0.25,@0.5,@0.75];
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
图1.3.1
2.让这个图层动起来,加个动画。
// CAGradientLayer可用来处理颜色渐变,它的渐变色也可以做隐式动画
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"locations"];
basicAnimation.fromValue = @[@0, @0, @0.25];
basicAnimation.toValue = @[@0.75, @1, @1];
basicAnimation.duration = 2.5;
basicAnimation.repeatCount = HUGE;
[gradientLayer addAnimation:basicAnimation forKey:nil];
图1.3.2
3.让UILabel上的文字成为CAGradientLayer的遮罩,完成。
// 设置 gradientLayer 的 mask 为 unLock 有透明度的地方 就露出来了
UILabel *unlock = [[UILabel alloc] initWithFrame:gradientLayer.bounds];
self.unlock = unlock;
unlock.alpha = 0.5;
unlock.text = @"滑动来解锁 >>";
unlock.textAlignment = NSTextAlignmentCenter;
unlock.font = [UIFont boldSystemFontOfSize:30];
gradientLayer.mask = unlock.layer;
图1.3.3
-
maskView配合CAShapeLayer使用
直接上代码,在图片层上 加一层毛玻璃层,在毛玻璃层上加一层圆形的mask。
图1.4.1 // 最底层的view 显示图片
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
imageView.image = [UIImage imageNamed:@"Slice"];
[self.view addSubview:imageView];
// 创建mask
// 贝塞尔曲线(创建一个圆)
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0)
radius:100
startAngle:DEGREES(0)
endAngle:DEGREES(360)
clockwise:YES];
_maskLayer = [CAShapeLayer layer];
_maskLayer.path = path.CGPath;
_maskLayer.position = CGPointMake(_showView.bounds.size.width/2.f,
_showView.bounds.size.height/2.f);
_maskLayer.fillColor = [UIColor whiteColor].CGColor;
_maskLayer.position = self.view.center;
// 创建覆盖在最底层imageView上的模糊图片, 添加mask 注意mask为一个圆形(模糊图片只会显示一个圆,其他地方会变成透明)
UIView *blurView = [[UIView alloc] initWithFrame:self.view.bounds];
blurView.backgroundColor = [UIColor blackColor];
[self.view addSubview:blurView];
blurView.layer.mask = _maskLayer;
blurView.layer.contents = (__bridge id)([[UIImage imageNamed:@"Slice"] imgWithBlur].CGImage);
/*
透明的View,用于maskView中的ShapeLayer的参考View(用于拖拽)
*/
_showView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
_showView.backgroundColor = [UIColor clearColor];
_showView.center = self.view.center;
[self.view addSubview:_showView];
UIPanGestureRecognizer *recognizer =
[[UIPanGestureRecognizer alloc] initWithTarget:self
action:@selector(handlePan:)];
[_showView addGestureRecognizer:recognizer];
}
- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
// 拖拽
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
// 关闭CoreAnimation实时动画绘制(核心)
[CATransaction setDisableActions:YES];
_maskLayer.position = recognizer.view.center;
}
-
毛玻璃渐变效果
如图1.5.1 效果 ,如果你理解了mask的原理,这个和上一个类似,
在图片层上 加一层毛玻璃层,在毛玻璃层上加一层透明度渐变的mask,OK。
图1.5.1
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
imageView.image = [UIImage imageNamed:@"Slice"];
[self.view addSubview:imageView];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[self.view.layer addSublayer:gradientLayer];
gradientLayer.frame = self.view.bounds;
// 颜色的透明度 alpha 0.0 全透过 1.0 不透明
gradientLayer.colors = @[
(__bridge id)[UIColor colorWithWhite:1 alpha:0.0].CGColor,
(__bridge id)[UIColor colorWithWhite:1 alpha:1.0].CGColor,
];
gradientLayer.locations = @[@0.35,@0.55];
_gradientLayer = gradientLayer;
UIView *blurView = [[UIView alloc] initWithFrame:self.view.bounds];
blurView.backgroundColor = [UIColor blackColor];
[self.view addSubview:blurView];
blurView.layer.mask = gradientLayer;
blurView.layer.contents = (__bridge id)([[UIImage imageNamed:@"Slice"] imgWithBlur].CGImage);
以上例子的代码可以在这下载
另外推荐一个mask实现的动画效果,mask的实现方式非常巧妙。
https://github.com/andreamazz/BubbleTransition