美文网首页
两个动画来理解maskView

两个动画来理解maskView

作者: 乌黑的太阳 | 来源:发表于2016-06-07 15:37 被阅读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
        }
    }
    

    相关文章

      网友评论

          本文标题:两个动画来理解maskView

          本文链接:https://www.haomeiwen.com/subject/sbiddttx.html