iOS如何開發簡單的手繪應用例項詳解
開發一款簡單的 iOS 手繪應用,
收集點,繪製形狀,給形狀著色,呈現給使用者,好像就完了
框架是 Quartz2D
1, 收集點
首先需要有一個介面 UIView,用這個介面監聽使用者的手勢,收集點
- 使用者按下手指
location(in,從觸控事件中,獲得在畫板中的座標
var lastPoint = CGPoint.zero override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) { guard let touch = touches.first else { return } // ... lastPoint = touch.location(in: view) }
- 使用者移動手指
override func touchesMoved(_ touches: Set<UITouch>,with event: UIEvent?) { // ... }
- 使用者抬起手指
override func touchesEnded(_ touches: Set<UITouch>,with event: UIEvent?) { // ... }
2,繪製形狀,給形狀著色
開闢一塊繪圖上下文 UIGraphicsGetCurrentContext,
使用採集的點連線
使用者手繪的不是一段連續的曲線,是很多個線段拼接起來的
func drawLine(from fromPoint: CGPoint,to toPoint: CGPoint) { UIGraphicsBeginImageContext(view.frame.size) guard let context = UIGraphicsGetCurrentContext() else { return } // ... // 繪製 context.move(to: fromPoint) context.addLine(to: toPoint) context.setLineCap(.round) context.setBlendMode(.normal) context.setLineWidth(brushWidth) context.setStrokeColor(color.cgColor) context.strokePath() // ... UIGraphicsEndImageContext() }
3,呈現給使用者
第一步使用的 UIView 是 UIImageView,
- 繪製就是畫一小段,取出畫好的圖片,賦給 UIImageView,我們就看到了
- 連續的繪製,是畫一小段,取出畫好的圖片,賦給 UIImageView,並用變數儲存下最新的圖片
接著畫,先把剛才的圖片變數繪製一遍,再畫一小段,取出畫好的圖片,賦給 UIImageView,並用變數儲存下最新的圖片
func drawLine(from fromPoint: CGPoint,to toPoint: CGPoint) { UIGraphicsBeginImageContext(view.frame.size) guard let context = UIGraphicsGetCurrentContext() else { return } tempImageView.image?.draw(in: view.bounds) // 繪製 ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() }
4,畫筆設定
修改畫筆顏色和粗細
func drawLine(from fromPoint: CGPoint,to toPoint: CGPoint) { UIGraphicsBeginImageContext(view.frame.size) guard let context = UIGraphicsGetCurrentContext() else { return } // ... context.setBlendMode(.normal) // 調顏色 context.setLineWidth(brushWidth) // 調粗細 context.setStrokeColor(color.cgColor) // ... }
畫筆變橡皮擦
- 方法一,把畫筆的顏色,調成畫板的顏色,就成了橡皮擦
- 方法 2 ,
把畫筆的顏色,調成透明,
把繪圖上下文的混色模式改掉
就成了橡皮擦
switch type { case .pencil,.none: context.setBlendMode(.color) case .eraser: context.setLineWidth(15) context.setStrokeColor(UIColor.clear.cgColor) context.setBlendMode(.clear) }
5,後續
更多功能:
加入文字輸入功能,
需要一個文字框控制元件 UITextField、 UITextView
文字框控制元件一般可以拖動,
文字框放在畫布上,拖出畫布了,有些問題。
這時候要做一個邊界檢測
效能優化:
一般效能優化,就是列印函式的執行時間
當畫布的大小為 1366 X 7700 ( iPad Pro + UIScrollView ) 的時候,畫布很大,
全部繪製一遍,並取出圖片,效能消耗很大
tempImageView.image?.draw(in: view.bounds) // ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
繪製一次,需要約 0.07 秒,
let t = Date() self.drawingImage() if #available(iOS 13.0,*) { let span = t.distance(to: Date()) print(span) }
我們期望 60 的 FPS,每一幀計算時間 0.016, 所以頻繁呼叫該方法,卡得厲害
之前的方法是一個點,一個點的繪製
移動一下,繪製一次
override func touchesMoved(_ touches: Set<UITouch>,with event: UIEvent?) { guard let touch = touches.first else { return } swiped = true let currentPoint = touch.location(in: view) drawLine(from: lastPoint,to: currentPoint) lastPoint = currentPoint }
畫一段線, func touchesMoved() ,一般可以觸發 30 ~ 60 次,收集的點比較多,線條柔和
此時頻繁呼叫該消耗效能方法,
只能觸發 6 次,畫一段只能採集 6 個點,正常手速,就畫出來一個多邊形
可以這樣優化,點的收集與繪製分離
使用一個 Timer ,每隔 0.15 秒,繪製一次
原本收集點,是一個 CGPoint, 現在收集點,是一個 [CGPoint]
- 原本畫一次之前的 image, 連一根線,更新圖片變數並呈現
n 個點,來 n 次全畫板繪製
- 現在畫一次之前的 image, 連線多根線,更新圖片變數並呈現
n 個點,來 1 次全畫板繪製
消耗效能的方法,少呼叫,就對了
tempImageView.image?.draw(in: view.bounds) // ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
前 4 點的程式碼,見 github
後續需要整理,tbd
總結
到此這篇關於iOS如何開發簡單的手繪應用的文章就介紹到這了,更多相關iOS開發手繪應用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!