美文网首页iOS DeveloperIOS
二、CAShapLayer马步

二、CAShapLayer马步

作者: iLees | 来源:发表于2017-01-09 15:26 被阅读185次

<h4>简述</h4>

1、CAShapeLayer继承自CALayer,通过UIBezierPath的结合可以实现非drawRect方式绘制图形;
2、CAShapLayer的path是一个首尾相连的闭环曲线,即使其贝塞尔曲线是非闭环的;
3、drawRect属于CoreGraphics框架,占用cpu性能消耗较大。CAShapLayer属于CoreAnimation框架,通过GPU渲染图形不消耗内存和cpu。

<h4>CAShapLayer关键属性</h4>

//  路径
@property(nullable) CGPathRef path;
// 填充色
@property(nullable) CGColorRef fillColor;
// 描边色
@property(nullable) CGColorRef strokeColor;
// path路径开始位置  0 - 1
@property CGFloat strokeStart;
// path路径结束位置 0 - 1
@property CGFloat strokeEnd;
// 线条宽度
@property CGFloat lineWidth;
// 线条首尾外观
@property(copy) NSString *lineCap;
// 线条交接处外观
@property(copy) NSString *lineJoin;

<h4>No code no bibi</h4>

<h5>1、先来画一个对号</h5>

@implementation SZShapLayer

- (void)didMoveToWindow {
    CGFloat viewWidth = self.frame.size.width;
    CGFloat viewHeitht = self.frame.size.height;
    // 1、创建path
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(viewWidth / 4, viewHeitht / 2)];
    [path addLineToPoint:CGPointMake(viewWidth / 2, viewWidth / 4 * 3)];
    [path addLineToPoint:CGPointMake(viewWidth / 4 * 3, viewWidth / 3)];
    // 2、创建ShapLayer
    CAShapeLayer *shapLayer = [CAShapeLayer layer];
    shapLayer.lineWidth = 16;
    shapLayer.fillColor = [UIColor clearColor].CGColor;
    shapLayer.strokeColor = [UIColor brownColor].CGColor;
    shapLayer.path = path.CGPath;
    shapLayer.lineCap = kCALineCapRound;
    shapLayer.lineJoin = kCALineJoinRound;
    [self.layer addSublayer:shapLayer];
}

@end

这里需要注意,如果填充色非透明会是下面效果:


<h5>2、实现一个带动画效果的选中按钮</h5>

CheckAnimationButton.gif
#import <UIKit/UIKit.h>

@interface SZShapLayer : UIView
- (void)resetView;
@end
#import "SZShapLayer.h"

static NSString * const kCornerRadiusAnimationKey = @"cornerRadiusAnimation";
static NSString * const kCheckAnimationKey = @"kCheckAnimationKey";
static const CGFloat kButtonWidth = 100;
static const CGFloat kButtonHeight = 100;

@interface SZShapLayer() <CAAnimationDelegate>

/** 对号 */
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
/** 对号 */
@property (nonatomic, strong) CABasicAnimation *shapeLayerAnimation;

/** 动画进行标识 */
@property (nonatomic, assign) BOOL isAnimation;
@end

@implementation SZShapLayer

#pragma mark - Life Circle

- (instancetype)init {
    if (self = [super init]) {
        [self config];
    }
    return self;
}

-(void)layoutSubviews {
    self.layer.cornerRadius=self.frame.size.height/2;
}

#pragma mark - Outer Method 

- (void)resetView {
    if (self.isAnimation) {
        return;
    }
    self.frame = CGRectMake(100, 100, 130, 50);
    [self.shapeLayer removeFromSuperlayer];
    self.backgroundColor = [UIColor colorWithRed:0.98 green:0.81 blue:0.84 alpha:1];
}

#pragma mark - UI Build

- (void)config {
    // 1、设置self背景色
    self.backgroundColor = [UIColor colorWithRed:0.98 green:0.81 blue:0.84 alpha:1];
    // 2、添加点击手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
    [self addGestureRecognizer:tap];
}

- (void)showCheckAnimation {
    // 1、添加对号
    [self.layer addSublayer:self.shapeLayer];
    // 2、给对号设置动画
    [self.shapeLayer addAnimation:self.shapeLayerAnimation forKey:kCheckAnimationKey];
}

#pragma mark - Event

- (void)tap:(UITapGestureRecognizer *)tapGesture {
    if (self.isAnimation) {
        return;
    }
    self.layer.cornerRadius = kButtonHeight * 0.5;
    // 设置动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
    animation.delegate = self;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.duration = 0.4;
    animation.fromValue = @(self.frame.size.height * 0.5);
    [self.layer addAnimation:animation forKey:kCornerRadiusAnimationKey];
}

#pragma mark - Animation Delegate

- (void)animationDidStart:(CAAnimation *)anim {
    if ([self.layer animationForKey:kCornerRadiusAnimationKey]) {
        // 1、动画进行标识设置
        self.isAnimation = YES;
        // 2、动画设置bounds和背景色
        [UIView animateWithDuration:0.6f delay:0.0f usingSpringWithDamping:0.6f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.bounds = CGRectMake(0, 0, kButtonWidth, kButtonHeight);
            self.backgroundColor = [UIColor colorWithRed:1 green:0.8 blue:0.6 alpha:1];
        } completion:^(BOOL finished) {
            //[self.layer removeAnimationForKey:@"kCornerRadiusAnimationKey"];
            [self showCheckAnimation];
        }];
    } else if([self.shapeLayer animationForKey:kCheckAnimationKey]) {
        self.isAnimation = YES;
    }
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    if (self.layer.animationKeys.count == 0 && self.shapeLayer.animationKeys.count == 0) {
        self.isAnimation = NO;
    }
}

#pragma mark - Property

- (CABasicAnimation *)shapeLayerAnimation {
    if (!_shapeLayerAnimation) {
        _shapeLayerAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        _shapeLayerAnimation.delegate = self;
        _shapeLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        _shapeLayerAnimation.duration = 0.4f;
        _shapeLayerAnimation.fromValue = @(0.0f);
        _shapeLayerAnimation.toValue = @(1.0f);
    }
    return _shapeLayerAnimation;
}

- (CAShapeLayer *)shapeLayer {
    if (!_shapeLayer) {
        // 1、获取宽高
        CGFloat viewWidth = self.frame.size.width;
        CGFloat viewHeitht = self.frame.size.height;
        // 2、创建path
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(viewWidth / 4, viewHeitht / 2)];
        [path addLineToPoint:CGPointMake(viewWidth / 2, viewWidth / 4 * 3)];
        [path addLineToPoint:CGPointMake(viewWidth / 4 * 3, viewWidth / 3)];
        // 3、创建ShapLayer
        CAShapeLayer *shapLayer = [CAShapeLayer layer];
        shapLayer.lineWidth = 16;
        shapLayer.fillColor = [UIColor clearColor].CGColor;
        shapLayer.strokeColor = [UIColor colorWithRed:0.75 green:0.9 blue:0.9 alpha:1].CGColor;
        shapLayer.path = path.CGPath;
        shapLayer.lineCap = kCALineCapRound;
        shapLayer.lineJoin = kCALineJoinRound;
        _shapeLayer = shapLayer;
    }
    return _shapeLayer;
}

@end

这么调用

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"CAShapLayer";
    SZShapLayer *view = [SZShapLayer new];
    view.frame = CGRectMake(100, 100, 130, 50);
    self.shapView = view;
    [self.view addSubview:view];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self.shapView resetView];
}

有几点需要注意:
1、static NSString * const kCornerRadiusAnimationKey = @"cornerRadiusAnimation";
这里const要在*后,表示kCornerRadiusAnimationKey这个变量的值是不可修改的。不这么写,使用该变量的地方会有警告产生:Sending 'const NSString *__strong' to parameter of type 'NSString *' discards qualifiers。
2、经过测试,animationDidStop回调函数中当所有的动画结束之后self.layer和self.shapLayer的animationKeys均为空。而非想象中的[self.shapeLayer animationForKey:kCheckAnimationKey] == anime,有兴趣的同学可以自己试试。

相关文章

  • 二、CAShapLayer马步

    简述 1、CAShapeLayer继承自CALayer,通过UIBezierPath的结合可以实现非drawRec...

  • CAShapLayer

    说到CAShapLayer就不得不说到UIBezierPath: UIBezierPath是在 UIKit 中的一...

  • CAShapLayer + UIBezierPath

    使用shapelayer 画图步骤 1、新建UIBezierPath对象bezierPath2、新建CAShape...

  • BeziaPath 、CAShapLayer、CAAnimati

    主要讲解使用贝塞尔曲线来绘制不规则图形、动画展示。 1.基本概念 核心动画作用在CALayer(Core anim...

  • 马步

    一定要45度 用身体自重站稳支撑 后腰打开膨胀 胸口内含 背部打开饱满 筋膜连城一个整体 收下巴 颈部后躺, 整体...

  • 马步

    马步是练习武术[https://baike.baidu.com/item/%E6%AD%A6%E6%9C%AF/2...

  • 2020-04-06

    4月6日 1分钟马步30组,累积30分钟马步,组间休息一分钟 为了能够每天扎马步,所以刚开始阶段缩短了单次马步时间...

  • 寒舍欣和的100道烤箱菜13【香烤马步鱼】

    13【香烤马步鱼】 主料:新鲜马步鱼3条 调料:盐、生抽、料酒、烧烤腌料(超市有买)、奥尔良腌料、料酒 1、马步鱼...

  • 扎马步

    昨晚看了罗胖的《成大事者不纠结》,看罗胖的书真的是一种享受,用讲故事的手法把历史事件还原,让读者看的津津有味,通...

  • 扎“马步”

    坐在这里,想起了奶奶,有许多很温馨的记忆。我在小学还有中学时候的记忆,奶奶对我的期望,总是默默的陪伴我。 ...

网友评论

    本文标题:二、CAShapLayer马步

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