swift塗鴉功能的實現包括截圖,畫板封裝,文本編輯,分享功能,橡皮擦功能,馬賽克技術

一伊塗鴉(swift)github下載地址:https://github.com/Darren-chenchen/yiyiTuYa
這是一款塗鴉軟件,可以實現對圖片的基本操做,供你們參考,在這裏記錄一下功能點和注意點,具體參考demo:git

效果圖github

1.截取長圖web

該功能的主要原理是截取webview的高度所在的區域,因此這種截屏須要在webview加載完畢後獲取到webView.scrollView的contensize,而後將webview的高度設置成這個高度再結合上下文進行截屏操做,注意截屏以後webview的尺寸要恢復成以前的尺寸swift

    // 截取webview全部的內容
    func screenShot() -> UIImage {
        var image = UIImage()
        UIGraphicsBeginImageContextWithOptions(self.webView.scrollView.contentSize, true, 0)
        //保存webView當前的偏移量
        let savedContentOffset = self.webView.scrollView.contentOffset
        let saveFrame = self.webView.scrollView.frame
        
        //將webView的偏移量設置爲(0,0)
        self.webView.scrollView.contentOffset = CGPoint(x: 0, y: 0)
        self.webView.frame = CGRect(x: 0, y: 0, width:
        self.webView.scrollView.contentSize.width, height: self.webView.scrollView.contentSize.height)
        
        //在當前上下文中渲染出webView
        self.webView.scrollView.layer.render(in: UIGraphicsGetCurrentContext()!)

        //截取當前上下文生成Image
        image = UIGraphicsGetImageFromCurrentImageContext()!
        
        //恢復webview的偏移量
        self.webView.scrollView.contentOffset = savedContentOffset
        self.webView.frame = saveFrame
        
        UIGraphicsEndImageContext()
        
        return image
    }

2.畫板的封裝,可以高高效、方便的實現畫板的操做。數組

這個思路我是參考這篇文章 http://blog.csdn.net/zhangao0086/article/details/43836789  ,他對畫板的封裝思路很好,你們能夠去看一下,不足之處就是圖片的緩存搞得有些複雜,我把他的圖片緩存邏輯給改了一下。這裏主要借鑑他的封裝思路。緩存

3.畫板的實現   ide

3.1點擊第一個頁面的編輯進入畫板頁面,該頁面的主要結構是:底層ScrollView,ScrollView上面放置一個DrawBoard(UIimageView)(放置ScrollView的緣由是能夠隨意縮放圖片)spa

新建DrawBoard,繼承自UIimageView,這個DrawBoard就是咱們的畫板,這裏面注意一點:咱們繪製的圖片不是DrawBoard的image屬性,而是backgroundColor。.net

        scrollView = UIScrollView()
        scrollView.frame = CGRect(x: 0, y: 64, width: KScreenWidth, height: KScreenHeight-50-40-64)
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        scrollView.delegate = self
        scrollView.minimumZoomScale = 1
        scrollView.maximumZoomScale = 10
        self.view.addSubview(scrollView!)
        
        drawBoardImageView = DrawBoard.init(frame:scrollView.bounds)
        drawBoardImageView.isUserInteractionEnabled = true
        // 對長圖壓縮處理
        let scaleImage = UIImage.scaleImage(image: self.editorImage, scaleSize: scrollView.cl_height/self.editorImage.size.height)
        drawBoardImageView.backgroundColor = UIColor(patternImage: scaleImage)
        scrollView?.addSubview(drawBoardImageView)

3.2 由於截取的是一個長圖,因此若是直接設置 drawBoardImageView.backgroundColor = UIColor(patternImage: self.editorImage),就會只顯示圖片的一部分,因此要對圖片進行壓縮
。在壓縮圖片時須要注意一點:圖片的大小仍是屏幕大小,只是內容壓縮,若是圖片寬度小於屏幕寬度,圖片會平鋪鋪滿整個界面。下面是壓縮圖片的代碼3d

// 對截取的長圖進行壓縮,由於項目中的長圖是設置爲背景顏色,若是不壓縮到適當的尺寸圖片就會平鋪
    static func scaleImage(image: UIImage,scaleSize:CGFloat) -> UIImage {
     //控制圖片的尺寸 UIGraphicsBeginImageContext(CGSize(width:image.size.width,height:image.size.height
*scaleSize)) image.draw(in: CGRect(x: 0.5*(KScreenWidth-image.size.width * scaleSize), y: 0, width: image.size.width * scaleSize, height: image.size.height*scaleSize)) let scaledImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() //對圖片包得大小進行壓縮 let imageData = UIImageJPEGRepresentation(scaledImage!,1) let m_selectImage = UIImage.init(data: imageData!) return m_selectImage! }

3.2 畫板的使用

4.馬賽克功能  

原理:獲取手指在屏幕上接觸的那一個點的顏色值,而後拿到這個顏色值不斷地繪製一個10*10的小矩形。這個馬賽克功能的實現思路是我本身想到的,若是有其餘更好的思路還麻煩提供給我,我將做出改進。

具體參考demo中RectangleBrush這個類中的實現

override func drawInContext(_ context: CGContext) {
        // 矩形  不填充
//        context.addRect(CGRect(origin: CGPoint(x: min(beginPoint.x, endPoint.x), y: min(beginPoint.y, endPoint.y)),
//            size: CGSize(width: abs(endPoint.x - beginPoint.x), height: abs(endPoint.y - beginPoint.y))))
        //        context.addRect(CGRect(x: pointX!, y: pointY!, width: 8, height: 8))

        // 模糊矩形  填充 畫完一個小正方形以後把終點賦值爲起點繼續畫
        let Width:CGFloat = 10
        var pointX: CGFloat?
        if abs(endPoint.x-beginPoint.x)>Width {
            pointX = endPoint.x
        } else {
            pointX = beginPoint.x
        }
        
        var pointY: CGFloat?
        if abs(endPoint.y-beginPoint.y)>Width {
            pointY = endPoint.y
        } else {
            pointY = beginPoint.y
        }
        context.fill(CGRect(x: pointX!, y: pointY!, width: Width, height: Width))
    }
    
    override func supportedContinuousDrawing() -> Bool {
        return true
    }

5.文本輸入功能

思路:手指觸摸屏幕時,在屏幕上繪製一個textView,當textView輸入結束時,將文字和圖片繪製到同一個image中。 繪製的文字一樣也支持撤銷,橡皮擦等操做

6.DrawBoard類中圖片的撤銷與前進功能  

6.1在DrawBoard類中有一個image的管理類DBUndoManager,主要用於管理咱們繪製了多少圖片,控制撤銷操做和前進操做

6.2DBUndoManager類中的imageArray屬性保存着咱們每次繪製結束後的image(包括畫筆的繪製後的image,文本的輸入後的image)

6.3 imageArray存儲方法:當用戶開始繪製時,先判斷是否是最開始的那張圖片(沒有作任何操做的圖片),若是是的,就將imageArray清空,若是不是最初的那張原圖,就繼續把繪製的image加入到數組中,這裏面的邏輯也不復雜,須要認真的理一下。因此,在這裏就很少少了,具體看demo,思考!

7.圖片的保存 

    // 返回畫板上的圖片,用於保存
    func takeImage() -> UIImage {
        UIGraphicsBeginImageContext(self.bounds.size)
        
        self.backgroundColor?.setFill()
        UIRectFill(self.bounds)
        
        self.image?.draw(in: self.bounds)
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return image!
    }
    //MARK: - 下載圖片
    func clickLoadBtn(){
        let alertController = UIAlertController(title: "提示", message: "您肯定要保存整個圖片到相冊嗎?", preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "取消", style: .cancel, handler: nil)
        let okAction = UIAlertAction(title: "肯定", style: .default, handler: {
            action in

            UIImageWriteToSavedPhotosAlbum(self.drawBoardImageView.takeImage(), self, #selector(EditorViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)
        })
        alertController.addAction(cancelAction)
        alertController.addAction(okAction)
        self.present(alertController, animated: true, completion: nil)
    }
    // 保存圖片的結果
    func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafeRawPointer) {
        if let err = error {
            UIAlertView(title: "錯誤", message: err.localizedDescription, delegate: nil, cancelButtonTitle: "肯定").show()
        } else {
            UIAlertView(title: "提示", message: "保存成功", delegate: nil, cancelButtonTitle: "肯定").show()
        }
    }
相關文章
相關標籤/搜索