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) {}
}

์ฃผ์š” ํด๋ž˜์Šค

๋ฐ๋ชจ ๋ชฉ๋ก

# ๋ฐ๋ชจ ์„ค๋ช…
1 Freehand Drawing SwiftUI Canvas ๊ธฐ๋ฐ˜ ์ž์œ  ๋“œ๋กœ์ž‰. 8์ƒ‰ ํŒ”๋ ˆํŠธ, ์„  ๊ตต๊ธฐ ์Šฌ๋ผ์ด๋”, ์ง€์šฐ๊ฐœ, undo/redo๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
2 PencilKit Canvas PKCanvasView + PKToolPicker ํ†ตํ•ฉ. Apple Pencil ํ•„์••/๊ธฐ์šธ๊ธฐ ์ง€์›, ์ด๋ฏธ์ง€ ๋‚ด๋ณด๋‚ด๊ธฐ ๊ธฐ๋Šฅ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
3 Shape Builder ํ„ฐ์น˜ ์ œ์Šค์ฒ˜๋กœ ์„ /์‚ฌ๊ฐํ˜•/์›/์‚ผ๊ฐํ˜•์„ ๊ทธ๋ฆฌ๊ณ  ์ŠคํŠธ๋กœํฌ์™€ ์ฑ„์šฐ๊ธฐ ์ƒ‰์ƒ์„ ์กฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ „ ํŒ

Best Practices

์ฃผ์˜ ์‚ฌํ•ญ