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( 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值为提示信息
效果:
有兴趣的童靴可可以直接用可变路径实现下 逻辑更简单 完了。