swift3.0 CoreGraphics繪圖-實現畫板

swift3.0對繪圖的API進行了優化,看起來更swift了。git

看下UI的構造。設置畫筆粗細、清空面板和保存到本地github

畫板哦.gif

下面直接看畫板文件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值爲提示信息

相冊權限.png

效果:

效果.png

有興趣的童靴可能夠直接用可變路徑實現下 邏輯更簡單 完了。

Demo地址

https://github.com/gongxiaokai/paintViewDemo

相關文章
相關標籤/搜索