swift3.0 CoreGraphics绘图-实现画板
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绘图-实现画板的更多相关文章
- 你知道吗, CoreGraphics绘图系统和Bezier贝塞尔曲线坐标系的顺时针方向是相反的!
UIBezierPath是对Core Graphics框架的一种上层封装,目的是让绘图需求可以被更方便的使用. 那你有没有发现被UIBezierPath封装后与之前有什么改变? 答:有三个变化. 1. ...
- Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)
本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...
- 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)
本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...
- Swift3.0变化分享
Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...
- swift3.0变化总结
Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...
- 关于for循环------swift3.0
在程序开发当中,for循环使用的频率无疑是最高的.常用的swift循环是递增式遍历.当然各种循环,swift都能办到.但其大多采用关键字形式实现,大部分开发者更喜欢直接使用C式循环代码.在swift3 ...
- Swift2.3 --> Swift3.0 的变化
Swift3.0语法变化 首先和大家分享一下学习新语法的技巧: 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Synt ...
- Swift3.0都有哪些变化
从写第一篇Swift文章的时候到现在Swift已经从1.2发展到了今天的3.0,这期间由于Swift目前还在发展阶段并不能向下兼容,因此第一篇文章中的部分代码在当前的Xcode环境中已经无法运行.在W ...
- iOS开发 swift3.0中文版
swift3.0中文版: http://pan.baidu.com/s/1nuHqrBb
随机推荐
- 原生和jQuery的ajax用法
jQuery的ajax方法: $.ajax({ url:'/comm/test1.php', type:'POST', //GET async:true, //或false,是否异步 data:{ n ...
- 实现容器的底层技术 - 每天5分钟玩转 Docker 容器技术(30)
为了更好地理解容器的特性,本节我们将讨论容器的底层实现技术.cgroup 和 namespace 是最重要的两种技术.cgroup 实现资源限额, namespace 实现资源隔离. cgroup c ...
- Android自定义简洁版EditText
Android开发中有些主题的EditText不能让我们满意,我们通常希望文本输入框是一条直线,这样显得简洁又美观. 这里我们自定义了一个MyEditText类,继承EditText类,可以实现一条线 ...
- 【RAC】RAC相关基础知识
[RAC]RAC相关基础知识 1.CRS简介 从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁. ...
- 不让bat文件运行命令结束后cmd窗口自动关闭
方法1假设你的bat名字叫aaa.bat你可以新开一个bat,内容是start aaa.bat然后这个新的bat是不会自动关闭的 方法2要执行bat后不退出,可以在bat里的最后添加pause命令,暂 ...
- JAVA容器结构图
- django-xadmin隐藏菜单不显示
环境:https://github.com/y2kconnect/xadmin-for-python3.git python3.5 django1.9.12 在adminx.py中的Admin类增加属 ...
- zookeeper client API实现(python kazoo 的实现)
这里主要分析zookeeper client API的实现方式,以python kazoo的实现代码为蓝本进行逻辑分析. 一.代码框架及介绍 API分为同步模式和异步模式.同步模式是在异步模式的基础上 ...
- 【LeetCode】233. Number of Digit One
题目: Given an integer n, count the total number of digit 1 appearing in all non-negative integers les ...
- 在线SVN仓库实现:金山快盘+TortoiseSVN(Win)+SCPlugin(Mac)
前段时间一直在研究SVN在线托管,也尝试了网上推荐的免费托管网站. 但毕竟是是免费的,还是要受到比如空间大小.私有性等这样那样的限制,感觉有些麻烦. 而且,比较心疼自己在本地开发的时候积累的更新日志, ...