Home > Drawing Canvas
Drawing Canvas
CoreGraphics(Quartz 2D)์ ์ ์์ค ๋๋ก์ API์ PencilKit์ ๊ณ ์์ค ํ๊ธฐ/๋๋ก์ ํ๋ ์์ํฌ๋ฅผ ํจ๊ป ํ์ตํฉ๋๋ค. ๋ฒกํฐ ๊ฒฝ๋ก๋ถํฐ Apple Pencil ํ์ ์ธ์๊น์ง ๋ค๋ฃน๋๋ค.
๊ฐ์
iOS ๋๋ก์์ ํฌ๊ฒ ๋ ๊ฐ์ง ์ ๊ทผ๋ฒ์ผ๋ก ๋๋ฉ๋๋ค.
CoreGraphics(Quartz 2D) ๋ C ๊ธฐ๋ฐ์ ์ ์์ค 2D ๋๋ก์ ์์ง์
๋๋ค. CGContext๋ฅผ ํตํด ๊ฒฝ๋ก(Path), ๊ทธ๋ผ๋์ธํธ, ๋ณํ ํ๋ ฌ ๋ฑ์ ์ง์ ์ ์ดํ๋ฉฐ, ์ปค์คํ
์ฐจํธ, ๋ํ ์๋ํฐ, ์ด๋ฏธ์ง ํฉ์ฑ ๋ฑ ์ ๋ฐํ ๊ทธ๋ํฝ ์์
์ ์ฌ์ฉํฉ๋๋ค.
PencilKit์ Apple Pencil ์ง์์ ํฌํจํ ๋๋ก์ ํ๊ฒฝ์ ์ ๊ณตํ๋ ๊ณ ์์ค ํ๋ ์์ํฌ์ ๋๋ค. ํ์, ๊ธฐ์ธ๊ธฐ, ๋ฐฉ์๊ฐ ์ธ์๊ณผ ํจ๊ป ๋ด์ฅ ๋๊ตฌ ํ๋ ํธ(PKToolPicker)๋ฅผ ์ ๊ณตํ์ฌ ๋๋ก์ ์ฑ์ ๋น ๋ฅด๊ฒ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
์ธ์ ์ฌ์ฉํ๋์?
| ๋ชฉ์ | ์ถ์ฒ |
|---|---|
| ์ปค์คํ ์ฐจํธ/๊ทธ๋ํ | CoreGraphics |
| ๋ฒกํฐ ๋ํ ์๋ํฐ | CoreGraphics + CGPath |
| ์์ ๋๋ก์/ํ๊ธฐ ์ฑ | PencilKit |
| Apple Pencil ํ์ ํ์ฉ | PencilKit |
| ์ด๋ฏธ์ง ์ ์ค๋ฒ๋ ์ด | CoreGraphics |
ํต์ฌ API
CoreGraphics Drawing
SwiftUI์ Canvas ๋ทฐ๋ CoreGraphics ๋๋ก์์ SwiftUI์ ํตํฉํ๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์
๋๋ค.
Canvas { context, size in
let rect = CGRect(origin: .zero, size: size)
// ๊ทธ๋ผ๋์ธํธ ๋ฐฐ๊ฒฝ
let gradient = Gradient(colors: [.blue, .purple])
context.fill(
Path(rect),
with: .linearGradient(gradient,
startPoint: .zero,
endPoint: CGPoint(x: size.width, y: size.height))
)
// ์ปค์คํ
๊ฒฝ๋ก
var path = Path()
path.move(to: CGPoint(x: 50, y: 50))
path.addCurve(to: CGPoint(x: 250, y: 50),
control1: CGPoint(x: 100, y: 0),
control2: CGPoint(x: 200, y: 100))
context.stroke(path, with: .color(.white), lineWidth: 3)
}
PencilKit Integration
PKCanvasView๋ UIKit ๊ธฐ๋ฐ์ด๋ฏ๋ก SwiftUI์์ UIViewRepresentable๋ก ๋ํํ์ฌ ์ฌ์ฉํฉ๋๋ค.
struct DrawingCanvas: UIViewRepresentable {
@Binding var canvasView: PKCanvasView
func makeUIView(context: Context) -> PKCanvasView {
canvasView.drawingPolicy = .anyInput
canvasView.tool = PKInkingTool(.pen, color: .black, width: 5)
// Tool Picker ํ์
let picker = PKToolPicker()
picker.setVisible(true, forFirstResponder: canvasView)
picker.addObserver(canvasView)
canvasView.becomeFirstResponder()
return canvasView
}
func updateUIView(_ uiView: PKCanvasView, context: Context) {}
}
์ฃผ์ ํด๋์ค
- CGContext: ๋๋ก์ ๋ช ๋ น์ ๋ฐ๋ ๊ทธ๋ํฝ ์ปจํ ์คํธ. ๋นํธ๋งต/PDF ์ปจํ ์คํธ ์์ฑ ๊ฐ๋ฅ
- CGPath / UIBezierPath: ์ง์ , ๊ณก์ , ํธ ๋ฑ์ผ๋ก ๊ตฌ์ฑ๋ ๋ฒกํฐ ๊ฒฝ๋ก
- PKCanvasView: PencilKit์ ๋๋ก์ ์์ญ. PKDrawing ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌ
- PKToolPicker: ํ, ๋ง์ปค, ์ง์ฐ๊ฐ ๋ฑ ๋๊ตฌ ์ ํ UI
๋ฐ๋ชจ ๋ชฉ๋ก
| # | ๋ฐ๋ชจ | ์ค๋ช |
|---|---|---|
| 1 | Freehand Drawing | SwiftUI Canvas ๊ธฐ๋ฐ ์์ ๋๋ก์. 8์ ํ๋ ํธ, ์ ๊ตต๊ธฐ ์ฌ๋ผ์ด๋, ์ง์ฐ๊ฐ, undo/redo๋ฅผ ๊ตฌํํฉ๋๋ค. |
| 2 | PencilKit Canvas | PKCanvasView + PKToolPicker ํตํฉ. Apple Pencil ํ์/๊ธฐ์ธ๊ธฐ ์ง์, ์ด๋ฏธ์ง ๋ด๋ณด๋ด๊ธฐ ๊ธฐ๋ฅ์ ํฌํจํฉ๋๋ค. |
| 3 | Shape Builder | ํฐ์น ์ ์ค์ฒ๋ก ์ /์ฌ๊ฐํ/์/์ผ๊ฐํ์ ๊ทธ๋ฆฌ๊ณ ์คํธ๋กํฌ์ ์ฑ์ฐ๊ธฐ ์์์ ์กฐํฉํฉ๋๋ค. |
์ค์ ํ
Best Practices
- ๋จ์ ๋๋ก์/ํ๊ธฐ ์ฑ์ด๋ผ๋ฉด PencilKit์ด ๊ฐ๋ฐ ์๋์ ํ์ง ๋ฉด์์ ์ ๋ฆฌํฉ๋๋ค.
- CoreGraphics๋ ์ขํ๊ณ ์์ ์ด ์ขํ๋จ(UIKit์์๋ ์ข์๋จ)์์ ์ฃผ์ํ์ธ์.
- SwiftUI
Canvas๋ทฐ๋ ๋งค ํ๋ ์ ๋ค์ ๊ทธ๋ฆฌ๋ฏ๋ก, ๋ณต์กํ ๋๋ก์์ ์บ์ฑ์ ๊ณ ๋ คํ์ธ์. - PKDrawing์ Data๋ก ์ง๋ ฌํ๋์ด ์ ์ฅ/๋ณต์์ด ๊ฐํธํฉ๋๋ค.
- Apple Pencil์ ์์ธก(predicted) ํฐ์น๋ฅผ ํ์ฉํ๋ฉด ์ฒด๊ฐ ์ง์ฐ์ ์ค์ผ ์ ์์ต๋๋ค.
์ฃผ์ ์ฌํญ
- CGContext ๊ธฐ๋ฐ ๋๋ก์์ ๋ฐ๋์
saveGState()/restoreGState()์์ผ๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ์ธ์. - PencilKit์ iOS/iPadOS ์ ์ฉ์ผ๋ก, macOS์์๋ ์ ํ์ ์ ๋๋ค.
- UIBezierPath์ CGPath๋ ๋ณํ ๊ฐ๋ฅํ์ง๋ง, ํผ์ฉ ์ ์ขํ๊ณ ์ฐจ์ด์ ์ฃผ์ํ์ธ์.
- ๊ณ ํด์๋(Retina) ๋์คํ๋ ์ด์์๋
UIScreen.main.scale์ ๋ฐ์ํด์ผ ์ ๋ช ํ๊ฒ ๊ทธ๋ ค์ง๋๋ค.