Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- rxswift
- combine
- 리팩토링
- 리펙토링
- uitableview
- UICollectionView
- Protocol
- ios
- RxCocoa
- MVVM
- HIG
- SWIFT
- ribs
- 리펙터링
- clean architecture
- swift documentation
- 애니메이션
- 클린 코드
- swiftUI
- UITextView
- map
- Xcode
- uiscrollview
- tableView
- collectionview
- 스위프트
- Human interface guide
- Observable
- Refactoring
- Clean Code
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - SwiftUI] 2. Canvas 사용 방법 (fill, stroke) 본문
2. Canvas 사용 방법 (fill, stroke)
이전 글에서 알아본 대로 (아래처럼 Canvas를 선언하여 사용 준비)
struct ContentView: View {
var body: some View {
Canvas(
opaque: true,
colorMode: .linear,
rendersAsynchronously: false
) { context, size in
context.opacity = 0.3
...
}
.frame(width: 300, height: 500)
}
}
fill을 사용하여 그리기
- context.fill(_:with:)을 사용하면 path만큼 안쪽을 채우는 효과가 있는데, 이것을 사용하면 원하는 도형을 쉽게 표현이 가능
public func fill(_ path: Path, with shading: GraphicsContext.Shading, style: FillStyle = FillStyle())
- 먼저 rect를 선언하여 그림을 그릴 전체 범위를 준비
struct ContentView: View {
var body: some View {
Canvas(
opaque: true,
colorMode: .linear,
rendersAsynchronously: false
) { context, size in
context.opacity = 0.3
let rect = CGRect(origin: .zero, size: size)
}
.frame(width: 300, height: 500)
}
}
- context.fill을 사용하면 만들어준 path만큼 안쪽을 채우는 효과가 있는 형태
struct ContentView: View {
var body: some View {
Canvas(
opaque: true,
colorMode: .linear,
rendersAsynchronously: false
) { context, size in
context.opacity = 0.3
let rect = CGRect(origin: .zero, size: size)
// 1. size
let targetRect = rect.applying(.init(scaleX: 1, y: 1))
// 2. path
let path = Rectangle().path(in: targetRect)
// 3. draw
context.fill(path, with: .color(.green))
}
.frame(width: 300, height: 500)
}
}
stroke를 사용하여 그리기
- stroke를 사용하면 넣어준 path만큼 그림을 그리기 쉽기 때문에 원하는 그림을 그릴때 사용
public func stroke(_ path: Path, with shading: GraphicsContext.Shading, style: StrokeStyle)
- 코드를 추가하여 삼각형 그리기
위에서 사각형을 그린 전체 코드)
struct ContentView: View {
var body: some View {
Canvas(
opaque: true,
colorMode: .linear,
rendersAsynchronously: false
) { context, size in
context.opacity = 0.3
let rect = CGRect(origin: .zero, size: size)
// # fill
// size
let targetRect = rect.applying(.init(scaleX: 1, y: 1))
// path
let path = Rectangle().path(in: targetRect)
// draw
context.fill(path, with: .color(.green))
// # stroke
// TODO...
}
.frame(width: 300, height: 500)
}
}
- 항상 path를 그릴때는 꼭지점을 알면 모두 그릴 수 있으므로, 삼각형 꼭지점 3개를 구하는 것을 목표로 코딩
- 삼각형 꼭지점 3개를 구하기 위해서, 중앙 좌표를 구한 후, 그 중앙 좌표로 부터 50만큼 떨어져 있는 꼭지점을 구한 후 path로 그리는 것
- SwiftUI의 Path를 사용하여 구현
// # stroke
let center = CGPoint(x: size.width / 2, y: size.height / 2)
// 반지름 50
let radius: CGFloat = 50
let trianglePath = Path { path in
// 삼각형의 꼭짓점 계산: 3등분하여 각 꼭지점 각도 구하기
let points = (0..<3).map { i -> CGPoint in
let angle = CGFloat(i) * (2.0 * .pi / 3.0) - .pi / 2.0
return CGPoint(
x: center.x + radius * cos(angle),
y: center.y + radius * sin(angle)
)
}
path.move(to: points[0])
for point in points.dropFirst() {
path.addLine(to: point)
}
path.closeSubpath()
}
- 이 path를 context.stroke에 넘기면 완성
context.stroke(
trianglePath,
with: .color(.black),
style: .init(
lineWidth: 5,
lineCap: .round,
lineJoin: .round
)
)
* 전체 코드
import SwiftUI
struct ContentView: View {
var body: some View {
Canvas(
opaque: true,
colorMode: .linear,
rendersAsynchronously: false
) { context, size in
context.opacity = 0.3
let rect = CGRect(origin: .zero, size: size)
// # fill
// size
let targetRect = rect.applying(.init(scaleX: 1, y: 1))
// path
let path = Rectangle().path(in: targetRect)
// draw
context.fill(path, with: .color(.green))
// # stroke
let center = CGPoint(x: size.width / 2, y: size.height / 2)
// 반지름 50
let radius: CGFloat = 50
let trianglePath = Path { path in
// 삼각형의 꼭짓점 계산: 3등분하여 각 꼭지점 각도 구하기
let points = (0..<3).map { i -> CGPoint in
let angle = CGFloat(i) * (2.0 * .pi / 3.0) - .pi / 2.0
// center기준으로 반지름에
return CGPoint(
x: center.x + radius * cos(angle),
y: center.y + radius * sin(angle)
)
}
// 그림 그리기
path.move(to: points[0])
for point in points.dropFirst() {
path.addLine(to: point)
}
path.closeSubpath()
}
context.stroke(
trianglePath,
with: .color(.black),
style: .init(
lineWidth: 5,
lineCap: .round,
lineJoin: .round
)
)
}
.frame(width: 300, height: 500)
}
}
#Preview {
ContentView()
}
Comments