美文网首页
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