shapeLayer + BezierPath 实现GPU高性能
2019-05-30 本文已影响0人
coding_Liu
// 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