swift3.0对绘图的API进行了优化,看起来更swift了。

看下UI的构造。设置画笔粗细、清空面板和保存到本地

下面直接看画板文件

这里我做的比较复杂,记录触摸到的每个点,再连成路径,其实直接用可变路径CGMutablePath可变路径就可以实现。

成员变量

    public var lineWidth:CGFloat = 1
fileprivate var allLineArray = [[CGPoint]]() //所有的线 记录每一条线
fileprivate var currentPointArray = [CGPoint]() //当前画线的点 画完置空 增加到 线数组中
fileprivate var allPointWidth = [CGFloat]() //所有的线宽

设置触摸时间,开始时记录第一个点并重绘(不重绘就没有只画一个点得效果),移动时不断记录并重绘。

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let point:CGPoint = (event?.allTouches?.first?.location(in: self))!
//路径起点
currentPointArray.append(point)
self.setNeedsDisplay()
} override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let point:CGPoint = (event?.allTouches?.first?.location(in: self))!
//路径
currentPointArray.append(point)
//刷新视图
self.setNeedsDisplay()
}

由于我们的点都是存在数组中,当要清空画板时 只要将数组清空就可以了

    func cleanAll(){
allLineArray.removeAll()
currentPointArray.removeAll()
allPointWidth.removeAll()
self.setNeedsDisplay()
}

下面看下 重绘的主逻辑

 override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineCap(.round)
context?.setLineJoin(.round) //绘制之前的线
if allLineArray.count > 0 {
//遍历之前的线
for i in 0..<allLineArray.count {
let tmpArr = allLineArray[i]
if tmpArr.count > 0 {
//画线
context?.beginPath()
//取出起始点
let sPoint:CGPoint = tmpArr[0]
context?.move(to: sPoint)
//取出所有当前线的点
for j in 0..<tmpArr.count {
let endPoint:CGPoint = tmpArr[j]
context?.addLine(to: endPoint)
}
context?.setLineWidth(allPointWidth[i])
context?.strokePath()
}
}
} if currentPointArray.count > 0 {
//绘制当前线
context?.beginPath()
context?.setLineWidth(self.lineWidth)
context?.move(to: currentPointArray[0])
print(currentPointArray[0]) for i in 0..<currentPointArray.count {
context?.addLine(to: currentPointArray[i])
print(currentPointArray[i])
}
context?.strokePath()
}
}

保存成图片可很简单,只要截屏设置范围就行

    //保存图片
@IBAction func savePic(_ sender: Any) { let height:CGFloat = self.view.bounds.size.height - self.saveBtn.frame.height - 10
let imageSize :CGSize = CGSize(width: self.view.bounds.size.width, height: height)
UIGraphicsBeginImageContext(imageSize)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let img:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(img, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
} //保存图片回调
func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafeRawPointer) {
var resultTitle:String?
var resultMessage:String?
if error != nil {
resultTitle = "错误"
resultMessage = "保存失败,请检查是否允许使用相册"
} else {
resultTitle = "提示"
resultMessage = "保存成功"
}
let alert:UIAlertController = UIAlertController.init(title: resultTitle, message:resultMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "确定", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}

不过千万别忘了给app设置相册的权限

在info.plist中添加Privacy - Photo Library Usage Description属性即可,value值为提示信息

效果:

有兴趣的童靴可可以直接用可变路径实现下 逻辑更简单 完了。

Demo地址

https://github.com/gongxiaokai/paintViewDemo

swift3.0 CoreGraphics绘图-实现画板的更多相关文章

  1. 你知道吗, CoreGraphics绘图系统和Bezier贝塞尔曲线坐标系的顺时针方向是相反的!

    UIBezierPath是对Core Graphics框架的一种上层封装,目的是让绘图需求可以被更方便的使用. 那你有没有发现被UIBezierPath封装后与之前有什么改变? 答:有三个变化. 1. ...

  2. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  3. 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)

    本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...

  4. Swift3.0变化分享

    Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...

  5. swift3.0变化总结

    Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...

  6. 关于for循环------swift3.0

    在程序开发当中,for循环使用的频率无疑是最高的.常用的swift循环是递增式遍历.当然各种循环,swift都能办到.但其大多采用关键字形式实现,大部分开发者更喜欢直接使用C式循环代码.在swift3 ...

  7. Swift2.3 --> Swift3.0 的变化

    Swift3.0语法变化 首先和大家分享一下学习新语法的技巧: 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Synt ...

  8. Swift3.0都有哪些变化

    从写第一篇Swift文章的时候到现在Swift已经从1.2发展到了今天的3.0,这期间由于Swift目前还在发展阶段并不能向下兼容,因此第一篇文章中的部分代码在当前的Xcode环境中已经无法运行.在W ...

  9. iOS开发 swift3.0中文版

    swift3.0中文版: http://pan.baidu.com/s/1nuHqrBb

随机推荐

  1. 产品经理必备工具-Axure(1)

    资源下载: Axure的中文官方下载地址:https://www.axure.com.cn/3510/ Axure汉化包:https://www.axure.com.cn/2616/ Axure元件库 ...

  2. solr学习笔记-开篇

    由于工作需要,近期接触了一下全文检索的相关技术,从lucenen到solr开始慢慢一路摸爬滚打,仅以此文记录自己的学习里程和记录下各种坑. 本次学习基于以下环境版本: java7,solr5.5.4( ...

  3. win10 搜索不能使用解决方法

    重装系统之后遇到一个问题,在搜索栏不能搜索到应用程序,Windows 10 Search can't find ANY applications. Even calculator - Super Us ...

  4. C#基础知识-XML介绍及基本操作(十)

    在讲了一系列的基础文档之后,现在开始讲一些实例.对于一些数据不是很大的程序,或者只是一些配置文件,需要本地存储的,完全可以使用XML代替数据库,因为只是去操作单个文件会比操作数据库要简单很多,在程序中 ...

  5. Hibernate入门(三)

    一 Hibernate生成器类 Hibernate中,标签id中的generator标签用于生成持久化类对象的唯一标识.所有的生成器类都实现了org.hibernate.id.IdentifierGe ...

  6. 收集一些工作中常用的经典SQL语句

    作为一枚程序员来说和数据库打交道是不可避免的,现收集一下工作中常用的SQL语句,希望能给大家带来一些帮助,当然不全面,欢迎补充! 1.执行插入语句,获取自动生成的递增的ID值 INSERT INTO ...

  7. Java IO学习笔记三

    Java IO学习笔记三 在整个IO包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流-字符流的转换类. OutputStreamWriter:是Writer的子类,将输出的 ...

  8. PHPStorm中的快捷键

    1.Ctrl+Alt+L 格式化代码 2.windows下按下快捷`Ctrl`+`Shift`+`-`,这样就能折叠所有代码了. 3.windows下按下快捷`Ctrl`+`Shift`+`+`,这样 ...

  9. [HNOI2007]紧急疏散EVACUATE (湖南2007年省选)

    [HNOI2007]紧急疏散EVACUATE 题目描述 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面 ...

  10. postgis 中的距离计算

    最近在做一个项目,有一个功能想要实现类似于查询附近的人的功能.由于项目的原因数据库只能使用 postgresql,空间查询就使用了 postgis 来实现. 具体业务像这样:业务需要返回附近距自己 1 ...