swift3.0对绘图的API进行了优化,看起来更swift了。git
看下UI的构造。设置画笔粗细、清空面板和保存到本地github
下面直接看画板文件swift
这里我作的比较复杂,记录触摸到的每一个点,再连成路径,其实直接用可变路径
CGMutablePath
可变路径就能够实现。数组
成员变量app
public var lineWidth:CGFloat = 1 fileprivate var allLineArray = [[CGPoint]]() //全部的线 记录每一条线 fileprivate var currentPointArray = [CGPoint]() //当前画线的点 画完置空 增长到 线数组中 fileprivate var allPointWidth = [CGFloat]() //全部的线宽
设置触摸时间,开始时记录第一个点并重绘(不重绘就没有只画一个点得效果),移动时不断记录并重绘。ide
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() }
下面看下 重绘的主逻辑3d
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() } }
保存成图片可很简单,只要截屏设置范围就行code
//保存图片 @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设置相册的权限blog
在info.plist中添加Privacy - Photo Library Usage Description
属性便可,value值为提示信息
效果:
有兴趣的童靴可能够直接用可变路径实现下 逻辑更简单 完了。
https://github.com/gongxiaokai/paintViewDemo