IOS画图

首先说明一下要求,知道了要求之后才能更好地工作呢。

1、通过滑动滑块来修改画笔的粗细;最小值为4,最大值为15;UISlider;

2、点击撤销按钮后,绘图区域撤销上一次画线操作;

3、点击保存按钮后,将绘图区域的图片按照顺序保存到上方的视图中;UIImageView;

4、保存的图片大于6张后,继续从第一个视图按照顺序往下保存;

5、每次点击按钮后,还要将绘制的图片保存到iOS相册内; 可以通过UIImageWriteToPhotosAlbum函数保存到图片相册,保存成功后可以在iPhone模拟器的照片应用程序中查看

 

首先创建工程,single view Application

先说说思路:

1.将界面给布置好,图片1——6的位置为UIImageView,"撤销"“保存",是两个UIButton,中间是一个UISlider,下面绘图区是一个UIView

2.当点击保存的时候,会弹出对话框,提示是否进行保存,如果保存就将绘图区的图片保存到上面同时保存的本地的照片库中,如果点击取消,则不进行保存

3.写保存,撤销按钮点击事件,(NSLog(@"hello");)进行界面测试

4.对绘图区进行书写,进行绘图。

5.绘图区应该是在外面是一个自己创建的继承与UIView的View

6.在绘图区的操作:

  6.1.重写

  - (void)drawRect:(CGRect)rect;方法

  首先是重写父视图的drawRect:rect方法;

  6.2.添加

  - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;方法

  6.3.添加

  - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;方法

  6.4.将每一次画得图保存为一个image,添加方法

  - (UIImage *)getImageFromCurrentContext;即得到当前视图的截图

  6.5.

画图过程应该是:每一次触摸屏幕的开始,就是一个触摸路径的开始,然后开始绘制,在绘制的过程中,只要绘制就会调用touchesMoved:方法

,同时对图片进行调用[self setNeedsDisplayInrect:rect];程序就会跳转到drawRect:方法中,对图片进行绘制。

根据上面的思路,来进行工作的实施。

首先是界面:

在viewController.m 文件中书写代码:

#import "ViewController.h"
#import "CustomView.h"
#import "CustomManager.h"
#import "CustomPath.h"

@interface ViewController ()
{
    NSInteger  imageCount;
}
@end

@implementation ViewController
#pragma mark---------------------------------------viewDidLoad
- (void)viewDidLoad
{
    [super viewDidLoad];
//后面的白板容器视图
    imageCount = 0;
	UIView * containerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
    containerView.backgroundColor = [UIColor whiteColor];
    containerView.tag = 0;
    [self.view addSubview:containerView];
//上面的文字视图
    UIView * titleView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 64)];
    [containerView addSubview:titleView];
//保存和撤销按钮
    UIButton * cancelButton = [[UIButton alloc]initWithFrame:CGRectMake(10, 0, 50, 40)];
    [cancelButton setTitle:@"撤销" forState:UIControlStateNormal];
    [cancelButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [cancelButton addTarget:self action:@selector(didClickCancelButton:) forControlEvents:UIControlEventTouchUpInside];
    cancelButton.backgroundColor = [UIColor grayColor];
    
    UIButton * saveButton = [[UIButton alloc]initWithFrame:CGRectMake(260, 0, 50, 40)];
    [saveButton setTitle:@"保存" forState:UIControlStateNormal];
    [saveButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [saveButton addTarget:self action:@selector(didClickSaveButton:) forControlEvents:UIControlEventTouchUpInside];
    saveButton.backgroundColor = [UIColor grayColor];
    
    [containerView addSubview:cancelButton];
    [containerView addSubview:saveButton];
//添加划线空间
    UISlider * slider = [[UISlider alloc]initWithFrame:CGRectMake(70, 0, 150, 0)];
    [titleView addSubview:slider];
    slider.minimumValue = 4.0f;
    slider.maximumValue = 15.0f;
    [slider addTarget:self action:@selector(changeSliderValue:) forControlEvents:UIControlEventValueChanged];
    
    
//添加6个UIImageView
    UIView * sixContainerView = [[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 215)];
    sixContainerView.backgroundColor = [UIColor greenColor];
    sixContainerView.tag = 3;
    [containerView addSubview:sixContainerView];
    
    UIImageView * firstImage = [[UIImageView alloc]initWithFrame:CGRectMake(5, 5, 100, 100)];
    UIImageView * secondImage = [[UIImageView alloc]initWithFrame:CGRectMake(110, 5, 100, 100)];
    UIImageView * thirdImage = [[UIImageView alloc]initWithFrame:CGRectMake(215, 5, 100, 100)];
    UIImageView * forthImage = [[UIImageView alloc]initWithFrame:CGRectMake(5, 110, 100, 100)];
    UIImageView * fifthImage = [[UIImageView alloc]initWithFrame:CGRectMake(110, 110, 100, 100)];
    UIImageView * sixthImage = [[UIImageView alloc]initWithFrame:CGRectMake(215, 110, 100, 100)];

    firstImage.backgroundColor = [UIColor grayColor];
    secondImage.backgroundColor = [UIColor grayColor];
    [thirdImage setBackgroundColor:[UIColor grayColor]];
    forthImage.backgroundColor = [UIColor grayColor];
    fifthImage.backgroundColor = [UIColor grayColor];
    sixthImage.backgroundColor = [UIColor grayColor];
    firstImage.tag = 1001;
    secondImage.tag = 1002;
    thirdImage .tag = 1003;
    forthImage.tag = 1004;
    fifthImage .tag = 1005;
    sixthImage.tag = 1006;
    firstImage.userInteractionEnabled = YES;
    secondImage.userInteractionEnabled = YES;
    thirdImage.userInteractionEnabled = YES;
    forthImage.userInteractionEnabled = YES;
    fifthImage.userInteractionEnabled = YES;
    sixthImage.userInteractionEnabled = YES;
    [firstImage clearsContextBeforeDrawing];
    [sixContainerView addSubview:firstImage];
    [sixContainerView addSubview:secondImage];
    [sixContainerView addSubview:thirdImage];
    [sixContainerView addSubview:forthImage];
    [sixContainerView addSubview:fifthImage];
    [sixContainerView addSubview: sixthImage];
    
//添加颜色选择
    UIButton * redButton = [[UIButton alloc]initWithFrame:CGRectMake(30, 270, 25, 10)];
    redButton.backgroundColor = [UIColor redColor];
    [redButton addTarget:self action:@selector(didClickRedButton:) forControlEvents:UIControlEventTouchUpInside];
    UIButton * greenButton = [[UIButton alloc]initWithFrame:CGRectMake(150, 270, 25, 10)];
    [greenButton setBackgroundColor:[UIColor greenColor]];
    [greenButton addTarget:self action:@selector(didClickGreenButton:) forControlEvents:UIControlEventTouchUpInside];
    UIButton * blueButton = [[UIButton alloc]initWithFrame:CGRectMake(260, 270, 25, 10)];
    blueButton.backgroundColor = [UIColor blueColor];
    [blueButton addTarget:self action:@selector(didClickBlueButton:) forControlEvents:UIControlEventTouchUpInside];
    
    [containerView addSubview:redButton];
    [containerView addSubview:greenButton];
    [containerView addSubview:blueButton];
//添加画板视图
    CustomView * cView = [[CustomView alloc]initWithFrame:CGRectMake(5, 280, 310, 210)];
    cView.backgroundColor= [UIColor grayColor];
    cView.tag = 1;
    [containerView addSubview:cView];
}

  当点击保存按钮和撤销按钮,进行相应地事件的触发,当跳出一个提示框后进行的操作:

#pragma mark---------------------------------------alertView
- (void)alertView:(UIAlertView *)alertViewt clickedButtonAtIndex:(NSInteger)buttonIndex

{
    UIView * containerView = [self.view viewWithTag:0];
    CustomView * cView = (CustomView *) [containerView viewWithTag:1];
    
    NSMutableArray * pathListArray =  [CustomManager defaultManager].pathList;
    UIView * sixContainerView = [containerView viewWithTag:3];
    NSArray * array = [sixContainerView subviews];
    UIImage * tempImage = [cView getImageFromCurrentContext];
    
    switch (buttonIndex) {
        case 0:
        {
            [pathListArray removeAllObjects];
            [cView setNeedsDisplay];
        }
            NSLog(@"取消");
            break;
        case 1:
        {
            UIImageWriteToSavedPhotosAlbum(tempImage, NULL, NULL, NULL);
            imageCount++;
            switch (imageCount) {
                case 1:
                    ((UIImageView *)array[0]).image = tempImage;
                    break;
                case 2:
                    ((UIImageView *)array[1]).image = tempImage;
                    break;
                case 3:
                    ((UIImageView *)array[2]).image = tempImage;
                    break;
                case 4:
                    ((UIImageView *)array[3]).image = tempImage;
                    break;
                case 5:
                    ((UIImageView *)array[4]).image = tempImage;
                    break;
                case 6:
                    ((UIImageView *)array[5]).image = tempImage;
                    break;
                default:
                    break;
            }
            [pathListArray removeAllObjects];
            [cView setNeedsDisplay];
        }
            NSLog(@"确定");
            break;
    }
}


#pragma mark---------------------------------------changeSliderValue:
- (void) changeSliderValue:(UISlider *)sender
{
    UIView * containerView = [self.view viewWithTag:0];
    CustomView * cView = (CustomView *)[containerView viewWithTag:1];
    cView.lineWidth = sender.value;
    NSLog(@"%f",sender.value);
}
#pragma mark---------------------------------------didClickSaveButton:
- (void) didClickSaveButton:(UIButton *)sender
{
    if (imageCount > 5) {
        imageCount = 0;
    }
    UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"是否保存" message:@"要保存吗?" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
    [alert show];
    
    NSLog(@"save click");
    
}



#pragma mark---------------------------------------didClickCancelButton:
- (void) didClickCancelButton:(UIButton *)sender
{
    UIView * containerView = [self.view viewWithTag:0];
    CustomView * cView = (CustomView *) [containerView viewWithTag:1];
    
    NSMutableArray * pathListArray =  [CustomManager defaultManager].pathList;
    [pathListArray removeLastObject];
    [cView setNeedsDisplay];
 
    NSLog(@"cancel click");
}

#pragma mark---------------------------------------didClickBlueButton:
- (void) didClickBlueButton:(UIButton *)sender
{
    UIView * containerView = [self.view viewWithTag:0];
    CustomView * cView = (CustomView *) [containerView viewWithTag:1];
    cView.lineColor = [UIColor blueColor];
    
    
    NSLog(@"blue");
}
#pragma mark---------------------------------------didClickRedButton:
- (void) didClickRedButton:(UIButton *)sender
{
    UIView * containerView = [self.view viewWithTag:0];
    CustomView * cView = (CustomView *) [containerView viewWithTag:1];
    cView.lineColor = [UIColor redColor];
    NSLog(@"red");
}
#pragma mark---------------------------------------didClickGreenButton:
- (void) didClickGreenButton:(UIButton *)sender
{
    UIView * containerView = [self.view viewWithTag:0];
    CustomView * cView = (CustomView *) [containerView viewWithTag:1];
    cView.lineColor = [UIColor greenColor];
    NSLog(@"green");
}
#pragma mark---------------------------------------didReceiveMemoryWarning
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}
@end 

创建一个单例:用来存储每一条路径的信息。一个数组。这个数组中得元素是一个另外一个类的每一个对象,另外一个类是linpath类。

在这个类中保存着每一个对象的所有数据,(线的路径,线的宽度,线的颜色)。

然后再drawRect:方法中for (in)这个单例中那个数组的所有元素,遍历出后,进行绘画和渲染。

 在这里,我们分别实现各个方法,

首先创建一个CustomView,用来进行绘图:绘图代码:

首先是CustomView.h文件中得声明:

#import <UIKit/UIKit.h>

@interface CustomView : UIView
@property (nonatomic,retain) UIColor* lineColor;
- (CGMutablePathRef) pathFromPoint:(CGPoint)originPoint toPoint:(CGPoint) finalPoint;
- (UIImage *)getImageFromCurrentContext;

@property (nonatomic,assign)float lineWidth;
@end

  然后是CustomView.m文件中各个方法的实现。

#import "CustomView.h"
#import "CustomManager.h"
#import "CustomPath.h"
//添加自定义视图的延展...
@interface CustomView ()

//获取坐标内的路径...
//- (CGMutablePathRef) pathFromPoint:(CGPoint)originPoint toPoint:(CGPoint) finalPoint;
//- (UIImage *)getImageFromCurrentContext;
@end
//静态内联函数
//程序启动后,这种类型的函数就已经准备完毕,在代码区准备程序内调用
static inline CGPoint midPoint(CGPoint point1,CGPoint point2)
{
    CGFloat minX = (point1.x + point2.x)/2.0f;
    CGFloat minY = (point2.y + point2.y)/2.0f;
    return CGPointMake(minX, minY);
}
@implementation CustomView
{
    //添加私有地实例变量
    //启动点...
    CGPoint startPoint;
    //结束点...
    CGPoint endPoint;
    //控制点
    CGPoint controlPoint;
    UIImage *tempImage;
    
    //声明路径私有地中间变量
    CGMutablePathRef tempPath;
    
    //声明每一次触摸完成后的路径
    CGMutablePathRef touchPath;
    
    //声明全部路径变量,用来存储所有的中间路径.....
    CGMutablePathRef totalPath;
    
    
}
#pragma mark---------------------------------------初始化
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        startPoint = CGPointZero;
        endPoint = CGPointZero;
        controlPoint = CGPointZero;
        //创建全部路径对象存储空间
//        totalPath = CGPathCreateMutable();
        _lineColor = [UIColor whiteColor];
    }
    return self;
}
#pragma mark---------------------------------------开始画 drawRect:

- (void)drawRect:(CGRect)rect
{
    //通知父类,开始画图....
   [super drawRect:rect];
    
    //如果两个都是(0,0),则不画图...
    if (CGPointEqualToPoint(startPoint, CGPointZero) && CGPointEqualToPoint(endPoint,CGPointZero)) {
        return;
    }
    
    //1.获取当前画布...
    CGContextRef context = UIGraphicsGetCurrentContext();//context 就是传过来的rect
    NSMutableArray * pathListArray =  [CustomManager defaultManager].pathList;
    
    for (CustomPath * itemPath in pathListArray) {
        
        CGContextSetLineCap(context, kCGLineCapRound);
        CGContextSetLineWidth(context, itemPath.lineWidth);
        
        CGContextSetStrokeColorWithColor(context, itemPath.lineColor);
        
        CGContextAddPath(context, itemPath.linePath);
        
        CGContextStrokePath(context);
        
    }
    
    
    /**/
    //1.开始创建图片画布

    /**/
    
    
    
    
}

#pragma mark---------------------------------------touchBegan
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //每一次触摸屏幕的开始,就是一个触摸路径的开始.....
    touchPath = CGPathCreateMutable();
    CustomPath * itemPath = [[CustomPath alloc]init];
    itemPath.lineWidth =_lineWidth;
    itemPath .lineColor = _lineColor.CGColor;
    itemPath.linePath = touchPath;
    [[CustomManager defaultManager].pathList addObject:itemPath];
    //获取触摸对象
    UITouch * touch = [touches anyObject];
    //设置每次触摸的点
    startPoint = [touch previousLocationInView:self];
    endPoint = [touch previousLocationInView:self];
    controlPoint =[touch previousLocationInView:self];
    [self touchesMoved:touches withEvent:event];
}
#pragma mark---------------------------------------touchesMoved
//当手指开始触摸得时候,实现的方法...
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    //获取当前的触摸对象
    UITouch * touch = [touches anyObject];
    //设置起点
    startPoint = controlPoint;
    //设置控制点为前一个触摸点
    controlPoint = [touch previousLocationInView:self];
    //设置中点为当前触摸点
    endPoint = [touch locationInView:self];
    
    //生成截图图片对象...
//    tempImage = [self getImageFromCurrentContext];
    
    CGPoint mid1 = midPoint(startPoint,controlPoint);
    CGPoint mid2 = midPoint(controlPoint, endPoint);
    //获取当前应该绘制的路径
    tempPath = [self pathFromPoint:mid1 toPoint:mid2];
    //获取最小的能够容纳路径的矩形体积
    CGRect rect = CGPathGetBoundingBox(tempPath);
    rect.origin.x -=15.0f;
    rect.origin.y -=15.0f;
    rect.size.height +=30.0f;
    rect.size.width +=30.0f;
    
    //将中间变量tempPath添加到全部路径
//    CGPathAddPath(totalPath, NULL, tempPath);
    //将中间变量tempPath添加到每一个的触摸路径touchPath内
    CGPathAddPath(touchPath, NULL, tempPath);
    //修改最后的自定义的path对象
    CustomPath * itemPath = [[CustomManager defaultManager].pathList lastObject];
    itemPath.linePath = touchPath;
    
    //这里的self是实例对象
    [self setNeedsDisplayInRect:rect];
}
#pragma mark---------------------------------------touchesEnded
//当手指结束触摸时,触发的方法
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    CustomPath * itemPath = [[CustomPath alloc]init];
    itemPath.linePath = touchPath;
}

//获取当前视图的截图....
#pragma mark---------------------------------------画图

- (UIImage *)getImageFromCurrentContext
{
    //1.开始创建图片画布
    UIGraphicsBeginImageContext(self.bounds.size);
    //2.将视图的内容渲染到图片画布上
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    //3.通过图片画布获取当前画布...
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    //4.结束图片画布
    UIGraphicsEndImageContext();
    return result;
}


#pragma mark---------------------------------------获取坐标内路径
//获取坐标内的路径...
- (CGMutablePathRef) pathFromPoint:(CGPoint)originPoint toPoint:(CGPoint) finalPoint
{
    //创建块
    CGMutablePathRef path = CGPathCreateMutable();
    //移动到出发点
    CGPathMoveToPoint(path, NULL, originPoint.x, originPoint.y);
    //添加直线结束点
//    CGPathAddLineToPoint(path,NULL , finalPoint.x, finalPoint.y);
    
    
    //添加曲线,通过控制点,到结束点
    CGPathAddQuadCurveToPoint(path, NULL, controlPoint.x, controlPoint.y, finalPoint.x, finalPoint.y);

    
    //CGPathRef,CGContextRef,CGColorRef
    //的基本类型都是CFtypeRef类型的
    //而ARC不支持此类型的自动释放
    
    //将cgpathref对象添加到自动释放池
    CFAutorelease(path);
    //将路径返回
    return path ;
}


@end

  

附件:

该程序的例子:

文件存到网盘了。百度网盘。

原文地址:https://www.cnblogs.com/yinyakun/p/3428309.html