ios layer.mask

本文介绍了在iOS中如何实现文字渐变效果,通过创建颜色渐变层并利用文字图层裁剪渐变层,使得渐变层仅显示文字部分。在代码实现中,需注意设置渐变图层的mask为文字label,从而达到预期效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


二、文字渐变实现思路:

1.创建一个颜色渐变层,渐变图层跟文字控件一样大。

2.用文字图层裁剪渐变层,只保留文字部分,就会让渐变层只保留有文字的部分,相当于间接让渐变层显示文字,我们看到的其实是被裁剪过后,渐变层的部分内容。

注意:如果用文字图层裁剪渐变层,文字图层就不在拥有显示功能,这个图层就被弄来裁剪了,不会显示,在下面代码中也会有说明。

2.1 创建一个带有文字的label,label能显示文字。

2.2 设置渐变图层的mask为label图层,就能用文字裁剪渐变图层了。

3.mask图层工作原理:

1.根据透明度进行裁剪,只保留非透明部分,显示底部内容。

4.详细代码+解释


// 创建UILabel
     UILabel *label = [[YZLabel alloc] init];
 
     label.text = @ "小码哥,专注于高级iOS开发工程师的培养" ;
 
     [label sizeToFit];
 
     label.center = CGPointMake(200, 100);
 
     // 疑问:label只是用来做文字裁剪,能否不添加到view上。
     // 必须要把Label添加到view上,如果不添加到view上,
label的图层就不会调用drawRect方法绘制文字,也就没有文字裁剪了。
     // 如何验证,自定义Label,重写drawRect方法,看是否调用,发现不添加上去,就不会调用
     [self.view addSubview:label];
 
     // 创建渐变层
     CAGradientLayer *gradientLayer = [CAGradientLayer layer];
 
     gradientLayer.frame = label.frame;
 
     // 设置渐变层的颜色,随机颜色渐变
     gradientLayer.colors = @[(id)[self randomColor].CGColor, (id)[self randomColor].CGColor,(id)[self randomColor].CGColor];
 
     // 疑问:渐变层能不能加在label上
     // 不能,mask原理:默认会显示mask层底部的内容,如果渐变层放在mask层上,就不会显示了
 
     // 添加渐变层到控制器的view图层上
     [self.view.layer addSublayer:gradientLayer];
 
     // mask层工作原理:按照透明度裁剪,只保留非透明部分,文字就是非透明的,因此除了文字,其他都被裁剪掉,
这样就只会显示文字下面渐变层的内容,相当于留了文字的区域,让渐变层去填充文字的颜色。
     // 设置渐变层的裁剪层
     gradientLayer.mask = label.layer;
 
     // 注意:一旦把label层设置为mask层,label层就不能显示了,会直接从父层中移除,然后作为渐变层的mask层,
且label层的父层会指向渐变层, 这样做的目的:以渐变层为坐标系,方便计算裁剪区域,
如果以其他层为坐标系,还需要做点的转换,需要把别的坐标系上的点,转换成自己坐标系上点,
判断当前点在不在裁剪范围内,比较麻烦。
 
 
     // 父层改了,坐标系也就改了,需要重新设置label的位置,才能正确的设置裁剪区域。

    label.frame = gradientLayer.bounds;




#import "LXGradientProcessView.h"
#import "UIView+Extensions.h"
#import "UIColor+Extensions.h"

static const CGFloat kProcessHeight = 10.f;
static const CGFloat kTopSpaces = 5.f;
static const CGFloat kNumberMarkWidth = 60.f;
static const CGFloat kNumberMarkHeight = 20.f;
static const CGFloat kAnimationTime = 3.f;

@interface LXGradientProcessView ()

@property (nonatomic, strong) CALayer *maskLayer;
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@property (nonatomic, strong) UIButton *numberMark; // 数字标示
@property (nonatomic, strong) NSTimer *numberChangeTimer;
@property (nonatomic, assign) CGFloat numberPercent;

@property (nonatomic, strong) NSArray *colorArray;
@property (nonatomic, strong) NSArray *colorLocationArray;

@end

@implementation LXGradientProcessView

- (instancetype)initWithFrame:(CGRect)frame{
    
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        self.colorArray = @[(id)[[UIColor colorWithHex:0xFF6347] CGColor],
                            (id)[[UIColor colorWithHex:0xFFEC8B] CGColor],
                            (id)[[UIColor colorWithHex:0x98FB98] CGColor],
                            (id)[[UIColor colorWithHex:0x00B2EE] CGColor],
                            (id)[[UIColor colorWithHex:0x9400D3] CGColor]];
        self.colorLocationArray = @[@0.1, @0.3, @0.5, @0.7, @1];
        
        self.numberMark.frame = CGRectMake(0, kTopSpaces, kNumberMarkWidth, kNumberMarkHeight);
        [self addSubview:self.numberMark];
        [self setNUmberMarkLayer];
        [self getGradientLayer];
        self.numberPercent = 0;
    }
    return self;
}

- (void)setNUmberMarkLayer { // 提示文字设置渐变色
    
    CAGradientLayer *numberGradientLayer = [CAGradientLayer layer];
    numberGradientLayer.frame = CGRectMake(0, kTopSpaces, self.width, kNumberMarkHeight);
    [numberGradientLayer setColors:self.colorArray];
    [numberGradientLayer setLocations:self.colorLocationArray];
    [numberGradientLayer setStartPoint:CGPointMake(0, 0)];
    [numberGradientLayer setEndPoint:CGPointMake(1, 0)];
    [self.layer addSublayer:numberGradientLayer];
    [numberGradientLayer setMask:self.numberMark.layer];
    self.numberMark.frame = numberGradientLayer.bounds;
    
    NSLog(@"numberMark = %@ numberGradientLayer = %@ ",NSStringFromCGRect(self.numberMark.frame),NSStringFromCGRect(numberGradientLayer.frame));
}

- (void)getGradientLayer
{ // 进度条设置渐变色
    
    // 灰色进度条背景
    CALayer *bgLayer = [CALayer layer];
    bgLayer.frame = CGRectMake(kNumberMarkWidth / 2, self.height - kProcessHeight - kTopSpaces, self.width - kNumberMarkWidth / 2, kProcessHeight);
    bgLayer.backgroundColor = [UIColor colorWithHex:0xF5F5F5].CGColor;
    bgLayer.masksToBounds = YES;
    bgLayer.cornerRadius = kProcessHeight / 2;
    [self.layer addSublayer:bgLayer];
    
    self.maskLayer = [CALayer layer];
    self.maskLayer.frame = CGRectMake(0, 0, (self.width - kNumberMarkWidth / 2) * self.percent / 100.f, kProcessHeight);
    self.maskLayer.borderWidth = self.height / 2;
    
    self.gradientLayer =  [CAGradientLayer layer];
    self.gradientLayer.frame = CGRectMake(kNumberMarkWidth / 2, self.height - kProcessHeight - kTopSpaces, self.width - kNumberMarkWidth / 2, kProcessHeight);
    self.gradientLayer.masksToBounds = YES;
    self.gradientLayer.cornerRadius = kProcessHeight / 2;
    [self.gradientLayer setColors:self.colorArray];
    [self.gradientLayer setLocations:self.colorLocationArray];
    [self.gradientLayer setStartPoint:CGPointMake(0, 0)];
    [self.gradientLayer setEndPoint:CGPointMake(1, 0)];
    [self.gradientLayer setMask:self.maskLayer];
    [self.layer addSublayer:self.gradientLayer];
    
    NSLog(@"maskLayer = %@ gradientLayer = %@  bgLayer = %@",NSStringFromCGRect(self.maskLayer.frame),NSStringFromCGRect(self.gradientLayer.frame),NSStringFromCGRect(bgLayer.frame));
}

- (void)setPercent:(CGFloat)percent {
    [self setPercent:percent animated:YES];
}

- (void)setPercent:(CGFloat)percent animated:(BOOL)animated {
    
    _percent = percent;
    [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(circleAnimation) userInfo:nil repeats:NO];
    // 文字动画
    __weak typeof(self)weakSelf = self;
    [UIView animateWithDuration:kAnimationTime animations:^{
        weakSelf.numberMark.frame = CGRectMake((weakSelf.width - kNumberMarkWidth) * percent / 100, 0, kNumberMarkWidth, kNumberMarkHeight);
        //        [weakSelf.numberMark setTitle:[NSString stringWithFormat:@"%.1f分",percent / 20.f] forState:UIControlStateNormal];
    }];
    
    self.numberChangeTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(changeNumber) userInfo:nil repeats:YES];
}

- (void)changeNumber { // 每0.1秒改变百分比文字
    
    if (!self.percent) {
        [self.numberChangeTimer invalidate];
        self.numberChangeTimer = nil;
    }
    self.numberPercent += (self.percent / (kAnimationTime * 10.f));
    if (self.numberPercent > self.percent) {
        [self.numberChangeTimer invalidate];
        self.numberChangeTimer = nil;
        self.numberPercent = self.percent;
    }
    [self.numberMark setTitle:[NSString stringWithFormat:@"%.1f",self.numberPercent] forState:UIControlStateNormal];
}

- (void)circleAnimation { // 进度条动画
    
    [CATransaction begin];
    [CATransaction setDisableActions:NO];
    [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [CATransaction setAnimationDuration:kAnimationTime];
    self.maskLayer.frame = CGRectMake(0, 0, (self.width - kNumberMarkWidth / 2) * _percent / 100.f, kProcessHeight);
    [CATransaction commit];
}

- (UIButton *)numberMark {
    
    if (nil == _numberMark) {
        _numberMark = [UIButton buttonWithType:UIButtonTypeCustom];
        [_numberMark setTitle:@"0分" forState:UIControlStateNormal];
        [_numberMark setTitleColor:[UIColor colorWithHex:0xFF6347] forState:UIControlStateNormal];
        [_numberMark setBackgroundImage:[UIImage imageNamed:@"user_score_bubble"] forState:UIControlStateNormal];
        _numberMark.titleLabel.font = [UIFont systemFontOfSize:13.f];
        _numberMark.enabled = NO;
    }
    return _numberMark;
}

    // 渐变进度条
    self.processView = [[LXGradientProcessView alloc] initWithFrame:CGRectMake(20.f, 100.f, SCREEN_WIDTH - 40.f, 45.f)];
    self.processView.percent = 0;
    [self.view addSubview:self.processView];
    
    UIButton *stareButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [stareButton setFrame:CGRectMake(20.f, 300.f, SCREEN_WIDTH - 40.f, 38.f)];
    [stareButton addTarget:self action:@selector(onStareButtonClick) forControlEvents:UIControlEventTouchUpInside];
    [stareButton setTitle:@"Stare" forState:UIControlStateNormal];
    stareButton.layer.cornerRadius = 4.f;
    stareButton.layer.borderWidth = 0.5;
    stareButton.layer.borderColor = [UIColor lightGrayColor].CGColor;
    [self.view addSubview:stareButton];
    




//镂空

- (void)addMask{
    UIButton * _maskButton = [[UIButton alloc] init];
    [_maskButton setFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    [_maskButton setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.7]];
    [self.view addSubview:_maskButton];
    
    //create path
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    
    // MARK: circlePath
    [path appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(SCREEN_WIDTH / 2, 200) radius:100 startAngle:0 endAngle:2*M_PI clockwise:NO]];
    
    // MARK: roundRectanglePath
    [path appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 400, SCREEN_WIDTH - 22 * 20, 100) cornerRadius:15] bezierPathByReversingPath]];
    
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    
    shapeLayer.path = path.CGPath;
    
    [_maskButton.layer setMask:shapeLayer];
    
    maskLayer = shapeLayer;
}


//文字变色

    
    UILabel *_numberMark = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 50)];
    _numberMark.textAlignment = NSTextAlignmentLeft;
    _numberMark.text = @"aa";
    
    textLabel = _numberMark;
    
    CAGradientLayer *colorLayer = [CAGradientLayer layer];
    colorLayer.frame    = CGRectMake(0, 0, 300, 50);
    // 颜色分配
    colorLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
                          (__bridge id)[UIColor greenColor].CGColor,
                          (__bridge id)[UIColor blueColor].CGColor,
                          (__bridge id)[UIColor redColor].CGColor];
    // 颜色分割线
    colorLayer.locations  = @[@(0.25), @(0.5), @(0.75)];
    // 起始点
    colorLayer.startPoint = CGPointMake(0, 0);
    // 结束点
    colorLayer.endPoint   = CGPointMake(1, 0);
    
    [self.view.layer addSublayer:colorLayer];
    
    colorLayer.mask = _numberMark.layer;


//绘制wifi图标

/1。弧度转角度
#define pi 3.14159265359
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))


//2。角度转弧度
// Degrees to radians
#define pi 3.14159265359
#define   DEGREES_TO_RADIANS(degrees)  ((pi * degrees)/ 180)

@implementation LTWiFiScanView

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        
    }
    return self;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
    
    CALayer *superLayer = [CALayer layer];
    superLayer.frame = self.frame;
    
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.frame = CGRectMake(0, 0, rect.size.width/6, rect.size.height/6);
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150,151) radius:2.5f startAngle:DEGREES_TO_RADIANS(220) endAngle:DEGREES_TO_RADIANS(320) clockwise:YES];
    layer.path = path.CGPath;
    layer.lineWidth = 5;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.fillColor = [UIColor blueColor].CGColor;
    
    CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animation];
    opacityAnimation.keyPath = @"opacity";
    opacityAnimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
    opacityAnimation.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
    opacityAnimation.fillMode = kCAFillModeBoth;
    opacityAnimation.duration = 1;
    opacityAnimation.beginTime  = CACurrentMediaTime() + (float) 0 * 1.5 / 3;
    opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    opacityAnimation.autoreverses = NO;
    opacityAnimation.removedOnCompletion = NO;
    opacityAnimation.repeatCount = HUGE_VALF;
    
//    [layer addAnimation:opacityAnimation forKey:@"op"];
    [superLayer addSublayer:layer];
    
    
    CAShapeLayer *layer1 = [CAShapeLayer layer];
    layer.frame = CGRectMake(0, 0, rect.size.width/6, rect.size.height/6);
    UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150,150) radius:10 startAngle:DEGREES_TO_RADIANS(220) endAngle:DEGREES_TO_RADIANS(320) clockwise:YES];
    layer1.path = path1.CGPath;
    layer1.lineWidth = 5;
    layer1.strokeColor = [UIColor blueColor].CGColor;
    layer1.fillColor = [UIColor clearColor].CGColor;
    
    CAKeyframeAnimation *opacityAnimation1 = [CAKeyframeAnimation animation];
    opacityAnimation1.keyPath = @"opacity";
    opacityAnimation1.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
    opacityAnimation1.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
    opacityAnimation1.fillMode = kCAFillModeBoth;
    opacityAnimation1.duration = 1;
    opacityAnimation1.beginTime  = CACurrentMediaTime() + (float) 1 * 1.5 / 3;
    opacityAnimation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    opacityAnimation1.autoreverses = NO;
    opacityAnimation1.removedOnCompletion = NO;
    opacityAnimation1.repeatCount = HUGE_VALF;
//    [layer1 addAnimation:opacityAnimation1 forKey:@"op"];
    
    [superLayer addSublayer:layer1];
    
    
    CAShapeLayer *layer2 = [CAShapeLayer layer];
    layer2.frame = CGRectMake(0, 0, rect.size.width/6, rect.size.height/6);
    UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150,150) radius:20 startAngle:DEGREES_TO_RADIANS(220) endAngle:DEGREES_TO_RADIANS(320) clockwise:YES];
    layer2.path = path2.CGPath;
    layer2.lineWidth = 5;
    layer2.strokeColor = [UIColor blueColor].CGColor;
    layer2.fillColor = [UIColor clearColor].CGColor;
    
    CAKeyframeAnimation *opacityAnimation2 = [CAKeyframeAnimation animation];
    opacityAnimation2.keyPath = @"opacity";
    opacityAnimation2.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
    opacityAnimation2.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
    opacityAnimation2.fillMode = kCAFillModeBoth;
    opacityAnimation2.duration = 1;
    opacityAnimation2.beginTime  = CACurrentMediaTime() + (float) 2 * 1.5 / 3;
    opacityAnimation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    opacityAnimation2.autoreverses = NO;
    opacityAnimation2.removedOnCompletion = NO;
    opacityAnimation2.repeatCount = HUGE_VALF;
//    [layer2 addAnimation:opacityAnimation2 forKey:@"op"];
    
    [superLayer addSublayer:layer2];
    
    [self.layer addSublayer:superLayer];



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值