iOS如何開發(fā)簡(jiǎn)單的手繪應(yīng)用實(shí)例詳解
開發(fā)一款簡(jiǎn)單的 iOS 手繪應(yīng)用,
收集點(diǎn),繪制形狀,給形狀著色,呈現(xiàn)給用戶,好像就完了
框架是 Quartz2D
1, 收集點(diǎn)
首先需要有一個(gè)界面 UIView, 用這個(gè)界面監(jiān)聽用戶的手勢(shì),收集點(diǎn)
- 用戶按下手指
location(in, 從觸摸事件中,獲得在畫板中的坐標(biāo)
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)
}
- 用戶移動(dòng)手指
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// ...
}
- 用戶抬起手指
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// ...
}
2, 繪制形狀,給形狀著色
開辟一塊繪圖上下文 UIGraphicsGetCurrentContext,
使用采集的點(diǎn)連線
用戶手繪的不是一段連續(xù)的曲線,是很多個(gè)線段拼接起來的
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, 呈現(xiàn)給用戶
第一步使用的 UIView 是 UIImageView,
- 繪制就是畫一小段,取出畫好的圖片,賦給 UIImageView,我們就看到了
- 連續(xù)的繪制,是畫一小段,取出畫好的圖片,賦給 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, 畫筆設(shè)置
修改畫筆顏色和粗細(xì)
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) {
UIGraphicsBeginImageContext(view.frame.size)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
// ...
context.setBlendMode(.normal)
// 調(diào)顏色
context.setLineWidth(brushWidth)
// 調(diào)粗細(xì)
context.setStrokeColor(color.cgColor)
// ...
}
畫筆變橡皮擦
- 方法一,把畫筆的顏色,調(diào)成畫板的顏色,就成了橡皮擦
- 方法 2 ,
把畫筆的顏色,調(diào)成透明,
把繪圖上下文的混色模式改掉
就成了橡皮擦
switch type {
case .pencil, .none:
context.setBlendMode(.color)
case .eraser:
context.setLineWidth(15)
context.setStrokeColor(UIColor.clear.cgColor)
context.setBlendMode(.clear)
}
5,后續(xù)
更多功能:
加入文本輸入功能,
需要一個(gè)文本框控件 UITextField、 UITextView
文本框控件一般可以拖動(dòng),
文本框放在畫布上,拖出畫布了,有些問題。
這時(shí)候要做一個(gè)邊界檢測(cè)
性能優(yōu)化:
一般性能優(yōu)化,就是打印函數(shù)的執(zhí)行時(shí)間
當(dāng)畫布的大小為 1366 X 7700 ( iPad Pro + UIScrollView ) 的時(shí)候,畫布很大,
全部繪制一遍,并取出圖片,性能消耗很大
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, 每一幀計(jì)算時(shí)間 0.016, 所以頻繁調(diào)用該方法,卡得厲害
之前的方法是一個(gè)點(diǎn),一個(gè)點(diǎn)的繪制
移動(dòng)一下,繪制一次
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() ,一般可以觸發(fā) 30 ~ 60 次,收集的點(diǎn)比較多,線條柔和
此時(shí)頻繁調(diào)用該消耗性能方法,
只能觸發(fā) 6 次,畫一段只能采集 6 個(gè)點(diǎn),正常手速,就畫出來一個(gè)多邊形
可以這樣優(yōu)化,點(diǎn)的收集與繪制分離
使用一個(gè) Timer ,每隔 0.15 秒,繪制一次
原本收集點(diǎn),是一個(gè) CGPoint, 現(xiàn)在收集點(diǎn),是一個(gè) [CGPoint]
- 原本畫一次之前的 image, 連一根線,更新圖片變量并呈現(xiàn)
n 個(gè)點(diǎn), 來 n 次全畫板繪制
- 現(xiàn)在畫一次之前的 image, 連接多根線,更新圖片變量并呈現(xiàn)
n 個(gè)點(diǎn), 來 1 次全畫板繪制
消耗性能的方法,少調(diào)用,就對(duì)了
tempImageView.image?.draw(in: view.bounds) // ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
后續(xù)需要整理,tbd
總結(jié)
到此這篇關(guān)于iOS如何開發(fā)簡(jiǎn)單的手繪應(yīng)用的文章就介紹到這了,更多相關(guān)iOS開發(fā)手繪應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
iOS 對(duì)NSMutableArray進(jìn)行排序和過濾的實(shí)例
下面小編就為大家分享一篇iOS 對(duì)NSMutableArray進(jìn)行排序和過濾的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01
兼容iOS 10 升級(jí)xcode8出現(xiàn)的問題及一些適配問題的解決方案
這篇文章主要介紹了兼容iOS 10 升級(jí)xcode8出現(xiàn)的問題及一些適配問題的解決方案,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式
組合模式,Composite Pattern,是一個(gè)非常巧妙的模式。幾乎所有的面向?qū)ο笙到y(tǒng)都應(yīng)用到了組合模式,接下來通過本文給大家介紹IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式,需要的朋友參考下2016-02-02
iOS開發(fā)中UIImageView控件的常用操作整理
這篇文章主要介紹了iOS開發(fā)中UIImageView控件的常用操作整理,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-01-01
iOS實(shí)現(xiàn)簡(jiǎn)單長(zhǎng)截圖
這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)簡(jiǎn)單長(zhǎng)截圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
iOS的客戶端菜單功能仿百度糯米/美團(tuán)二級(jí)菜單
我剛好最近在開發(fā)一個(gè)商城項(xiàng)目,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的控件,控件的效果就是類似百度糯米或者美團(tuán)的二級(jí)菜單,非常不錯(cuò)具有參考借鑒價(jià)值,對(duì)百度糯米 美團(tuán)二級(jí)菜單功能感興趣的朋友一起看看吧2016-11-11
iOS實(shí)現(xiàn)導(dǎo)航欄透明示例代碼
本篇文章主要介紹了iOS實(shí)現(xiàn)導(dǎo)航欄透明示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
iOS開發(fā)中Quartz2D繪圖路徑的使用以及條紋效果的實(shí)現(xiàn)
這篇文章主要介紹了iOS開發(fā)中Quartz2D繪圖路徑的使用以及條紋效果的實(shí)現(xiàn),代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-11-11
iOS應(yīng)用中UICollectionViewCell定制Button
這篇文章主要介紹了iOS應(yīng)用中UICollectionViewCell如何定制Button,設(shè)置每行顯示的按鈕的個(gè)數(shù),自定制按鈕的顯示樣式,感興趣的小伙伴們可以參考一下2016-08-08

