Main.storyboard
下面四个颜色设置在右边的view中background
ViewController.m
//
// ViewController.m
// 6A06.涂鸦
//
// Created by huan on 16/1/30.
// Copyright © 2016年 huanxi. All rights reserved.
//
#import "ViewController.h"
#import "CZPaintView.h"
#import "UIImage+CZ.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CZPaintView *paintView;//画板
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.拖一个view,用于画板
//2.监听触摸的事件,记录触摸的点
//3.根据触摸的点进行绘制
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)back:(id)sender
{
[self.paintView back];
//1.将 数组里 最后一条“线”删除
//2. 重绘
}
-(IBAction)clean:(id)sender{
[self.paintView clear];
}
-(IBAction)save:(id)sender{
//将画板 保存成一张图片
UIImage *captureImage = [UIImage captureImage:self.paintView];
NSData *imgData = UIImagePNGRepresentation(captureImage);
[imgData writeToFile:@"/Users/huan/Desktop/capture.png" atomically:YES];
}
-(IBAction)colorBtnClick:(UIButton *)sender{
//设置paintView当前颜色
self.paintView.currentColor = sender.backgroundColor;
NSLog(@"%s",__func__);
}
@end
CZPaintView.h
#import <UIKit/UIKit.h>
@interface CZPaintView : UIView
@property (nonatomic, strong) UIColor *currentColor;//当前选中的颜色
-(void)back;
-(void)clear;
@end
CZPaintView.m
//
// CZPaintView.m
// 6A06.涂鸦
//
// Created by huan on 16/1/30.
// Copyright © 2016年 huanxi. All rights reserved.
//
#import "CZPaintView.h"
@interface CZPaintView()
/**
* 存储“所有线”的点,数组里面存“一条线”的数组
*/
@property (nonatomic, strong) NSMutableArray *pointOfAllLine;
@property (nonatomic, strong) NSMutableArray *pointOfLine;//一条线上的所有点
/**
* 存储线的颜色 每一条对应里面一个元素
*/
@property (nonatomic, strong) NSMutableArray *colorsOfAllLine;
@end
@implementation CZPaintView
-(NSMutableArray *)colorsOfAllLine{
if (!_colorsOfAllLine) {
_colorsOfAllLine = [NSMutableArray array];
}
return _colorsOfAllLine;
}
-(NSMutableArray *)pointOfAllLine{
if (!_pointOfAllLine) {
_pointOfAllLine = [NSMutableArray array];
}
return _pointOfAllLine;
}
//-(NSMutableArray *)pointOfLine{
// if (!_pointOfLine) {
// _pointOfLine = [NSMutableArray array];
// }
// return _pointOfLine;
//}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
*/
- (void)drawRect:(CGRect)rect {
// Drawing code
//上下文
CGContextRef layerContext = UIGraphicsGetCurrentContext();
//设置线宽
CGContextSetLineWidth(layerContext, 3);
//设置首尾和接点的样式
CGContextSetLineCap(layerContext, kCGLineCapRound);
CGContextSetLineJoin(layerContext, kCGLineJoinRound);
//遍历点进行绘制
// NSInteger count = self.pointOfLine.count;
// for (NSInteger i = 0; i < count; i ++) {
// //获取点
// CGPoint position = [self.pointOfLine[i] CGPointValue];
//
// if (i == 0) {
// CGContextMoveToPoint(layerContext, position.x, position.y);
// }else{
// CGContextAddLineToPoint(layerContext, position.x, position.y);
// }
// }
// //渲染
// CGContextStrokePath(layerContext);
//遍历多少条线
NSInteger lineCount = self.pointOfAllLine.count;
for (NSInteger i = 0; i < lineCount; i ++) {
//取出当前“一条线”的数组
NSArray *pointOfAline = self.pointOfAllLine[i];
//设置颜色
UIColor *lineColor = self.colorsOfAllLine[i];
[lineColor set];
//画线
//取出"线"的“点”的个数进行绘制
NSInteger pointsCount = pointOfAline.count;
for (NSInteger j = 0; j < pointsCount; j++) {
CGPoint point = [pointOfAline[j] CGPointValue];
if (j == 0) {
CGContextMoveToPoint(layerContext, point.x, point.y);
}else{
CGContextAddLineToPoint(layerContext, point.x, point.y);
}
}
//渲染
CGContextStrokePath(layerContext);
}
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//创建一个数组,存放当前“一条线”的点
NSMutableArray *pointsOfAlline = [NSMutableArray array];
//添加到pointsOfAllLine
[self.pointOfAllLine addObject:pointsOfAlline];
//保存当前“一条线”的颜色
if (!self.currentColor) {//为空,给个默认的黑色
[self.colorsOfAllLine addObject:[UIColor blackColor]];
}else{
[self.colorsOfAllLine addObject:self.currentColor];
}
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 2.监听触摸的事件,记录触摸的点
//2.0 给一个属性 保存所有线的点
//获取当前的位置
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:touch.view];
//2.1 获取当前 “一条线”数组 添加 点
NSMutableArray *pointsOfAline = [self.pointOfAllLine lastObject];
[pointsOfAline addObject:[NSValue valueWithCGPoint:touchPoint]];
// [self.pointOfLine addObject:[NSValue valueWithCGPoint:touchPoint]];
//3.根据触摸的点进行绘制
[self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"多少条线 %ld", self.pointOfAllLine.count);
}
-(void)back{
//1.将 数组里 最后一条“线”删除
[self.pointOfAllLine removeLastObject];
//2. 重绘
[self setNeedsDisplay];
}
-(void)clear{
//1.将 数组里 所有的“线”删除
[self.pointOfAllLine removeAllObjects];
//2. 重绘
[self setNeedsDisplay];
}
@end
UIImage + CZ.h
//
// UIImage+CZ.h
// B06.图片水印
//
// Created by Apple on 15/1/2.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (CZ)
/**
*
* @param bgImageName 背景图片
* @param waterImageName 水印图片
* @param scale 图片生成的比例
* @return 添加了水印的背景图片
*/
+(UIImage *)waterImageWithBgImageName:(NSString *)bgImageName waterImageName:(NSString *)waterImageName scale:(CGFloat)scale;
/**
*
* @param imageName 需要裁剪的图片
* @param borderColor 边框的颜色
* @param borderWidth 边框的宽度
* @return 一个裁剪 带有边框的圆形图片
*/
+(UIImage *)circleImageWithImageName:(NSString *)imageName borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;
/**
* @param captureView 需要裁图View
* @return 返回view的图片
*/
+(UIImage *)captureImage:(UIView *)captureView;
@end
//
// UIImage+CZ.m
// B06.图片水印
//
// Created by Apple on 15/1/2.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "UIImage+CZ.h"
@implementation UIImage (CZ)
+(UIImage *)waterImageWithBgImageName:(NSString *)bgImageName waterImageName:(NSString *)waterImageName scale:(CGFloat)scale{
// 生成一张有水印的图片,一定要获取UIImage对象 然后显示在imageView上
//创建一背景图片
UIImage *bgImage = [UIImage imageNamed:bgImageName];
//NSLog(@"bgImage Size: %@",NSStringFromCGSize(bgImage.size));
// 1.创建一个位图【图片】,开启位图上下文
// size:位图大小
// opaque: alpha通道 YES:不透明/ NO透明 使用NO,生成的更清析
// scale 比例 设置0.0为屏幕的比例
// scale 是用于获取生成图片大小 比如位图大小:20X20 / 生成一张图片:(20 *scale X 20 *scale)
//NSLog(@"当前屏幕的比例 %f",[UIScreen mainScreen].scale);
UIGraphicsBeginImageContextWithOptions(bgImage.size, NO, scale);
// 2.画背景图
[bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];
// 3.画水印
// 算水印的位置和大小
// 一般会通过一个比例来缩小水印图片
UIImage *waterImage = [UIImage imageNamed:waterImageName];
#warning 水印的比例,根据需求而定
CGFloat waterScale = 0.4;
CGFloat waterW = waterImage.size.width * waterScale;
CGFloat waterH = waterImage.size.height * waterScale;
CGFloat waterX = bgImage.size.width - waterW;
CGFloat waterY = bgImage.size.height - waterH;
[waterImage drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];
// 4.从位图上下文获取 当前编辑的图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// 5.结束当前位置编辑
UIGraphicsEndImageContext();
return newImage;
}
+(UIImage *)circleImageWithImageName:(NSString *)imageName borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth{
//需求:从位图上下文,裁剪图片[裁剪成圆形,也添加圆形的边框],生成一张图片
// 获取要裁剪的图片
UIImage *img = [UIImage imageNamed:imageName];
CGRect imgRect = CGRectMake(0, 0, img.size.width, img.size.height);
// 1.开启位图上下文
UIGraphicsBeginImageContextWithOptions(img.size, NO, 0.0);
#warning 在自定义的view的drawRect方法里,调用UIGraphicsGetCurrentContext获取的上下文,是图层上下文(Layer Graphics Context)
// 1.1 获取位图上下文
CGContextRef bitmapContext = UIGraphicsGetCurrentContext();
// 2.往位图上下裁剪图片
// 2.1 指定一个圆形的路径,把圆形之外的剪切掉
CGContextAddEllipseInRect(bitmapContext, imgRect);
CGContextClip(bitmapContext);
// 2.2 添加图片
[img drawInRect:imgRect];
// 2.3 添加边框
// 设置边框的宽度
CGContextSetLineWidth(bitmapContext, borderWidth);
// 设置边框的颜色
[borderColor set];
CGContextAddEllipseInRect(bitmapContext, imgRect);
CGContextStrokePath(bitmapContext);
// 3.获取当前位图上下文的图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// 4.结束位图编辑
UIGraphicsEndImageContext();
return newImage;
}
+(UIImage *)captureImage:(UIView *)captureView{
//创建一个位图上下文
UIGraphicsBeginImageContext(captureView.bounds.size);
//把view渲染到位图上下文
[captureView.layer renderInContext:UIGraphicsGetCurrentContext()];
//获取图片
UIImage *captureImg = UIGraphicsGetImageFromCurrentImageContext();
//结束位图的编辑
UIGraphicsEndImageContext();
//返回
return captureImg;
}
@end
如果使用 UIBezierPath
不需要使用到上下文,内部实现(只有CZPaintView.m与上不同,其他相同)
// 1.拖一个view,用于画板
// 2.监听触摸的事件,记录触摸的点
// 3.根据触摸的点进行绘制
//
// CZPaintView.m
// A05.涂鸦
//
// Created by apple on 15-1-2.
// Copyright (c) 2015年 apple. All rights reserved.
//
#import "CZPaintView.h"
@interface CZPaintView()
/**
* 存放所有“线的路径”数组
*/
@property (nonatomic, strong) NSMutableArray *linesPath;
@end
@implementation CZPaintView
-(NSMutableArray *)linesPath{
if (!_linesPath) {
_linesPath = [NSMutableArray array];
}
return _linesPath;
}
/**实现方法:使用UIBezierPath类
一条线 就使用一个 UIBezierPath对象
*0. 需要一个数组 存放UIBerzierPath 对象
*1. 监听move方法
*2. move方法里获取当前“点”添加到UIBezierPath对象
*3. 渲染
*/
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
#warning UIBezierPath 不需要使用到上下文,内部实现
//遍历所有path对象
NSInteger pathCount = self.linesPath.count;
for (NSInteger i = 0; i < pathCount; i++) {
//取path对象
UIBezierPath *path = self.linesPath[i];
//设置线宽、首尾样式、连接样式
path.lineWidth = 3;
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
//画
[path stroke];
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.获取当前的点
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:touch.view];
//创建一个 UIBezierPath对象,添加到数组
UIBezierPath *linePath = [UIBezierPath bezierPath];
[self.linesPath addObject:linePath];
//设置path 起始点
[linePath moveToPoint:touchPoint];
[self.linesPath addObject:linePath];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
//1.获取当前的点
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:touch.view];
//2.添加当前的“点” 到当前的 “线的路径”
UIBezierPath *currentLinepath = [self.linesPath lastObject];
[currentLinepath addLineToPoint:touchPoint];
//3.渲染
[self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
}
-(void)back{
}
-(void)clear{
// 1.将 数组里 "所有线" 删除
}
@end