利用layer的mask属性实现逐渐揭示的动画效果,layermask
来源:互联网 发布:高频彩票算法大揭秘 编辑:程序博客网 时间:2024/06/06 10:53
github上又看到个不错的动画(https://github.com/rounak/RJImageLoader),如图: 所以就想来自己实现以下 不试不知道,这个动画还真不是看上去那么简单,我自己想了半天愣是没做出来,最后还是看了作者的代码,才知道怎么实现。 不过也从作者哪儿学了一招,就是layer.mask的用法。 自己实现的效果如图: demo在这里:https://github.com/Phelthas/LXMRevealDemo (前面的画圆的动画,这是一个CAShaperLayer修改其strokeEnd的动画,比较简单,就没有再写了) 这个动画说难也不难,其关键就在于对layer.mask的特性的运用,如果你不知道layer.mask的特性,那实现起来就相当困难了;相反,如果知道,那思路就豁然开朗了。 关键就是这个: /* A layer whose alpha channel is used as a mask to select between the * layer's background and the result of compositing the layer's
* contents with its filtered background. Defaults to nil. When used as
* a mask the layer's `compositingFilter' and `backgroundFilters'
* properties are ignored. When setting the mask to a new layer, the
* new layer must have a nil superlayer, otherwise the behavior is
* undefined. Nested masks (mask layers with their own masks) are * unsupported. */@property(strong) CALayer *mask; mask属性,可以实现很多形状的遮罩,其基本效果是: 比如layerA是layerB的mask,即layerB.mask = layerA; 那么layerA上透明的部分,会被绘制成白色挡住layerB(貌似都是白色,不知道能不能弄成其他颜色); layerA上不透明的部分,会被绘制成透明,显示出layerB的内容。 注意:作为mask的layer不能有superLayer或者subLayer! 知道了这个,动画的思路就有了: imageView上有个遮罩,遮罩透明的部分逐渐变大,向外向内同时扩展,使遮罩后面的图片爆料出来。 这里首先需要一个圆形的CAShapeLayer,还需要两个动画,使这个layer同时向内向外扩展。 那么问题来了,只有一个layer,还不能有subLayer,怎么让它同时又变大又变小呢? 答案是:换个方式。 注意CAShapeLayer是线画出来,线也有颜色,还有宽度是 lineWidth,而且这些属性也是可以动画的。 所以最终的方案是:设置圆的线的颜色为透明,圆的填充色为不透明,园外的颜色不透明(这里的设置指的是看到的效果),让圆逐渐变大到可以显示出整个view,同时让圆的lineWidth逐渐变宽到圆的半径那么大。 看到的效果就是图片像上面的效果一样逐渐显露出来了。 核心动画代码如下: - (void)reveal {
self.backgroundColor = [UIColor clearColor];
[self.circleLayer removeFromSuperlayer];//理论上作为mask的layer不能有父layer,所以要remove掉
self.superview.layer.mask = self.circleLayer;
//让圆的变大的动画
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
UIBezierPath *toPath = [self pathWithDiameter:self.bigDiameter];
// UIBezierPath *toPath = [self pathWithDiameter:0];//缩小当前path的动画
pathAnimation.toValue = (id)toPath.CGPath;
pathAnimation.duration = 1.0;
//让圆的线的宽度变大的动画,效果是内圆变小
CABasicAnimation *lineWidthAnimation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(lineWidth))];
lineWidthAnimation.toValue = @(self.bigDiameter);
lineWidthAnimation.duration = 1.0;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[pathAnimation, lineWidthAnimation];
group.duration = 1.0;
group.removedOnCompletion = NO;//这两句的效果是让动画结束后不会回到原处,必须加
group.fillMode = kCAFillModeForwards;//这两句的效果是让动画结束后不会回到原处,必须加
group.delegate = self;
[self.circleLayer addAnimation:group forKey:@"revealAnimation"]; } /**
* 根据直径生成圆的path,注意圆点是self的中心点,所以(x,y)不是(0,0)
*/
- (UIBezierPath *)pathWithDiameter:(CGFloat)diameter {
return [UIBezierPath bezierPathWithOvalInRect:CGRectMake((CGRectGetWidth(self.bounds) - diameter) / 2, (CGRectGetHeight(self.bounds) - diameter) / 2, diameter, diameter)];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
self.superview.layer.mask = nil;
[self removeFromSuperview];
}
#pragma mark - property
- (CAShapeLayer *)circleLayer {
if (!_circleLayer) {
_circleLayer = [CAShapeLayer layer];
_circleLayer.fillColor = [UIColor clearColor].CGColor;//这个必须透明,因为这样内圆才是不透明的
_circleLayer.strokeColor = [UIColor yellowColor].CGColor;//注意这个必须不能透明,因为实际上是这个显示出后面的图片了
_circleLayer.path = [self pathWithDiameter:self.smallDiameter].CGPath;
}
return _circleLayer; } 完整代码见github:https://github.com/Phelthas/LXMRevealDemo 有什么错误欢迎批评指正
* contents with its filtered background. Defaults to nil. When used as
* a mask the layer's `compositingFilter' and `backgroundFilters'
* properties are ignored. When setting the mask to a new layer, the
* new layer must have a nil superlayer, otherwise the behavior is
* undefined. Nested masks (mask layers with their own masks) are * unsupported. */@property(strong) CALayer *mask; mask属性,可以实现很多形状的遮罩,其基本效果是: 比如layerA是layerB的mask,即layerB.mask = layerA; 那么layerA上透明的部分,会被绘制成白色挡住layerB(貌似都是白色,不知道能不能弄成其他颜色); layerA上不透明的部分,会被绘制成透明,显示出layerB的内容。 注意:作为mask的layer不能有superLayer或者subLayer! 知道了这个,动画的思路就有了: imageView上有个遮罩,遮罩透明的部分逐渐变大,向外向内同时扩展,使遮罩后面的图片爆料出来。 这里首先需要一个圆形的CAShapeLayer,还需要两个动画,使这个layer同时向内向外扩展。 那么问题来了,只有一个layer,还不能有subLayer,怎么让它同时又变大又变小呢? 答案是:换个方式。 注意CAShapeLayer是线画出来,线也有颜色,还有宽度是 lineWidth,而且这些属性也是可以动画的。 所以最终的方案是:设置圆的线的颜色为透明,圆的填充色为不透明,园外的颜色不透明(这里的设置指的是看到的效果),让圆逐渐变大到可以显示出整个view,同时让圆的lineWidth逐渐变宽到圆的半径那么大。 看到的效果就是图片像上面的效果一样逐渐显露出来了。 核心动画代码如下: - (void)reveal {
self.backgroundColor = [UIColor clearColor];
[self.circleLayer removeFromSuperlayer];//理论上作为mask的layer不能有父layer,所以要remove掉
self.superview.layer.mask = self.circleLayer;
//让圆的变大的动画
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
UIBezierPath *toPath = [self pathWithDiameter:self.bigDiameter];
// UIBezierPath *toPath = [self pathWithDiameter:0];//缩小当前path的动画
pathAnimation.toValue = (id)toPath.CGPath;
pathAnimation.duration = 1.0;
//让圆的线的宽度变大的动画,效果是内圆变小
CABasicAnimation *lineWidthAnimation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(lineWidth))];
lineWidthAnimation.toValue = @(self.bigDiameter);
lineWidthAnimation.duration = 1.0;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[pathAnimation, lineWidthAnimation];
group.duration = 1.0;
group.removedOnCompletion = NO;//这两句的效果是让动画结束后不会回到原处,必须加
group.fillMode = kCAFillModeForwards;//这两句的效果是让动画结束后不会回到原处,必须加
group.delegate = self;
[self.circleLayer addAnimation:group forKey:@"revealAnimation"]; } /**
* 根据直径生成圆的path,注意圆点是self的中心点,所以(x,y)不是(0,0)
*/
- (UIBezierPath *)pathWithDiameter:(CGFloat)diameter {
return [UIBezierPath bezierPathWithOvalInRect:CGRectMake((CGRectGetWidth(self.bounds) - diameter) / 2, (CGRectGetHeight(self.bounds) - diameter) / 2, diameter, diameter)];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
self.superview.layer.mask = nil;
[self removeFromSuperview];
}
#pragma mark - property
- (CAShapeLayer *)circleLayer {
if (!_circleLayer) {
_circleLayer = [CAShapeLayer layer];
_circleLayer.fillColor = [UIColor clearColor].CGColor;//这个必须透明,因为这样内圆才是不透明的
_circleLayer.strokeColor = [UIColor yellowColor].CGColor;//注意这个必须不能透明,因为实际上是这个显示出后面的图片了
_circleLayer.path = [self pathWithDiameter:self.smallDiameter].CGPath;
}
return _circleLayer; } 完整代码见github:https://github.com/Phelthas/LXMRevealDemo 有什么错误欢迎批评指正
0 0
- 利用layer的mask属性实现逐渐揭示的动画效果,layermask
- 利用layer的mask属性实现逐渐揭示的动画效果
- 为什么layer的mask属性和photoshop的mask不一样
- 使用CALayer的Mask实现注水动画效果
- 使用CALayer的Mask实现注水动画效果
- 使用CALayer的Mask实现注水动画效果
- 使用CALayer的Mask实现注水动画效果
- 使用CALayer的Mask实现注水动画效果
- 利用MovieClip对象的rotationY属性实现翻转动画效果
- 利用属性动画实现动态菜单的效果
- UIImageView 的 layer.mask
- 自定义 Layer 属性的动画
- 自定义 Layer 属性的动画
- 自定义 Layer 属性的动画
- 自定义 Layer 属性的动画
- iOS mask layer的使用
- iOS图片逐渐加载的效果实现
- IOS 雷达效果(Layer的动画)笔记
- Connection refused Will not attempt to authenticate using SASL
- Android 文件的读写(内置存储卡)
- Hbase 基本操作
- 单点登录cas常见问题(十一) - 怎么搭建oauth服务器?
- CALayer2-创建新的层
- 利用layer的mask属性实现逐渐揭示的动画效果,layermask
- 文字渐变效果:图层中的mask属性
- ImportError: No module named persisted.styles 问题解决
- python 警告:simplify chained comparison
- scala: Java Iterator 转 Scala Iterator
- zssh 的使用
- 解决rabbitmq网页管理不成功
- 3029: 守卫者的挑战 概率与期望DP
- gem install 失败的解决办法