• IOS简单画板实现


    效果图

     设计要求

     1、画笔能设置大小、颜色

     2、有清屏、撤销、橡皮擦、导入照片功能

     3、能将绘好的画面保存到相册

    实现思路

     1、画笔的实现,我们可以通过监听用户的 平移手势 中创建 UIBezierPath 来实现线条的绘制

     2、撤销功能,我们先来看下撤销功能,我们会想到用一个数组队列将用户的每一次的笔画都加入到数组中,然后撤销的时候只需要将最后添加进去的笔画pop掉,重新绘制就可以了

     3、清屏功能就简单了,只需要将上面说到的那个数组清空重新绘制下就可以了

     4、导入照片功能,可以用系统的 UIImagePickerController 选取照片得到UIImage,然后再将 UIImage 绘制到屏幕中就可以了

     5、保存到相册功能,可以使用 UIGraphicsGetImageFromCurrentImageContext 获取当前的图片上下文,得到屏幕画面的 UIImage ,然后通过 UIImageWriteToSavedPhotosAlbum 写入到相册

    具体代码实现

     1、先画个界面

    2、因为我们绘制线条会用到 UIBezierPath ,并且要能可设置颜色,但是UIBezierPath是没有设置颜色的属性,所以我们这里需要简单扩展一下,创建一个继承于 UIBezierPath 的子类 DrawPath

    //
    //  DrawPath.h
    //  画板
    //
    //  Created by xgao on 16/4/13.
    //  Copyright © 2016年 xgao. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface DrawPath : UIBezierPath
    
    // 画笔颜色 @property(nonatomic,retain)UIColor
    * pathColor; @end

    这个子类只需要扩展一个属性,就是 pathColor 用来保存画笔的颜色

    //
    //  DrawPath.m
    //  画板
    //
    //  Created by xgao on 16/4/13.
    //  Copyright © 2016年 xgao. All rights reserved.
    //
    
    #import "DrawPath.h"
    
    @implementation DrawPath
    
    @end

    DrawPath.m 里面不需要做其它功能

    3、接到来我们对画板功能的实现封装一下,创建一个继承于UIView的 DrawView子类

    //
    //  DrawView.h
    //  画板
    //
    //  Created by xgao on 16/4/13.
    //  Copyright © 2016年 xgao. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface DrawView : UIView
    
    // 画线的宽度
    @property(nonatomic,assign)CGFloat lineWidth;
    
    // 线条颜色
    @property(nonatomic,retain)UIColor* pathColor;
    
    // 加载背景图片
    @property(nonatomic,strong)UIImage* image;
    
    // 清屏
    - (void)clear;
    
    // 撤销
    - (void)undo;
    
    // 橡皮擦
    - (void)eraser;
    
    // 保存
    - (void)save;
    
    @end
    //
    //  DrawView.m
    //  画板
    //
    //  Created by xgao on 16/4/13.
    //  Copyright © 2016年 xgao. All rights reserved.
    //
    
    #import "DrawView.h"
    #import "DrawPath.h"
    
    @interface DrawView()
    
    @property(nonatomic,strong) DrawPath* path;
    
    // 线的数组
    @property(nonatomic,strong) NSMutableArray* paths;
    
    @end
    
    @implementation DrawView
    
    - (void)awakeFromNib{
    
        [self setUp];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self setUp];
        }
        return self;
    }
    
    // 重绘UI
    - (void)drawRect:(CGRect)rect {
        
        for (DrawPath* path in self.paths) {
            
            if ([path isKindOfClass:[UIImage class]]) {
                // 画图片
                UIImage* image = (UIImage*)path;
                [image drawInRect:rect];
            }else{
                // 画线
                
                // 设置画笔颜色
                [path.pathColor set];
                
                // 绘制
                [path stroke];
            }
        }
    }
    
    // 懒加载属性
    - (NSMutableArray*)paths{
        
        if (_paths == nil) {
            _paths = [NSMutableArray array];
        }
        return _paths;
    }
    
    // 重写image属性
    - (void)setImage:(UIImage *)image{
    
        _image = image;
        
        // 将图片加入到线条数组中
        [self.paths addObject:image];
        
        [self setNeedsDisplay];
    }
    
    #pragma mark - Init
    
    // 初始化
    - (void)setUp{
        
        // 添加平移手势
        UIPanGestureRecognizer* panGes = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGes:)];
        [self addGestureRecognizer:panGes];
        
        // 默认值
        self.lineWidth = 1;
        self.pathColor = [UIColor blackColor];
    }
    
    #pragma mark - Event
    
    // 平移事件
    - (void)panGes:(UIPanGestureRecognizer*)ges{
        
        // 获取当前点
        CGPoint curPoint = [ges locationInView:self];
        
        if (ges.state == UIGestureRecognizerStateBegan) { // 开始移动
            
            // 创建贝塞尔曲线
            _path = [[DrawPath alloc]init];
            
            // 设置线条宽度
            _path.lineWidth = _lineWidth;
    
            // 线条默认颜色
            _path.pathColor = _pathColor;
            
            // 设置起始点
            [_path moveToPoint:curPoint];
            
            [self.paths addObject:_path];
        }
        
        // 连线
        [_path addLineToPoint:curPoint];
        
        // 重绘
        [self setNeedsDisplay];
    }
    
    #pragma mark - Method
    
    // 清屏
    - (void)clear{
        
        [self.paths removeAllObjects];
        
        [self setNeedsDisplay];
    }
    
    // 撤销
    - (void)undo{
        
        [self.paths removeLastObject];
        
        [self setNeedsDisplay];
    }
    
    // 橡皮擦
    - (void)eraser{
        
        self.pathColor = [UIColor whiteColor];
        
        [self setNeedsDisplay];
    }
    
    // 保存
    - (void)save{
        
        // ---- 截图操作
        // 开启上下文
        UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0);
        
        // 获取当前上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        // 渲染图层到上下文
        [self.layer renderInContext:context];
        
        // 从上下文中获取图片
        UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
        
        // 关闭上下文
        UIGraphicsEndImageContext();
        
        // ---- 保存图片
        UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
        
    }
    
    // 图片保存方法,必需写这个方法体,不能会保存不了图片
    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
        
        // 提示
        UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"保存成功" message:nil delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
        [alert show];
    }
    
    @end

    4、接下来就是如果使用这个画板类了,直接上代码吧

    //
    //  ViewController.m
    //  画板
    //
    //  Created by xgao on 16/4/13.
    //  Copyright © 2016年 xgao. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "DrawView.h"
    
    @interface ViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
    
    // 画板
    @property (weak, nonatomic) IBOutlet DrawView *drawView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
    }
    
    #pragma mark - Event
    
    // 线条宽度变化
    - (IBAction)lineWidthChange:(UISlider*)sender {
        
        _drawView.lineWidth = sender.value;
    }
    
    // 线条颜色变化
    - (IBAction)pathColorChange:(UIButton*)sender {
        
        _drawView.pathColor = sender.backgroundColor;
    }
    
    
    // 清屏
    - (IBAction)clearAction:(id)sender {
    
        [_drawView clear];
    }
    
    // 撤销
    - (IBAction)undoAction:(id)sender {
    
        [_drawView undo];
    }
    
    // 橡皮擦
    - (IBAction)eraserAction:(id)sender {
    
        [_drawView eraser];
    }
    
    // 照片
    - (IBAction)pickerPhotoAction:(id)sender {
        
        // 照片选择控制器
        UIImagePickerController* picVC = [[UIImagePickerController alloc]init];
        // 照片源
        picVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        // 委托
        picVC.delegate = self;
        
        [self presentViewController:picVC animated:YES completion:nil];
    }
    
    // 保存
    - (IBAction)saveAction:(id)sender {
        
        [_drawView save];
    }
    
    #pragma mark - UIImagePickerControllerDelegate
    
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo{
        
        // 设置图片
        _drawView.image = image;
        
        // 关闭窗口
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    @end

    到这里就差不多了,这个小功能实现的基本思路与具体代码我都已经放上来了,大家如果还有哪里不清楚的可以留言喔~~

  • 相关阅读:
    transform 多值先后执行顺序
    css 清除浮动
    鼠标移动到图片,图片放大
    js 事件循环机制EventLoop
    web安全
    web前端踩坑记录
    滚动加载图片(懒加载)
    css 兼容问题
    模块化 AMD与CMD 规范
    css 盒子模型 ie盒子模型
  • 原文地址:https://www.cnblogs.com/xgao/p/6650225.html
Copyright © 2020-2023  润新知