iOS笔记053- Quartz2D-练习
1、水印处理
给图片添加文字、图片水印
// 水印处理
- (void)shuiyin
{
// 水印处理
UIImage *image = [UIImage imageNamed:@"4"];
UIImage *image2 = [UIImage imageNamed:@"010"];
CGFloat imageH = image.size.height;
CGFloat imageW = image.size.width;
// 获取位图上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
// 绘制图形或者文字
[image drawAtPoint:CGPointZero];
NSString *str = @"@zhang@163.com";
CGFloat strlenth = str.length * 8;
// 文字水印
[str drawAtPoint:CGPointMake(imageW - strlenth, imageH - 44) withAttributes:nil];
// 图片水印
[image2 drawAtPoint:CGPointMake(imageW - strlenth - 66, imageH - 66)];
// 关闭位图上下文
UIGraphicsEndPDFContext();
// 获取位图
_imageView.image = UIGraphicsGetImageFromCurrentImageContext();
// 保存图片,需要转换成二进制数据
NSData *data = UIImageJPEGRepresentation(_imageView.image, 1); // 参数2表示图片质量
NSData *data1 = UIImagePNGRepresentation(_imageView.image); // png默认最高质量
// 写入文件
[data1 writeToFile:@"/Users/song/Desktop/me.png"atomically:YES];
}
2、图形裁切
首先设置一个裁切区域,然后在裁切区域显示图片。
// 图形裁切
- (void)clipImage
{
// 获取图片
UIImage *image = [UIImage imageNamed:@"4"];
// 获取位图上下文
UIGraphicsBeginImageContextWithOptions(image.size,NO,0.0);
// 设置圆形裁剪区域,正切与图片
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
// 添加裁切区域
[path addClip];
// 绘制图片
[ima drawAtPoint:CGPointZero];
// 从上下文获取图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭位图上下文
UIGraphicsEndImageContext();
// 显示位图
_imageView.image = image;
}
带边框的圆形裁切
首先绘制一个红色的圆,然后在圆中心绘制图片,保留一定的边框。
// 带边框的原型裁切
- (void)cicleAroundImage
{
// 1、绘制一个大圆,设置背景色
// 获取图片
UIImage *ima = [UIImage imageNamed:@"4"];
// 图片宽高
CGFloat imageW = ima.size.width;
// 边界宽度
CGFloat boarder = 3;
// 圆环宽高
CGFloat cicleW = imageW + 2 * boarder;
// 获取位图上下文
UIGraphicsBeginImageContextWithOptions(CGSizeMake(cicleW, cicleW),NO,0.0);
// 绘制圆形
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, cicleW, cicleW)];
// 填充红色
[[UIColor redColor] set];
[path fill];
// 2、绘制图片,要比大圆小一点
UIBezierPath *clipArea = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(boarder , boarder, imageW, imageW)];
// 裁切
[clipArea addClip];
// 绘制图片
[ima drawAtPoint:CGPointMake(boarder, boarder)];
// 从上下文获取图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭位图上下文
UIGraphicsEndImageContext();
// 显示位图
_imageView.image = image;
}
带有边框的裁切可以使用一个分类
#import "UIImage+image.h"
@implementation UIImage (image)
+ (instancetype) imageWithImage:(UIImage *)image withBoard:(CGFloat )board withColor:(UIColor *)color
{
// 1、绘制一个大圆,设置背景色
// 获取图片
UIImage *ima = image;
// 图片宽高
CGFloat imageW = ima.size.width;
// 边界宽度
CGFloat boarder = board;
// 圆环宽高
CGFloat cicleW = imageW + 2 * boarder;
// 获取位图上下文
UIGraphicsBeginImageContextWithOptions(CGSizeMake(cicleW, cicleW),NO,0.0);
// 绘制圆形
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, cicleW, cicleW)];
// 填充红色
[color set];
[path fill];
// 2、绘制图片,要比大圆小一点
UIBezierPath *clipArea = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(boarder , boarder, imageW, imageW)];
// 裁切
[clipArea addClip];
// 绘制图片
[ima drawAtPoint:CGPointMake(boarder, boarder)];
// 从上下文获取图片
UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
// 关闭位图上下文
UIGraphicsEndImageContext();
// 显示位图
return clipImage;
}
@end
使用起来也方便,直接包含头文件即可使用
#import "ViewController.h"
#import "UIImage+image.h"
@interfaceViewController ()
@property (weak, nonatomic) IBOutletUIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 使用分类
UIImage *ima = [UIImage imageWithImage:[UIImage imageNamed:@"4"] withBoard:3 withColor:[UIColor blueColor]];
_imageView.image = ima;
}
3、屏幕截图
主要是从控制器上获取图层。一定要使用 renderInContext: 进行渲染,不可使用draw...
// 屏幕截图
- (void)snipImage
{
//获取位图上下文
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
// 获取当前上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 渲染控制器图层到图形上下文,把控件上的图层渲染到上下文,layer只能渲染
[self.view.layer renderInContext:ctx];
// 获取图形上下文
UIImage *snipImage = UIGraphicsGetImageFromCurrentImageContext();
// 关闭位图上下文
UIGraphicsEndImageContext();
NSData *data = UIImagePNGRepresentation(snipImage);
[data writeToFile:@"/Users/song/Desktop/snip.png"atomically:YES];
}
4、手势解锁
效果
4.1、界面
在storyboard里添加一个view用来显示九宫格
4.2、新建一个类继承自UIView
添加按钮
// 添加按钮
- (void)awakeFromNib
{
[super awakeFromNib];
// 创建按钮
for (NSInteger i = 0; i < 9; i ++)
{
UIButton *btn = [UIButtonbuttonWithType:UIButtonTypeCustom];
[btn setBackgroundImage:[UIImageimageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImageimageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
btn.userInteractionEnabled = NO;
btn.tag = i;
[self addSubview:btn];
}
}
设置按钮frame
// 九宫格按钮计算
- (void)layoutSubviews
{
[super layoutSubviews];
// 按钮个数
NSInteger count = self.subviews.count;
// 按钮宽度和高度
CGFloat x = 0;
CGFloat y = 0;
CGFloat w = 74;
CGFloat h = 74;
// 行
NSInteger cols = 3;
// 列
NSInteger rows = 3;
// 间距
CGFloat margin = (self.bounds.size.width - cols * w)/(cols + 1);
// 设置frame
for (NSInteger i = 0; i < count; i ++)
{
UIButton *btn = (UIButton *)self.subviews[i];
// 当前行
NSInteger row = i / rows;
// 当前列
NSInteger col = i % cols;
// x
x = margin + col * (margin + w);
// y
y = row * (margin + h);
btn.frame = CGRectMake(x, y, w, h);
}
}
定义一个可变数组用来保存选中按钮
@property (nonatomic,strong) NSMutableArray *selectedBtn;
- (NSMutableArray *)selectedBtn
{
if (_selectedBtn == nil) {
_selectedBtn = [NSMutableArray array];
}
return _selectedBtn;
}
实现滑动手势方法
- (IBAction)pan:(UIPanGestureRecognizer *)sender {
// NSLog(@"pan");
// 获取触摸点
_curP = [sender locationInView:self];
// 遍历按钮数组
for (UIButton *btn in self.subviews) {
// 判断点是否包含在按钮中
if (CGRectContainsPoint(btn.frame, _curP) && !btn.selected ) {
btn.selected = YES;
[self.selectedBtn addObject:btn];
}
}
// 重绘
[self setNeedsDisplay];
// 恢复原状
if (sender.state == UIGestureRecognizerStateEnded ) {
// 保存密码
NSMutableString *str = [NSMutableStringstring];
for (UIButton *btn in self.selectedBtn) {
[ str appendFormat:@"%ld",btn.tag ];
}
NSLog(@"%@",str);
// 删除选中状态
[self.selectedBtn makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
// 情况选中数组
[self.selectedBtn removeAllObjects];
}
}
然后在drawRect中进行连线
- (void)drawRect:(CGRect)rect
{
// 没有选中按钮,直接退出
if (self.selectedBtn.count == 0) {
return;
}
// 把所有选中的按钮连线
NSInteger count = self.selectedBtn.count;
UIBezierPath *path = [UIBezierPathbezierPath];
// 遍历选中按钮数组,对按钮连线
for (int i = 0 ; i < count ; i ++) {
UIButton *btn = self.selectedBtn[i];
if (i == 0) {
// 设置起点
[path moveToPoint:btn.center];
}else
{
[path addLineToPoint:btn.center];
}
}
// 连接到当前点
[path addLineToPoint:_curP];
// 设置连线样式
[[UIColorgreenColor] set];
path.lineWidth = 10;
path.lineJoinStyle = kCGLineJoinRound;
[path stroke];
}
5、画板
5.1、通过自动布局搭建界面
5.2、在自定义view中得实现
使用滑动手势进行画线
自定义一个继承自UIBezierPath 的类,用来改变线条的颜色,只需添加一个属性即可
#import <UIKit/UIKit.h>
@interface drawPath : UIBezierPath
@property (nonatomic,strong) UIColor *lineColor;
@end
自定义一个view封装画板的操作 DrawView
#import <UIKit/UIKit.h>
@classdrawPath;
@interface DrawView : UIView
@property (nonatomic, strong) UIColor *lineColor; // 线条颜色
@property (nonatomic,assign) CGFloat lineWidth; // 线条宽度
@property (nonatomic,strong) UIImage *image; // 保存加载的图片
- (void)eraseScreen; // 清屏
- (void)undo; // 撤销
@end
类扩展中添加两个属性
#import "DrawView.h"
#import "drawPath.h"
@interfaceDrawView ()
@property (nonatomic,strong) drawPath *path; // 绘图路径
@property (nonatomic,strong) NSMutableArray *drawLines; // 路径数组
@end
// 数组懒加载
- (NSMutableArray *)drawLines
{
if (_drawLines == nil) {
_drawLines = [NSMutableArray array];
}
return _drawLines;
}
初始化方法
- (void)setUp
{
// 设置手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[selfaddGestureRecognizer:pan];
_lineColor = [UIColor blackColor];
_lineWidth = 1;
}
手势实现
- (void)pan:(UIPanGestureRecognizer *)pan
{
// 获取当前点
CGPoint curPoint = [pan locationInView:self];
if (pan.state == UIGestureRecognizerStateBegan)
{
// 设置起点
_path = [[drawPath alloc] init];
_path.lineColor = _lineColor;
_path.lineWidth = _lineWidth;
[_path moveToPoint:curPoint];
// 保存路径
[self.drawLines addObject:_path];
}
// 绘制
[_path addLineToPoint:curPoint];
// 重绘
[self setNeedsDisplay];
}
重写的构造方法
// xib调用
- (void)awakeFromNib
{
[self setUp];
}
// 代码调用
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setUp];
}
returnself;
}
在drawRect 绘制图片
// 清空屏幕
- (void)drawRect:(CGRect)rect
{
for (drawPath *path in self.drawLines) {
// 判断是不是图片
if ([path isKindOfClass:[UIImage class]]) {
// 绘制图片
UIImage *image = (UIImage *)path;
[image drawInRect:rect];
}
// 不是图片就画线
else
{
[path.lineColor set];
[path stroke];
}
}
}
其他方法实现
// 清屏
- (void)eraseScreen
{
[self.drawLines removeAllObjects];
[self setNeedsDisplay];
}
// 撤销
- (void)undo
{
[self.drawLines removeLastObject];
[self setNeedsDisplay];
}
// setter 方法,传入照片时进行刷新
- (void)setImage:(UIImage *)image
{
_image = image;
// 添加图片到绘图数组
[self.drawLinesaddObject:_image];
[selfsetNeedsDisplay];
}
5.3、在控制器中实现
添加两个属性,imageView位于DrawView下面
@property (nonatomic,strong) IBOutlet DrawView *drawView; // 绘图面板
@property (weak, nonatomic) IBOutlet UIImageView *imageView; // 加载的图片显示面板
工具栏:通过拖线的方式创建一个方法
// 清屏
- (IBAction)eraseScreen:(UIBarButtonItem *)sender {
[_drawView eraseScreen];
}
// 撤销
- (IBAction)undo:(id)sender {
[_drawView undo];
}
// 橡皮擦
- (IBAction)eraser:(UIBarButtonItem *)sender {
if ([sender.title isEqualToString:@"橡皮擦"]) {
sender.title = @"绘图";
_drawView.lineColor = [UIColor whiteColor];
_drawView.lineWidth = 5;
}
else if ([sender.title isEqualToString:@"绘图"]) {
sender.title = @"橡皮擦";
_drawView.lineColor = [UIColor blackColor];
_drawView.lineWidth = 1;
}
}
// 保存图片到相册
- (IBAction)save:(id)sender {
// 开启上下文
UIGraphicsBeginImageContextWithOptions(self.drawView.bounds.size, NO, 0);
// 获取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
// 渲染控制器到上下文
[self.drawView.layerrenderInContext:ref];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 关闭上下文
UIGraphicsEndImageContext();
// 保存画板的内容放入相册
// image:写入的图片
// completionTarget图片保存监听者
// 注意:以后写入相册方法中,想要监听图片有没有保存完成,保存完成的方法不能随意乱写,必须传入这个方法didFinishSavingWithError
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
// 保存到桌面
// NSData *data = UIImagePNGRepresentation(image);
// [data writeToFile:@"/Users/song/Desktop/sss.png" atomically:YES];
}
// 监听保存完成,必须实现这个方法
- (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo
{
NSLog(@"图片保存成功");
}
加载图片:图片控制器
// 从相册加载一张图片
- (IBAction)photo:(id)sender {
// 初始化图片控制器
UIImagePickerController *pick = [[UIImagePickerController alloc] init];
// 设置路径
// 设置选择控制器的来源
// UIImagePickerControllerSourceTypePhotoLibrary 相册集
// UIImagePickerControllerSourceTypeSavedPhotosAlbum:照片库
pick.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// 设置代理
pick.delegate = self;
// modal 方式弹出图片控制器
[selfpresentViewController:pick animated:YEScompletion:nil];
}
// 图片代理
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// 获取选中的图片
UIImage *image = info[@"UIImagePickerControllerOriginalImage"];
NSLog(@"%@",image);
self.imageView.alpha = 1; // 可见
self.imageView.userInteractionEnabled = YES; // 设置交互
self.imageView.image = image;
[self addGestures]; // 添加手势
// 退出控制器
[self dismissViewControllerAnimated:YES completion: nil];
}
添加各种手势
- (void)addGestures
{
// 滑动
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
pan.delegate = self;
[self.imageViewaddGestureRecognizer:pan];
// 旋转
UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotate:)];
rotate.delegate = self;
[self.imageViewaddGestureRecognizer:rotate];
// 捏合
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
pinch.delegate = self;
[self.imageViewaddGestureRecognizer:pinch];
// 长按
UILongPressGestureRecognizer *lPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(lPress:)];
[self.imageViewaddGestureRecognizer:lPress];
// 点按
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
[self.imageViewaddGestureRecognizer:tap];
}
// 同一时刻运行响应多个手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (void)pan:(UIPanGestureRecognizer *)pan
{
CGPoint curP = [pan translationInView:self.imageView];
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, curP.x, curP.y);
// 复位
[pan setTranslation:CGPointZeroinView:self.imageView];
}
- (void)pinch:(UIPinchGestureRecognizer *)pinch
{
CGFloat scale = pinch.scale;
self.imageView.transform = CGAffineTransformScale(self.imageView.transform, scale, scale);
// 复位
pinch.scale = 1;
}
- (void)tap:(UITapGestureRecognizer *)tap
{
}
- (void)lPress:(UILongPressGestureRecognizer *)lPress
{
// 截取图片到绘图面板
if (lPress.state == UIGestureRecognizerStateBegan) {
[UIViewanimateWithDuration:0.25animations:^{
self.imageView.alpha = 0.5;
} completion:^(BOOL finished) {
[UIViewanimateWithDuration:0.25animations:^{
self.imageView.alpha = 1;
} completion:^(BOOL finished) {
// 截屏,使用之前定义的分类,包含头文件即可使用
UIImage *image = [UIImage imageWithSnipView:self.drawView];
self.imageView.alpha = 0;
_drawView.image = image; // 显示图片到绘图面板
}];
}];
}
}
- (void)rotate:(UIRotationGestureRecognizer *)rotate
{
CGFloat rotation = rotate.rotation;
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation);
// 复位
rotate.rotation = 0;
}
线条颜色和宽度设置
- (IBAction)colorChange:(UIButton *)sender {
_drawView.lineColor = sender.backgroundColor;
}
- (IBAction)valueChange:(UISlider *)sender {
_drawView.lineWidth = sender.value * 10;
}
效果
iOS笔记053- Quartz2D-练习的更多相关文章
- 荼菜的iOS笔记--UIView的几个Block动画
前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...
- 【原】iOS学习之Quartz2D(1)
什么是Quartz2D 1.Quartz 2D 是一个二维绘图引擎,同时支持iOS和Mac系统 2.Quartz 2D 能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成 ...
- iOS开发之Quartz2D详解
1. 什么是Quartz2D? Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片( ...
- IOS笔记 1
< ![CDATA[ 笔记 UIWindows 与UIView的关系iOS的坐标系统视图层次结构视图坐标(Frame和Bounds区别)UIView的常用属性和方法坐标系统的变换UIView内容 ...
- iOS开发之Quartz2D
1. Quartz2D概述及作用 Quartz2D的API是纯C语言的,Quartz2D的API来自于Core Graphics框架. 数据类型和函数基本都以CG作为前缀,比如: CG ...
- 【转】iOS笔记-自定义控件(OC)
原文网址:http://www.jianshu.com/p/f23862eb7b8a 导读: iOS开发中,很多时候系统提供的控件并不能很好的满足我们的需求,因此,自定义控件便成为搭建UI界面中必不可 ...
- iOS笔记———数据存储
应用沙盒:应用文件系统的根目录,每个应用都有独自的沙盒相互:在xcode中可以用NSHomeDirectory()函数,打印当前应用的沙盒根路径. 应用程序包:包含了所有资源文件和执行文件; * Do ...
- IOS 绘图教程Quartz2D
http://www.cocoachina.com/industry/20140115/7703.html http://www.cnblogs.com/wendingding/p/3803020.h ...
- Xamarin开发IOS笔记:切换输入法时输入框被遮住
在进行IOS开发的过程中,出现类似微信朋友圈的交互界面,当用户遇到感兴趣的内容可以进行评论.为了方便评论输入,当出现评论输入框的时候自动将评论输入框移动至键盘的上方,这样方便边输入边查看. 当用户隐藏 ...
- 【IOS笔记】Delegation
Delegation Delegation is a simple and powerful pattern in which one object in a program acts on beha ...
随机推荐
- 并查集,是否成树,Poj(1308)
思路: 对于每一条新的边的两个端点,是否是属于一颗树,要是的话,就不是一颗树.否则,就合并. 这里要注意的是,不能是森林,我这里WA了两次了.只不过在最后,查看每个节点的祖先是否是同一个就可以了. # ...
- 探索性数据分析EDA综述
目录 1. 数据探索的步骤和准备 2. 缺失值处理 为什么需要处理缺失值 Why data has missing values? 缺失值处理的技术 3. 异常值检测和处理 What is an ou ...
- Mac安装protobuf 流程
下载 https://github.com/google/protobuf/releases 找到对应版本下载 编译 cd protobuf./autogen.sh./configuremake 安装 ...
- Python 爬虫的工具列表
这个列表包含与网页抓取和数据处理的Python库 网络 通用 urllib -网络库(stdlib). requests -网络库. grab - 网络库(基于pycurl). pycurl - 网络 ...
- printf、sprintf与fprintf 的用法区分
原文链接 1: fprintf()#include <stdio.h> int fprintf( FILE *stream, const char *format, ... );fprin ...
- Mathematica 讲座
Mathematica 讲座笔记本 [下载] 第一章 Mathematica 简介 [观看] [下载] 第二章 Mathematica 界面和编程语言 [观看] [下载] 第三章 符号运算 [观看] ...
- C#流程控制语句
C#流程控制语句 一.选择语句 当程序中需要进行两个或两个以上的选择时,可以根据条件的判断来选择将要执行的一组语句. ?if语句 ?switch语句 二.循环语句 循环语句是对一个程序模块进行的重复操 ...
- HTML中行内元素和块级元素的区别及转换
区别可以去找 “html文档流”相关的资料去学习,最主要的区别就是元素是占据一行还是挤在一行 转换的方式是用css的display属性 display:block; /*转换为块级*/display: ...
- JS常见内置对象和方法
JS中常用的内置对象:Array对象.Date对象.正则表达式对象.string对象.Global对象 Array对象中常用方法: concat() 表示把几个数组合并成一个数组join() 设 ...
- LVM(扩展)
LVM(扩展)======================== [root@aminglinux newdir]# fdisk -l /dev/sdb 磁盘 /dev/sdb:10.7 GB, 107 ...