iOS - Quartz 2D 画板绘制

简介: 1、绘制画板1.1 绘制简单画板PaintBoardView.h @interface PaintBoardView : UIView @endPaintBoardView.

1、绘制画板

1.1 绘制简单画板

  • PaintBoardView.h

        @interface PaintBoardView : UIView
    
        @end
  • PaintBoardView.m

        @interface PaintBoardView ()
    
        /// 路径
        @property (nonatomic, strong) UIBezierPath *path;
    
        /// 保存所有路径的数组
        @property (nonatomic, strong) NSMutableArray *pathsArrayM;
    
        @end
    
        @implementation PaintBoardView
    
        /// 初始化
        - (instancetype)initWithFrame:(CGRect)frame {
    
            if (self = [super initWithFrame:frame]) {
                self.backgroundColor = [UIColor whiteColor];
            }
            return self;
        }
    
        /// 触摸开始
        - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
            // 获取触摸起始点位置
            CGPoint startPoint = [touches.anyObject locationInView:self];
    
            // 添加路径描绘起始点
            [self.path moveToPoint:startPoint];
    
            // 添加一条触摸路径描绘
            [self.pathsArrayM addObject:self.path];
        }
    
        /// 触摸移动
        - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
            // 获取触摸点位置
            CGPoint touchPoint = [touches.anyObject locationInView:self];
    
            // 添加路径描绘
            [self.path addLineToPoint:touchPoint];
    
            // 刷新视图
            [self setNeedsDisplay];
        }
    
        /// 触摸结束
        - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
            // 获取绘制结果
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);
            CGContextRef ctx = UIGraphicsGetCurrentContext();
            [self.layer renderInContext:ctx];
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
    
            NSData *data = UIImagePNGRepresentation(image);
            [data writeToFile:@"/Users/JHQ0228/Desktop/Images/pic.png" atomically:YES];
        }
    
        /// 触摸取消
        - (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event {
            [self touchesEnded:touches withEvent:event];
        }
    
        /// 绘制图形
        - (void)drawRect:(CGRect)rect {
    
            for (UIBezierPath *path in self.pathsArrayM) {
    
                // 绘制路径
                [path stroke];
            }
        }
    
        /// 懒加载
    
        - (UIBezierPath *)path {
    
            if (_path == nil) {
                _path = [UIBezierPath bezierPath];
            }
            return _path;
        }
    
        - (NSMutableArray *)pathsArrayM {
    
            if (_pathsArrayM == nil) {
                _pathsArrayM = [NSMutableArray array];
            }
            return _pathsArrayM;
        }
    
        @end
  • ViewController.m

        // 创建画板
        CGRect frame = CGRectMake(20, 50, self.view.bounds.size.width - 40, 200);
        PaintBoardView *paintBoard = [[PaintBoardView alloc] initWithFrame:frame];
    
        [self.view addSubview:paintBoard];
  • 效果

    Quartz2D102Quartz2D103

1.2 绘制画板封装

  • 具体实现代码见 GitHub 源码 QExtension

  • QPaintBoardPath.h

        @interface QPaintBoardPath : UIBezierPath
    
        /// 线的颜色
        @property (nonatomic, strong) UIColor *pathColor;
    
        /// 线的宽度
        @property (nonatomic, assign) CGFloat pathWidth;
    
        @end
  • QPaintBoardPath.m

        @implementation QPaintBoardPath
    
        @end
  • QPaintBoardView.h

        @interface QPaintBoardView : UIView
    
        /// 画线的宽度,default is 1,max is 30
        @property (nonatomic, assign) CGFloat paintLineWidth;
    
        /// 画笔的颜色,default is blackColor
        @property (nonatomic, strong) UIColor *paintLineColor;
    
        /// 画板的颜色,default is whiteColor
        @property (nonatomic, strong) UIColor *paintBoardColor;
    
        /**
         *  创建画板视图控件,获取绘画结果
         *
         *  @param frame        画板视图控件 frame
         *  @param lineWidth    画笔的线宽,default is 1,max is 30
         *  @param lineColor    画笔的颜色,default is blackColor
         *  @param boardColor   画板的颜色,default is whiteColor
         *  @param result       绘画结果
         *
         *  @return 手势锁视图控件
         */
        + (instancetype)q_paintBoardViewWithFrame:(CGRect)frame
                                        lineWidth:(CGFloat)lineWidth
                                        lineColor:(nullable UIColor *)lineColor
                                       boardColor:(nullable UIColor *)boardColor
                                      paintResult:(void (^)(UIImage * _Nullable image))result;
    
        /**
         *  创建简单画板视图控件
         *
         *  @param frame    画板视图控件 frame
         *
         *  @return 手势锁视图控件
         */
        + (instancetype)q_paintBoardViewWithFrame:(CGRect)frame;
    
        /**
         *  获取绘画结果
         *
         *  @return 绘画结果图片
         */
        - (UIImage * _Nullable)q_getPaintImage;
    
        /**
         *  清除绘画结果
         */
        - (void)q_clear;
    
        /**
         *  撤销绘画结果
         */
        - (void)q_back;
    
        @end
  • QPaintBoardView.m

        #import "QPaintBoardPath.h"
    
        @interface QPaintBoardView ()
    
        /// 路径
        @property (nonatomic, strong, nullable) QPaintBoardPath *path;
    
        /// 保存所有路径的数组
        @property (nonatomic, strong) NSMutableArray *pathsArrayM;
    
        /// 绘画结果
        @property (nonatomic, copy) void (^resultBlock)(UIImage * _Nullable);
    
        /// 按钮工具条
        @property (nonatomic, strong) UIView *toolView;
    
        /// 画笔设置视图
        @property (nonatomic, strong) UIView *brushSetingView;
    
        /// 颜色选择视图
        @property (nonatomic, strong) UIScrollView *colorSelectedView;
    
        /// 画板设置视图
        @property (nonatomic, strong) UIScrollView *boardSetingView;
    
        /// 记录线的颜色
        @property (nonatomic, strong) UIColor *lastPaintLineColor;
    
        /// 记录线的宽度
        @property (nonatomic, assign) CGFloat lastPaintLineWidth;
    
        @end
    
        @implementation QPaintBoardView
    
        #pragma mark - 创建画板
    
        /// 创建画板视图控件,获取绘画结果
        + (instancetype)q_paintBoardViewWithFrame:(CGRect)frame
                                        lineWidth:(CGFloat)lineWidth
                                        lineColor:(nullable UIColor *)lineColor
                                       boardColor:(nullable UIColor *)boardColor
                                      paintResult:(void (^)(UIImage * _Nullable image))result {
    
            QPaintBoardView *paintBoardView = [[self alloc] init];
    
        //    CGRect tmpFrame = frame;
        //    tmpFrame.size.height = frame.size.height + 44;
    
            paintBoardView.frame = frame;
            paintBoardView.paintLineWidth = (lineWidth > 30 ? 30 : lineWidth) ? : 1;
            paintBoardView.paintLineColor = lineColor ? : [UIColor blackColor];
            paintBoardView.paintBoardColor = boardColor ? : [UIColor whiteColor];
            paintBoardView.resultBlock = result;
    
            return paintBoardView;
        }
    
        /// 创建简单画板视图控件
        + (instancetype)q_paintBoardViewWithFrame:(CGRect)frame {
    
            QPaintBoardView *paintBoardView = [[self alloc] initWithFrame:frame];
    
            paintBoardView.paintLineWidth = 1;
            paintBoardView.paintLineColor = [UIColor blackColor];
            paintBoardView.paintBoardColor = [UIColor whiteColor];
    
            return paintBoardView;
        }
    
        #pragma mark - 自定义画板
    
        /// 初始化,自定义画板界面
        - (instancetype)init {
    
            if (self = [super init]) {
    
                self.clipsToBounds = YES;
    
                // 添加工具按钮视图
    
                self.toolView = [[UIView alloc] init];
                self.toolView.backgroundColor = [UIColor blackColor];
                [self addSubview:self.toolView];
    
                NSArray *imageNames = @[@"btn_brush", @"btn_board", @"btn_eraser", @"btn_back", @"btn_clear", @"btn_save"];
                NSArray *selectedImageNames = @[@"btn_brush_pressed", @"btn_board_pressed", @"btn_eraser_pressed"];
    
                for (NSUInteger i = 0; i < 6; i++) {
    
                    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
                    button.tag = i;
                    [button setBackgroundImage:[self q_getBundleImageWithName:imageNames[i]] forState:UIControlStateNormal];
                    [button addTarget:self action:@selector(toolButtonClick:) forControlEvents:UIControlEventTouchUpInside];
                    [self.toolView addSubview:button];
    
                    if (i < 3) {
                        [button setBackgroundImage:[self q_getBundleImageWithName:selectedImageNames[i]] forState:UIControlStateSelected];
                    }
                }
    
                // 添加画笔设置视图
    
                self.brushSetingView = [[UIView alloc] init];
                self.brushSetingView.backgroundColor = [UIColor grayColor];
                [self addSubview:self.brushSetingView];
                [self sendSubviewToBack:self.brushSetingView];
    
                UIView *widthBackView = [[UIView alloc] init];
                widthBackView.layer.borderWidth = 1;
                widthBackView.layer.borderColor = [UIColor lightGrayColor].CGColor;
                UIView *widthView = [[UIView alloc] init];
                [widthBackView addSubview:widthView];
                [self.brushSetingView addSubview:widthBackView];
    
                UISlider *widthSlider = [[UISlider alloc] init];
                widthSlider.thumbTintColor = [UIColor orangeColor];
                [widthSlider addTarget:self action:@selector(widthSliderClick:) forControlEvents:UIControlEventValueChanged];
                [self.brushSetingView addSubview:widthSlider];
    
                UIButton *colorSelectedBtn = [[UIButton alloc] init];
                colorSelectedBtn.layer.borderWidth = 1;
                colorSelectedBtn.layer.borderColor = [UIColor lightGrayColor].CGColor;
                [colorSelectedBtn addTarget:self action:@selector(colorSelectedBtnClick:) forControlEvents:UIControlEventTouchUpInside];
                [self.brushSetingView addSubview:colorSelectedBtn];
    
                // 添加画笔颜色选择视图
    
                self.colorSelectedView = [[UIScrollView alloc] init];
                self.colorSelectedView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.3];
                self.colorSelectedView.showsHorizontalScrollIndicator = NO;
                [self addSubview:self.colorSelectedView];
                [self sendSubviewToBack:self.colorSelectedView];
    
                NSArray *colorArray = @[[UIColor blackColor], [UIColor whiteColor], [UIColor redColor],
                                        [UIColor greenColor], [UIColor blueColor], [UIColor cyanColor],
                                        [UIColor magentaColor], [UIColor orangeColor], [UIColor yellowColor],
                                        [UIColor darkGrayColor], [UIColor lightGrayColor], [UIColor brownColor],
                                        [UIColor grayColor], [UIColor purpleColor]];
    
                for (NSUInteger i = 0; i < 14; i++) {
                    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
                    button.layer.borderWidth = 1;
                    button.layer.borderColor = [UIColor lightGrayColor].CGColor;
                    [button setBackgroundColor:colorArray[i]];
                    [button addTarget:self action:@selector(colorSelectedClick:) forControlEvents:UIControlEventTouchUpInside];
                    [self.colorSelectedView addSubview:button];
                }
    
                // 添加画板设置视图
    
                self.boardSetingView = [[UIScrollView alloc] init];
                self.boardSetingView.backgroundColor = [UIColor grayColor];
                self.boardSetingView.showsHorizontalScrollIndicator = NO;
                [self addSubview:self.boardSetingView];
                [self sendSubviewToBack:self.boardSetingView];
    
                for (NSUInteger i = 0; i < 14; i++) {
                    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
                    button.layer.borderWidth = 1;
                    button.layer.borderColor = [UIColor lightGrayColor].CGColor;
                    [button setBackgroundColor:colorArray[i]];
                    [button addTarget:self action:@selector(boardColorSelectedClick:) forControlEvents:UIControlEventTouchUpInside];
                    [self.boardSetingView addSubview:button];
                }
            }
            return self;
        }
    
        /// 布局子控件
        - (void)layoutSubviews {
            [super layoutSubviews];
    
            if (self.subviews.count) {
    
                // 设置工具按钮视图
    
                self.toolView.frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 44);
    
                for (NSUInteger i = 0; i < 6; i++) {
                    CGFloat margin = (self.bounds.size.width - 44 * 6) / 7;
                    CGFloat x = margin + (margin + 44) * i;
                    self.toolView.subviews[i].frame = CGRectMake(x, 0, 44, 44);
                }
    
                // 设置画笔设置视图
    
                self.brushSetingView.frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 60);
    
                self.brushSetingView.subviews[0].frame = CGRectMake(15, 15, 30, 30);
                self.brushSetingView.subviews[0].layer.cornerRadius = 15;
                self.brushSetingView.subviews[0].layer.masksToBounds = YES;
    
                CGFloat w = self.paintLineWidth;
                self.brushSetingView.subviews[0].subviews[0].frame = CGRectMake(15 - w / 2, 15 - w / 2, w, w);
                self.brushSetingView.subviews[0].subviews[0].layer.cornerRadius = w / 2;
                self.brushSetingView.subviews[0].subviews[0].layer.masksToBounds = YES;
                self.brushSetingView.subviews[0].subviews[0].backgroundColor = self.paintLineColor;
    
                self.brushSetingView.subviews[1].frame = CGRectMake(60, 15, self.bounds.size.width - 60 - 80, 32);
                UISlider *slider = self.brushSetingView.subviews[1];
                slider.value = self.paintLineWidth / 30;
    
                self.brushSetingView.subviews[2].frame = CGRectMake(self.bounds.size.width - 60, 15, 50, 30);
                self.brushSetingView.subviews[2].backgroundColor = self.paintLineColor;
    
                // 设置画笔颜色选择视图
    
                self.colorSelectedView.frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 60);
                self.colorSelectedView.contentSize = CGSizeMake(14 * (50 + 20) + 20, 50);
    
                for (NSUInteger i = 0; i < 14; i++) {
                    CGFloat x = 20 + (20 + 50) * i;
                    self.colorSelectedView.subviews[i].frame = CGRectMake(x, 10, 50, 40);
                }
    
                // 设置画板设置视图
    
                self.boardSetingView.frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 60);
                self.boardSetingView.contentSize = CGSizeMake(14 * (50 + 20) + 20, 50);
    
                for (NSUInteger i = 0; i < 14; i++) {
                    CGFloat x = 20 + (20 + 50) * i;
                    self.boardSetingView.subviews[i].frame = CGRectMake(x, 10, 50, 40);
                }
            }
        }
    
        /// 工具按钮点击事件处理
        - (void)toolButtonClick:(UIButton *)btn {
    
            switch (btn.tag) {
    
                case 0: {
                    // 画笔设置
    
                    [self exitEraseState];
    
                    if (btn.isSelected == NO) {
    
                        [self hideBoardSetingView];
    
                        [self showColorSelectedView];
                        [self showBrushSetingView];
    
                    } else {
    
                        [self hideColorSelectedView];
                        [self hideBrushSetingView];
                    }
                    break;
                }
    
                case 1: {
                    // 画板设置
    
                    [self exitEraseState];
    
                    if (btn.isSelected == NO) {
    
                        [self hideColorSelectedView];
                        [self hideBrushSetingView];
    
                        [self showBoardSetingView];
    
                    } else {
    
                        [self hideBoardSetingView];
                    }
                    break;
                }
    
                case 2: {
                    // 擦除
    
                    [self hideBoardSetingView];
    
                    [self hideColorSelectedView];
                    [self hideBrushSetingView];
    
                    if (btn.selected == NO) {
    
                        [self enterEraseState];
    
                    } else {
                        [self exitEraseState];
                    }
                    break;
                }
    
                case 3: {
                    // 撤销
    
                    [self hideBoardSetingView];
    
                    [self hideColorSelectedView];
                    [self hideBrushSetingView];
    
                    [self q_back];
    
                    break;
                }
    
                case 4: {
                    // 清除
    
                    [self hideBoardSetingView];
    
                    [self hideColorSelectedView];
                    [self hideBrushSetingView];
    
                    [self exitEraseState];
    
                    [self q_clear];
    
                    break;
                }
    
                case 5: {
                    // 获取绘制结果
    
                    [self hideBoardSetingView];
    
                    [self hideColorSelectedView];
                    [self hideBrushSetingView];
    
                    [self exitEraseState];
    
                    if (self.resultBlock) {
                        self.resultBlock([self q_getPaintImage]);
                    }
    
                    break;
                }
    
                default:
                    break;
            }
        }
    
        /// 画笔线宽设置按钮点击事件处理
        - (void)widthSliderClick:(UISlider *)slider {
    
            if (slider.value == 0) {
                self.paintLineWidth = 1;
            } else {
                self.paintLineWidth = slider.value * 30;
            }
    
            CGFloat w = self.paintLineWidth;
            self.brushSetingView.subviews[0].subviews[0].frame = CGRectMake(15 - w / 2, 15 - w / 2, w, w);
            self.brushSetingView.subviews[0].subviews[0].layer.cornerRadius = w / 2;
        }
    
        /// 画笔颜色选择按钮点击事件处理
        - (void)colorSelectedBtnClick:(UIButton *)btn {
    
            if (btn.selected == NO) {
                [self showColorSelectedView];
            } else {
                [self hideColorSelectedView];
            }
        }
    
        /// 画笔颜色选择点击响应事件处理
        - (void)colorSelectedClick:(UIButton *)btn {
    
            self.paintLineColor = btn.backgroundColor;
    
            self.brushSetingView.subviews[0].subviews[0].backgroundColor = btn.backgroundColor;
            self.brushSetingView.subviews[2].backgroundColor = btn.backgroundColor;
        }
    
        /// 画板颜色选择点击响应事件处理
        - (void)boardColorSelectedClick:(UIButton *)btn {
    
            self.paintBoardColor = btn.backgroundColor;
        }
    
        /// 显示画笔设置视图
        - (void)showBrushSetingView {
    
            UIButton *setBrushBtn = self.toolView.subviews[0];
    
            if (setBrushBtn.selected == NO) {
    
                setBrushBtn.selected = YES;
    
                [UIView animateWithDuration:0.2 animations:^{
                    CGRect frame = CGRectMake(0, self.bounds.size.height - 44 - 60, self.bounds.size.width, 60);
                    self.brushSetingView.frame = frame;
                }];
            }
        }
    
        /// 隐藏画笔设置视图
        - (void)hideBrushSetingView {
    
            UIButton *setBrushBtn = self.toolView.subviews[0];
    
            if (setBrushBtn.selected) {
    
                setBrushBtn.selected = NO;
    
                [UIView animateWithDuration:0.2 animations:^{
                    CGRect frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 60);
                    self.brushSetingView.frame = frame;
                }];
            }
        }
    
        // 显示画笔颜色选择视图
        - (void)showColorSelectedView {
    
            UIButton *colorSelectedBtn = self.brushSetingView.subviews[2];
    
            if (colorSelectedBtn.selected == NO) {
    
                colorSelectedBtn.selected = YES;
    
                [UIView animateWithDuration:0.2 animations:^{
                    CGRect frame = CGRectMake(0, self.bounds.size.height - 44 - 60 - 60, self.bounds.size.width, 60);
                    self.colorSelectedView.frame = frame;
                }];
            }
        }
    
        /// 隐藏画笔颜色选择视图
        - (void)hideColorSelectedView {
    
            UIButton *colorSelectedBtn = self.brushSetingView.subviews[2];
    
            if (colorSelectedBtn.selected) {
    
                colorSelectedBtn.selected = NO;
    
                [UIView animateWithDuration:0.2 animations:^{
                    CGRect frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 60);
                    self.colorSelectedView.frame = frame;
                }];
            }
        }
    
        /// 显示画板设置视图
        - (void)showBoardSetingView {
    
            UIButton *setBoardBtn = self.toolView.subviews[1];
    
            if (setBoardBtn.selected == NO) {
    
                setBoardBtn.selected = YES;
    
                [UIView animateWithDuration:0.2 animations:^{
                    CGRect frame = CGRectMake(0, self.bounds.size.height - 44 - 60, self.bounds.size.width, 60);
                    self.boardSetingView.frame = frame;
                }];
            }
        }
    
        /// 隐藏画板设置视图
        - (void)hideBoardSetingView {
    
            UIButton *setBoardBtn = self.toolView.subviews[1];
    
            if (setBoardBtn.selected) {
    
                setBoardBtn.selected = NO;
    
                [UIView animateWithDuration:0.2 animations:^{
                    CGRect frame = CGRectMake(0, self.bounds.size.height - 44, self.bounds.size.width, 60);
                    self.boardSetingView.frame = frame;
                }];
            }
        }
    
        /// 进入擦除状态
        - (void)enterEraseState {
    
            UIButton *setEraseBtn = self.toolView.subviews[2];
    
            if (setEraseBtn.selected == NO) {
    
                setEraseBtn.selected = YES;
    
                self.lastPaintLineColor = self.paintLineColor;
                self.paintLineColor = self.paintBoardColor;
    
                self.lastPaintLineWidth = self.paintLineWidth;
                self.paintLineWidth = self.paintLineWidth + 5;
            }
        }
    
        /// 退出擦除状态
        - (void)exitEraseState {
    
            UIButton *setEraseBtn = self.toolView.subviews[2];
    
            if (setEraseBtn.isSelected) {
    
                setEraseBtn.selected = NO;
    
                self.paintLineColor = self.lastPaintLineColor;
                self.paintLineWidth = self.lastPaintLineWidth;
            }
        }
    
        #pragma mark - 绘制图案
    
        /// 触摸开始
        - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
            if (self.subviews.count) {
    
                [self hideColorSelectedView];
                [self hideBrushSetingView];
                [self hideBoardSetingView];
            }
    
            // 获取触摸起始点位置
            CGPoint startPoint = [touches.anyObject locationInView:self];
    
            // 添加路径描绘起始点
            [self.path moveToPoint:startPoint];
    
            // 记录线的属性
            self.path.pathColor = self.paintLineColor;
            self.path.pathWidth = self.paintLineWidth;
    
            // 添加一条触摸路径描绘
            [self.pathsArrayM addObject:self.path];
        }
    
        /// 触摸移动
        - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
            // 获取触摸点位置
            CGPoint touchPoint = [touches.anyObject locationInView:self];
    
            // 添加路径描绘
            [self.path addLineToPoint:touchPoint];
    
            // 刷新视图
            [self setNeedsDisplay];
        }
    
        /// 触摸结束
        - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
            // 销毁 path
            self.path = nil;
        }
    
        /// 触摸取消
        - (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event {
            [self touchesEnded:touches withEvent:event];
        }
    
        /// 绘制图形,只要调用 drawRect 方法就会把之前的内容全部清空
        - (void)drawRect:(CGRect)rect {
    
            for (QPaintBoardPath *path in self.pathsArrayM) {
    
                // 绘制路径
                path.lineWidth = path.pathWidth;
                [path.pathColor setStroke];
    
                path.lineCapStyle = kCGLineCapRound;
                path.lineJoinStyle = kCGLineJoinRound;
                [path stroke];
            }
        }
    
        /// 获取绘画结果
        - (UIImage * _Nullable)q_getPaintImage {
    
            UIImage *image = nil;
    
            CGSize boardSize = self.bounds.size;
    
            if (self.subviews.count) {
                boardSize.height = self.bounds.size.height - 44;
            }
    
            if (self.pathsArrayM.count) {
                UIGraphicsBeginImageContextWithOptions(boardSize, NO, 0);
                CGContextRef ctx = UIGraphicsGetCurrentContext();
                [self.layer renderInContext:ctx];
                image = UIGraphicsGetImageFromCurrentImageContext();
                UIGraphicsEndImageContext();
            }
    
            return image;
        }
    
        /// 清除绘画结果
        - (void)q_clear {
    
            if (self.pathsArrayM.count) {
                [self.pathsArrayM removeAllObjects];
    
                [self setNeedsDisplay];
            }
        }
    
        /// 撤销绘画结果
        - (void)q_back {
    
            if (self.pathsArrayM.count) {
                [self.pathsArrayM removeLastObject];
    
                [self setNeedsDisplay];
            }
        }
    
        /// 懒加载
    
        - (QPaintBoardPath * _Nullable)path {
    
            // path 每次绘制完成后需要销毁,否则无法清除之前绘制的路径
    
            if (_path == nil) {
                _path = [QPaintBoardPath bezierPath];
            }
            return _path;
        }
    
        - (NSMutableArray *)pathsArrayM {
    
            if (_pathsArrayM == nil) {
                _pathsArrayM = [NSMutableArray array];
            }
            return _pathsArrayM;
        }
    
        /// 设置属性值
        - (void)setPaintBoardColor:(UIColor *)paintBoardColor {
            _paintBoardColor = paintBoardColor;
            self.backgroundColor = paintBoardColor;
        }
    
        /// 加载 bundle 中的图片
        - (UIImage *)q_getBundleImageWithName:(NSString *)name {
    
            NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"QPaintBoardView.bundle"];
    
            UIImage *image = [[UIImage imageWithContentsOfFile:[bundlePath stringByAppendingPathComponent:name]]
                              imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            return image;
        }
    
        @end
  • 1、创建简单画板

        // 创建简单画板
        CGRect frame = CGRectMake(20, 50, self.view.bounds.size.width - 40, 200);
    
        QPaintBoardView *paintBoardView = [QPaintBoardView q_paintBoardViewWithFrame:frame];
    
        // 可选属性值设置
        paintBoardView.paintLineWidth = 5;                         // default is 1
        paintBoardView.paintLineColor = [UIColor redColor];        // default is blackColor
        paintBoardView.paintBoardColor = [UIColor cyanColor];      // default is whiteColor
    
        [self.view addSubview:paintBoardView];
        self.paintBoardView = paintBoardView;
    
        // 撤销绘画结果
        [self.paintBoardView q_back];
    
        // 清除绘画结果
        [self.paintBoardView q_clear];
    
        // 获取绘画结果
        UIImage *image = [self.paintBoardView q_getPaintImage];
    • 效果

      Quartz2D104Quartz2D105

  • 2、创建画板

        // 创建画板
        QPaintBoardView *paintBoard = [QPaintBoardView q_paintBoardViewWithFrame:self.view.bounds
                                                                       lineWidth:0
                                                                       lineColor:nil
                                                                      boardColor:nil
                                                                     paintResult:^(UIImage * _Nullable image) {
    
            if (image) {
                NSData *data = UIImagePNGRepresentation(image);
                [data writeToFile:@"/Users/JHQ0228/Desktop/Images/pic.png" atomically:YES];
            }
        }];
    
        [self.view addSubview:paintBoard];
    • 效果

      Quartz2D106Quartz2D107

      Quartz2D108Quartz2D109

      Quartz2D110Quartz2D111

目录
相关文章
|
iOS开发
iOS开发-聊天气泡的绘制和聊天消息列表
iOS开发-聊天气泡的绘制和聊天消息列表
275 0
iOS开发-聊天气泡的绘制和聊天消息列表
|
JSON 搜索推荐 Serverless
iOS绘制物理按钮 - 透明圆角渐变边框
iOS绘制物理按钮 - 透明圆角渐变边框
418 0
|
iOS开发 MacOS
IOS之Quartz
IOS之Quartz
166 0
IOS之Quartz
|
iOS开发
iOS开发UI篇 - Quartz 2D简单使用
iOS开发UI篇 - Quartz 2D简单使用
iOS开发UI篇 - Quartz 2D简单使用
|
缓存 编解码 并行计算
iOS 开发:绘制像素到屏幕
像素是如何绘制到屏幕上面的?把数据输出到屏幕的方法有很多,通过调用很多不同的framework和不同的函数。这里我们讲一下这个过程背后的东西。希望能够帮助大家了解什么时候该使用什么API,特别是当遇到性能问题需要调试的时候。当然,我们这里主要讲iOS,但是事实上,很多东西也是可以应用到OSX上面的。
349 0
iOS 开发:绘制像素到屏幕
|
iOS开发
iOS开发UI篇—Quartz2D使用(图形上下文栈)
iOS开发UI篇—Quartz2D使用(图形上下文栈) 一、qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目,自定义一个view类和storyboard关联后,重写该类中的drowrect方法。
744 0
|
iOS开发
iOS开发UI篇—Quartz2D使用(矩阵操作)
iOS开发UI篇—Quartz2D使用(矩阵操作) 一、关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制。 代码: 1 - (void)drawRect:(CGRect)rect 2 { 3 //画四边形 4 //获取图...
729 0
|
图形学 iOS开发 C语言
iOS开发UI篇—Quartz2D使用(绘制基本图形)
iOS开发UI篇—Quartz2D使用(绘制基本图形) 一、简单说明 图形上下文(Graphics Context):是一个CGContextRef类型的数据 图形上下文的作用:保存绘图信息、绘图状态 决定绘制的输出目标(绘制到什么地方去?)(输出目标可以是PDF文件、Bitmap或者显示器的窗口上) 相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上。
771 0
|
计算机视觉 iOS开发
|
API 图形学 iOS开发
IOS开发应用之Quartz 2D学习指南
引用:http://mobile.51cto.com/iphone-284414.htm IOS开发应用之Quartz 2D学习指南是本文要介绍的内容,主要是来学习Quartz 2D的使用方法和操作。
937 0

热门文章

最新文章

  • 1
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    24
  • 2
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    32
  • 3
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    27
  • 4
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 5
    uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
    143
  • 6
    【05】2025年1月首发完整版-篇幅较长-苹果app如何上架到app store完整流程·不借助第三方上架工具的情况下无需花钱但需仔细学习-优雅草央千澈详解关于APP签名以及分发-们最关心的一篇来了-IOS上架app
    232
  • 7
    app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
    90
  • 8
    深入探索iOS开发中的SwiftUI框架
    143
  • 9
    ios样式开关按钮jQuery插件
    58
  • 10
    Android与iOS生态差异深度剖析:技术架构、开发体验与市场影响####
    75