美文网首页
shapeLayer + BezierPath 实现GPU高性能

shapeLayer + BezierPath 实现GPU高性能

作者: coding_Liu | 来源:发表于2019-05-30 09:08 被阅读0次
//  DrawView.m
//  JZYConferenceModule
//
//  Created by Admin on 2018/12/19.
//  Copyright © 2018年 lpc. All rights reserved.
//

#import "JZYDrawView.h"
#import "JZYHioManager.h"
#import "SDPhotoBrowser.h"
#import "SDBrowserImageView.h"
#import "UIColor+HexColor.h"
#import "JZYNotificationKey.h"
#import "BrushModel.h"
#import "JZYHelperManager.h"
#import "LFMovingView.h"
#import "LFStickerLabel.h"
#import "LFText.h"
#import "UIView+LFMEFrame.h"
#import "Masonry.h"
#import "JZYMacro.h"

CGFloat const lf_editingView_stickMinScale = .2f;
CGFloat const lf_editingView_stickMaxScale = 1.2f;

@interface JZYDrawView ()<TouchesHandleDelegate,LFPhotoEditStickerDelegate>

@property (nonatomic, strong) NSMutableArray <BrushModel *>*tmpPathArr;
@property (nonatomic, strong) NSMutableArray *pathsArr; ///存放多个path对象的数组
@property (nonatomic, strong) NSMutableArray *shapeLayersArr; ///存放多个path对象的数组

///存放目前有的LFMovingView对象数组
@property (nonatomic, strong) NSMutableArray <LFMovingView *>*movingViewsArr;

//@property (nonatomic, weak) LFClippingView *clippingView;
/** 因为LFClippingView需要调整transform属性,需要额外创建一层进行缩放处理,理由:UIScrollView的缩放会自动重置transform */

@property (nonatomic, weak) LFMovingView *selectMovingView;

@property (nonatomic, weak) id<LFEditingProtocol> editingDelegate;


@end

@implementation JZYDrawView

{
    CAShapeLayer *shapeLayer;
    CAShapeLayer *otherShapeLayer;
    BOOL _isSingleTap; // defulet is no
}

- (void)dealloc
{
    NSLog(@"drawView 被释放");
}

+ (void)LFStickerViewDeactivated
{
    [LFMovingView setActiveEmoticonView:nil];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self configUI];
    }
    return self;
}
- (void)configUI {
 
    self.backgroundColor = [UIColor.greenColor colorWithAlphaComponent:0.3];
    self.userInteractionEnabled = YES;
    self.clipsToBounds = YES;
    _screenScale = 1.f;
    _minScale = .2f;
    _maxScale = 3.f;
    self.editDelegate = self;
    
}
+ (Class)layerClass
{
    return [CAShapeLayer class];
}
// MARK:- touchesBegan
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (_currentDrawStyle == DrawStyleNone) {
        return;
    }
    self.mineLine = YES;
    _isSingleTap = NO;//回置状态
    
    self.aPath = [[JZYBezierPath alloc] init];
    self.aPath.drawStyle = _currentDrawStyle;
    self.aPath.startPoint = [[touches anyObject] locationInView:self];
    CGPoint point = self.aPath.startPoint;

    shapeLayer = [CAShapeLayer layer];
    shapeLayer.lineJoin      = kCALineJoinRound;
    shapeLayer.lineCap       = kCALineCapRound;
    shapeLayer.lineWidth     = 2;
    shapeLayer.fillColor     = (self.aPath.drawStyle == DrawStyleArrow) ? _selfPainColor.CGColor : [UIColor clearColor].CGColor;

    ///设置画笔颜色
    shapeLayer.strokeColor = _selfPainColor.CGColor;
    
    [self.aPath moveToPoint:point];
    SDBrowserImageView *imageView = (SDBrowserImageView *)self.superview;
    CGFloat scale = imageView.image.size.width / self.bounds.size.width;
    
    [self.whiteboardSession mouseDown:point.x*scale y:point.y*scale];
    
    //通知更变清屏按钮状态
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationRefreshClearBtnStatus object:nil userInfo:@{@"statusMark":@YES}];
    NSLog(@"touchesEvent111");

    [self.shapeLayersArr addObject:shapeLayer];
    [self.pathsArr addObject:self.aPath];
    
}
// MARK:- touchesMoved
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (_currentDrawStyle == DrawStyleNone) {
        return;
    }
    _isSingleTap = YES;
    CGFloat max_x = CGRectGetMaxX(self.frame);
    CGFloat min_x = CGRectGetMinX(self.frame);
    CGFloat max_y = CGRectGetMaxY(self.frame);
    CGFloat min_y = CGRectGetMinY(self.frame);
    NSLog(@"touchesEvent222");

    //    [touches enumerateObjectsUsingBlock:^(UITouch * _Nonnull touche, BOOL * _Nonnull stop) {
    
    UITouch *touche = [touches anyObject];


    __block CGPoint point;

//    if (@available(iOS 9.0, *)) {
//        [[event coalescedTouchesForTouch:touche] enumerateObjectsUsingBlock:^(UITouch * _Nonnull coalescedTouch, NSUInteger idx, BOOL * _Nonnull stop) {
//            point = [coalescedTouch locationInView:self];
//            if (0 < point.x && point.x < max_x - min_x && 0 < point.y && point.y < max_y - min_y) {
//
//                NSLog(@"point:::%f",point.x);
//                [self.path addLineToPoint:point];
//                self->shapeLayer.path = self.path.CGPath;
//
//                BrushModel *model = [[BrushModel alloc] init];
//                model.point = point;
//                model.brushColor = [UIColor colorWithCGColor:self->shapeLayer.strokeColor];
//                ///同时备份点
//                [self.tmpPathArr addObject:model];
//
//                SDBrowserImageView *imageView = (SDBrowserImageView *)self.superview;
//                CGFloat scale = imageView.image.size.width / self.bounds.size.width;
//                [self.whiteboardSession mouseMove:point.x*scale y:point.y*scale];
//            }
//        }];
//    } else {
        self.aPath.endPoint = [touche locationInView:self];
    //pc6
    point = self.aPath.endPoint;
        if (0 < point.x && point.x < max_x - min_x && 0 < point.y && point.y < max_y - min_y) {
    
            NSLog(@"point:::%f",point.x);
            [self.aPath addLineToPoint:point];
            
            
            //6666666线画不上问题 ⚠️ self.aPath.bezierPath.CGPath
            if (self.aPath.drawStyle == DrawStyleLine || self.aPath.drawStyle == DrawStyleArrow) {
                self->shapeLayer.path = self.aPath.CGPath;
            }else {
                self->shapeLayer.path = self.aPath.bezierPath.CGPath;
            }
            
            BrushModel *model = [[BrushModel alloc] init];
            model.point = point;
            model.brushColor = [UIColor colorWithCGColor:self->shapeLayer.strokeColor];
            ///同时备份点
            [self.tmpPathArr addObject:model];
            
            SDBrowserImageView *imageView = (SDBrowserImageView *)self.superview;
            CGFloat scale = imageView.image.size.width / self.bounds.size.width;
            [self.whiteboardSession mouseMove:point.x*scale y:point.y*scale];
        }
//    }
    //    }];
    
    [self.layer addSublayer:shapeLayer];
}
// MARK:-touchesEnded
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (_currentDrawStyle == DrawStyleNone) {
        return;
    }
    if (!_isSingleTap) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationIsSingleTap object:nil];
    }
    NSLog(@"touchesEvent333");
    NSMutableArray *tmpArr = [NSMutableArray arrayWithArray:self.tmpPathArr];
    [self.tmpChangeArr addObject:tmpArr];
    [self.tmpPathArr removeAllObjects];
    
    self.aPath.endPoint = [[touches anyObject] locationInView:self];
    CGPoint point = self.aPath.endPoint;

    SDBrowserImageView *imageView = (SDBrowserImageView *)self.superview;
    CGFloat scale = imageView.image.size.width / self.bounds.size.width;
    [self.whiteboardSession mouseUp:point.x*scale y:point.y*scale];
}
// MARK:- touchesHandle
// MARK: └ touchesBeginHandle
- (void)touchesBeginHandle:(CGPoint)touchPoint {
    
    self.otherPath = [[JZYBezierPath alloc] init];

    otherShapeLayer = [CAShapeLayer layer];
    otherShapeLayer.fillColor     = [UIColor clearColor].CGColor;
    otherShapeLayer.lineJoin      = kCALineJoinRound;
    otherShapeLayer.lineCap       = kCALineCapRound;
    otherShapeLayer.lineWidth     = 2;
    otherShapeLayer.strokeColor = _painColor.CGColor;

    SDBrowserImageView *imageView = (SDBrowserImageView *)self.superview;
    CGFloat scale = imageView.image.size.width / self.bounds.size.width;
    
    NSLog(@"touchesHandle111 scale:%f imageView.image:%@",scale,imageView.image);

    CGPoint point = CGPointMake(touchPoint.x / scale, touchPoint.y / scale);
    
    [self.otherPath moveToPoint:point];
    
    [self.shapeLayersArr addObject:otherShapeLayer];
    [self.pathsArr addObject:self.otherPath];

}
// MARK: └ touchesMovedHandle
- (void)touchesMovedHandle:(CGPoint)touchPoint {
    NSLog(@"touchesHandle222");
    SDBrowserImageView *imageView = (SDBrowserImageView *)self.superview;
    CGFloat scale = imageView.image.size.width / self.bounds.size.width;
    CGPoint point = CGPointMake(touchPoint.x / scale, touchPoint.y / scale);
    
    [self.otherPath addLineToPoint:point];
    otherShapeLayer.path = self.otherPath.CGPath;
    [self.layer addSublayer:otherShapeLayer];

}
// MARK: └ touchesEndHandle
- (void)touchesEndHandle:(CGPoint)touchPoint{

    NSLog(@"touchesHandle333");
    
}

// MARK:- 横竖屏旋转transformPoint
/**
 当切换横竖屏时进行已有坐标转化
 */
- (void)transformPoint:(CGFloat)scaleValue {
    
    NSLog(@"scaleValue 值 :::%f",scaleValue);
    
    /// 处理文本框
    if (self.movingViewsArr.count) {
        [self.movingViewsArr enumerateObjectsUsingBlock:^(LFMovingView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

            
            
  ///444
//            obj.width = 0;
//            obj.frame = CGRectMake(0, obj.origin.y, obj.width, obj.height);
            NSLog(@"objobj111: %@",obj);
//            [obj setWidth:obj.width *scaleValue];
//            [obj setHeight:obj.height *scaleValue];
            obj.backgroundColor = UIColor.redColor;
////            [obj setCenterX:obj.centerX * scaleValue];
////            [obj setCenterY:obj.centerY * scaleValue];
            [obj setX:obj.x *scaleValue];
            [obj setY:obj.y *scaleValue];
//333
//            UIView *l = (LFStickerLabel *)obj.subviews.firstObject;
//            [l setWidth:l.width *scaleValue];
//            [l setHeight:l.height *scaleValue];
//
//            [l setX:l.x *scaleValue];
//            [l setY:l.y *scaleValue];
//
//            LFStickerLabel *lab = (LFStickerLabel *)obj.subviews.firstObject.subviews.firstObject;
//            [lab setWidth:lab.width *scaleValue];
//            [lab setHeight:lab.height *scaleValue];
//
//            [lab setX:lab.x *scaleValue];
//            [lab setY:lab.y *scaleValue];
//
            
 ///222
//            obj.transform = CGAffineTransformIdentity;
//
//            obj.transform = CGAffineTransformMakeScale(scaleValue, scaleValue);
//            CGRect rct = self.frame;
//            rct.size.width  = obj.frame.size.width;
//            rct.size.height = obj.frame.size.height;
//            self.frame = rct;
            
//            obj.center = CGPointMake(rct.size.width/2, rct.size.height/2);
            
///111
//            [obj setScale:scaleValue];



            NSLog(@"objobj222: %@",obj);


            
        }];
    }
    
    
    /// 处理线
    [self.aPath removeAllPoints];
    if (!self.tmpChangeArr.count) {
        return;
    }
    
    //清除子layer
    NSArray<CALayer *> *subLayers = self.layer.sublayers;
    NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id  _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
        return [evaluatedObject isKindOfClass:[CAShapeLayer class]];
    }]];
    [removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [obj removeFromSuperlayer];
    }];
    
    NSMutableArray *tmpArr = [NSMutableArray array];
    [self.tmpChangeArr enumerateObjectsUsingBlock:^(NSMutableArray <BrushModel *>* _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        CAShapeLayer * ashapeLayer = [CAShapeLayer layer];
        JZYBezierPath *apath = [[JZYBezierPath alloc] init];
        
        NSMutableArray <BrushModel *>*tmpPathArr = [NSMutableArray array];
        [obj enumerateObjectsUsingBlock:^(BrushModel * _Nonnull subObj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            NSLog(@"scaleValue 值 ::2222:%f",scaleValue);

            CGPoint point= subObj.point;
            NSLog(@"test value ::: %f",point.x);
            CGFloat x = point.x * scaleValue;
            CGFloat y = point.y * scaleValue;
            NSLog(@"test value222 ::: %f",x);

            point = CGPointMake(x, y);
            
            if (idx == 0) {
                [apath moveToPoint:point];
            }
            [apath addLineToPoint:point];
            
            ashapeLayer.path          = apath.CGPath;
            ashapeLayer.fillColor     = [UIColor clearColor].CGColor;
            ashapeLayer.strokeColor   = subObj.brushColor.CGColor;
            ashapeLayer.lineJoin      = kCALineJoinRound;
            ashapeLayer.lineCap       = kCALineCapRound;
            ashapeLayer.lineWidth     = 2;
            
            [self.layer addSublayer:ashapeLayer];
            BrushModel *model = [[BrushModel alloc] init];
            model.brushColor = subObj.brushColor;
            model.point = point;
            [tmpPathArr addObject:model];
        }];
        
        //放在清屏数组中
        [self.shapeLayersArr addObject:ashapeLayer];
        [self.pathsArr addObject:apath];
        
        [tmpArr addObject:tmpPathArr];
    }];

    [self.tmpChangeArr removeAllObjects];
    [self.tmpChangeArr addObjectsFromArray:tmpArr];
    [tmpArr removeAllObjects];
    tmpArr = nil;
    
}
// MARK:- 清屏
- (void)clear{
    
    [self.shapeLayersArr enumerateObjectsUsingBlock:^(CAShapeLayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.path = nil;
        [obj removeFromSuperlayer];
    }];
    
    [self.pathsArr enumerateObjectsUsingBlock:^(UIBezierPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [obj removeAllPoints];
    }];
}
// MARK:- public
/** 禁用其他功能 */
- (void)photoEditEnable:(BOOL)enable
{
    [self photoEditEnable:enable];
}
// MARK: └ 文字功能
- (void)setEditDelegate:(id<LFPhotoEditStickerDelegate>)editDelegate {
    if (editDelegate) {
        
        /** 贴图 */
        self.tapEnded = ^(BOOL isActive){
            if ([editDelegate respondsToSelector:@selector(lf_photoEditStickerDidSelectViewIsActive:)]) {
                [editDelegate
                 lf_photoEditStickerDidSelectViewIsActive:isActive];
            }
        };
    }
}
- (void)setTapEnded:(void (^)(BOOL))tapEnded
{
    _tapEnded = tapEnded;
    for (LFMovingView *subView in self.subviews) {
        if ([subView isKindOfClass:[LFMovingView class]]) {
            if (tapEnded) {
                __weak typeof(self) weakSelf = self;
                [subView setTapEnded:^(LFMovingView *movingView, UIView *view, BOOL isActive) {
                    weakSelf.selectMovingView = movingView;
                    weakSelf.tapEnded(isActive);
                }];
            } else {
                [subView setTapEnded:nil];
            }
        }
    }
}
/** 创建可移动视图 */
- (LFMovingView *)createBaseMovingView:(UIView *)view active:(BOOL)active
{
    LFMovingViewType type = LFMovingViewType_unknown;
    if ([view isMemberOfClass:[UIImageView class]]) {
        type = LFMovingViewType_imageView;
    } else if ([view isMemberOfClass:[LFStickerLabel class]]) {
        type = LFMovingViewType_label;
    }
    
    LFMovingView *movingView = [[LFMovingView alloc] initWithView:view type:type];
    
    
    [self.movingViewsArr addObject:movingView];
    /** 屏幕中心 */
    movingView.center = [self convertPoint:self.superview.center fromView:(UIView *)self.superview];
    /** 最小缩放率 */
    movingView.minScale = self.minScale;
    /** 最大缩放率 额外调整最大缩放率的比例,比例以屏幕为标准。 */
    CGFloat diffScale = [UIScreen mainScreen].bounds.size.width / view.frame.size.width;
    movingView.maxScale = self.maxScale * diffScale;
    /** 屏幕缩放率 */
    movingView.screenScale = self.screenScale;
    
    [self addSubview:movingView];
    
    
    if (active) {
        [LFMovingView setActiveEmoticonView:movingView];
    }
    
    if (self.tapEnded) {
        __weak typeof(self) weakSelf = self;
        [movingView setTapEnded:^(LFMovingView *movingView, UIView *view, BOOL isActive) {
            weakSelf.selectMovingView = movingView;
            weakSelf.tapEnded(isActive);
        }];
    }
    
    return movingView;
}
- (LFMovingView *)doCreateImage:(UIImage *)image active:(BOOL)active
{
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
    NSLog(@"imageView : %@",imageView);
    LFMovingView *movingView = [self createBaseMovingView:imageView active:active];
    
    return movingView;
}
- (LFMovingView *)doCreateText:(LFText *)text active:(BOOL)active
{
    CGFloat margin = 5.f;
    LFStickerLabel *label = [[LFStickerLabel alloc] initWithFrame:CGRectZero];
    /** 设置内边距 */
    label.textInsets = UIEdgeInsetsMake(margin, margin, margin, margin);
    label.lf_text = text;
    [label drawText];
    
    LFMovingView *movingView = [self createBaseMovingView:label active:active];
    
    return movingView;
}
- (void)setScreenScale:(CGFloat)screenScale
{
    if (screenScale > 0) {
        _screenScale = screenScale;
        for (LFMovingView *subView in self.subviews) {
            if ([subView isKindOfClass:[LFMovingView class]]) {
                subView.screenScale = screenScale;
            }
        }
    }
}

// MARK:- delagate
/** 创建文字 */
- (void)createStickerText:(LFText *)text
{
    if (text) {
        [self createText:text];
    }
}
/** 创建文字 */
- (void)createText:(LFText *)text
{
    LFMovingView *movingView = [self doCreateText:text active:YES];
    //    CGFloat ratio = MIN( (0.5 * self.width) / movingView.width, (0.5 * self.height) / movingView.height);
    CGFloat scale = 0.8f/self.screenScale;
    [movingView setScale:scale];
    self.selectMovingView = movingView;
}
/** 创建图片 */
- (void)createImage:(UIImage *)image
{
    LFMovingView *movingView = [self doCreateImage:image active:YES];
    CGFloat ratio = MIN( (0.2 * [UIScreen mainScreen].bounds.size.width) / movingView.width, (0.5 * [UIScreen mainScreen].bounds.size.height) / movingView.height);
    CGFloat scale = ratio/self.screenScale;
    [movingView setScale:scale];
    self.selectMovingView = movingView;
}
/** 激活选中的贴图 */
- (void)activeSelectStickerView
{
    [LFMovingView setActiveEmoticonView:self.selectMovingView];
}
/** 删除选中贴图 */
- (void)removeSelectStickerView
{
    [self.selectMovingView removeFromSuperview];
}

/** 获取选中贴图的内容 */
- (UIImage *)getSelectStickerImage
{
    if (self.selectMovingView.type == LFMovingViewType_imageView) {
        return ((UIImageView *)self.selectMovingView.view).image;
    }
    return nil;
}
- (LFText *)getSelectStickerText
{
    if (self.selectMovingView.type == LFMovingViewType_label) {
        return ((LFStickerLabel *)self.selectMovingView.view).lf_text;
    }
    return nil;
}

/** 更改选中贴图内容 */
- (void)changeSelectStickerImage:(UIImage *)image
{
    if (self.selectMovingView.type == LFMovingViewType_imageView) {
        UIImageView *imageView = (UIImageView *)self.selectMovingView.view;
        imageView.image = image;
        [self.selectMovingView updateFrameWithViewSize:image.size];
    }
}
- (void)changeSelectStickerText:(LFText *)text
{
    if (self.selectMovingView.type == LFMovingViewType_label) {
        LFStickerLabel *label = (LFStickerLabel *)self.selectMovingView.view;
        label.lf_text = text;
        
        //阴影颜色
        //        label.layer.shadowColor = ([text.textColor isEqual:[UIColor blackColor]]) ? [UIColor whiteColor].CGColor : [UIColor blackColor].CGColor;
        label.lf_text.textColor = _selfPainColor;
        [label drawText];
        //ggggg
        [self.selectMovingView updateFrameWithViewSize:label.size];
    }
}

// MARK:- lazy
-(id<NSHioWhiteboardService>)whiteboardSession {
    return [[JZYHioManager shareInstance] whiteboardSession];
}

- (NSMutableArray<BrushModel *> *)tmpPathArr {
    if (_tmpPathArr == nil)
    {
        _tmpPathArr = [NSMutableArray array];
    }
    return _tmpPathArr;
}

- (NSMutableArray <NSMutableArray *>*)tmpChangeArr {
    if (_tmpChangeArr == nil)
    {
        _tmpChangeArr = [NSMutableArray array];
    }
    return _tmpChangeArr;
}

- (NSMutableArray<LFMovingView *> *)movingViewsArr {
    if (!_movingViewsArr) {
        _movingViewsArr = [NSMutableArray array];
    }
    return _movingViewsArr;
}

- (NSMutableArray *)pathsArr {
    if (_pathsArr == nil)
    {
        _pathsArr = [NSMutableArray array];
    }
    return _pathsArr;
}

- (NSMutableArray *)shapeLayersArr {
    if (_shapeLayersArr == nil)
    {
        _shapeLayersArr = [NSMutableArray array];
    }
    return _shapeLayersArr;
}

@end

相关文章

网友评论

      本文标题:shapeLayer + BezierPath 实现GPU高性能

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