两个动画来理解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
    }
}
上一篇下一篇

猜你喜欢

热点阅读