两个动画来理解maskView
2016-06-07 本文已影响180人
乌黑的太阳
属性说明
maskView是UIView的一个属性,对应的CALayer也有一个mask,他们两个的作用是一样的,同样的一个东西。这个属性类似一个遮罩,设置maskView后,原本的view只能看到maskView不透明的部分。这个属性用来做动画可以实现一些很好玩的东西。
下面介绍两个动画一个swift版,一个oc版
oc版
很简单,主要是利用设置maskView后,原本的view只能看到maskView不透明的部分。
maskView.gif
#import "HZSGradientProgressView.h"
@interface HZSGradientProgressView ()
@property (nonatomic, strong) UIView *mask;
@end
@implementation HZSGradientProgressView
+ (Class)layerClass {
return [CAGradientLayer class];
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)init {
return [self initWithFrame:CGRectZero];
}
- (void)commonInit {
CAGradientLayer *gradientLayer = (CAGradientLayer *)self.layer;
NSArray *colors = [NSArray arrayWithObjects:(__bridge id)[UIColor redColor].CGColor,
(__bridge id)[UIColor orangeColor].CGColor,
(__bridge id)[UIColor yellowColor].CGColor,
(__bridge id)[UIColor greenColor].CGColor,
(__bridge id)[UIColor blueColor].CGColor,
(__bridge id)[UIColor purpleColor].CGColor,
nil];
gradientLayer.startPoint = CGPointMake(0.0, 0.5);
gradientLayer.endPoint = CGPointMake(1.0, 0.5);
gradientLayer.colors = colors;
_mask = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, self.bounds.size.height)];
_mask.backgroundColor = [UIColor blackColor];
self.maskView = _mask;
_value = 0.0;
}
- (void)setValue:(CGFloat)value {
if (value == _value) return;
value = MAX(value, 0);
value = MIN(value, 1);
_value = value;
_mask.frame = CGRectMake(0, 0, self.bounds.size.width * _value, self.bounds.size.height);
[self colorsAnimation];
}
- (void)colorsAnimation {
CAGradientLayer *gradientLayer = (CAGradientLayer *)self.layer;
NSArray *colors = gradientLayer.colors;
if (colors == nil) return;
NSMutableArray *temp = [colors mutableCopy];
id last = colors.lastObject;
[temp removeLastObject];
[temp insertObject:last atIndex:0];
gradientLayer.colors = temp;
}
swift版
这个实现也很方便,主要是利用了视差,有两个imageView都添加在同一个view上面,最上面的那个imageView设置maskView,如果maskView的透明度是0,则看不到最上面的imageView了,只能看到底下的view;如果maskView不透明了,则就能看到最上层的imageview了。这样就造成了切换效果。这么细碎地切换是因为maskView赋值的那个view有n个小碎片似的的子视图,遍历控制每个子视图的alpha就有这个效果了。
maskView2.gif
用的分类实现
import Foundation
private var isFadingKey = "isFadingKey"
private var durationKey = "durationKey"
extension UIView {
private(set) var isFading: Bool {
get {
guard let result = objc_getAssociatedObject(self, &isFadingKey) else { return false }
return (result as! NSNumber).boolValue
}
set {
objc_setAssociatedObject(self, &isFadingKey, NSNumber(bool: newValue), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var maskAnimationDuration: NSTimeInterval {
get {
guard let result = objc_getAssociatedObject(self, &durationKey) else { return 0.1 }
return (result as! NSNumber).doubleValue
}
set {
objc_setAssociatedObject(self, &durationKey, NSNumber(double: newValue), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
func fadeAnimation(reverse: Bool, complete: (() -> Void)?) {
if isFading { return }
isFading = true
configureMaskView()
var subs: [UIView]
if reverse {
subs = self.maskView!.subviews.reverse()
} else {
subs = self.maskView!.subviews
}
let currentAlpha = subs[0].alpha
for (index, sub) in subs.enumerate() {
UIView.animateWithDuration(maskAnimationDuration, delay: Double(index)*maskAnimationDuration, options: [.CurveEaseOut], animations: {
sub.alpha = (currentAlpha == 0 ? 1 : 0)
}, completion: { (finish) in
if index == 14 {
if let closure = complete {
closure()
}
self.isFading = false
}
})
}
}
private func configureMaskView() {
guard self.maskView == nil else { return }
let mask = UIView(frame: self.bounds)
let itemWidth = self.width/15
for index in 0...14 {
let sub = UIView(frame: CGRect(x: CGFloat(index)*itemWidth, y: 0, width: itemWidth, height: self.height))
sub.backgroundColor = UIColor.blackColor()
mask.addSubview(sub)
}
self.maskView = mask
}
}