사용자는 목록에서 랜드마크를 방문 할 때마다 배지를 받는다. 물론 사용자가 배지를 받으려면 배지를 만들어야 한다.
이 튜토리얼에서는 paths와 shapes을 결합하여 배지를 만드는 과정을 안내하며, 그런 다음 위치를 나타내는 모양으로 오버레이한다.
여러 종류의 랜드마크에 대해 여러개의 배지를 만들려면 중첩된 기호로 실험하거나 반복 횟수를 변경하거나 다양한 각도와 배율을 변경해 보라.
그리기 전에 HexagonParameters.swift를 추가하고 입력한다.
import CoreGraphics
struct HexagonParameters {
struct Segment {
let line: CGPoint
let curve: CGPoint
let control: CGPoint
}
static let adjustment: CGFloat = 0.085
static let segments = [
Segment(
line: CGPoint(x: 0.60, y: 0.05),
curve: CGPoint(x: 0.40, y: 0.05),
control: CGPoint(x: 0.50, y: 0.00)
),
Segment(
line: CGPoint(x: 0.05, y: 0.20 + adjustment),
curve: CGPoint(x: 0.00, y: 0.30 + adjustment),
control: CGPoint(x: 0.00, y: 0.25 + adjustment)
),
Segment(
line: CGPoint(x: 0.00, y: 0.70 - adjustment),
curve: CGPoint(x: 0.05, y: 0.80 - adjustment),
control: CGPoint(x: 0.00, y: 0.75 - adjustment)
),
Segment(
line: CGPoint(x: 0.40, y: 0.95),
curve: CGPoint(x: 0.60, y: 0.95),
control: CGPoint(x: 0.50, y: 1.00)
),
Segment(
line: CGPoint(x: 0.95, y: 0.80 - adjustment),
curve: CGPoint(x: 1.00, y: 0.70 - adjustment),
control: CGPoint(x: 1.00, y: 0.75 - adjustment)
),
Segment(
line: CGPoint(x: 1.00, y: 0.30 + adjustment),
curve: CGPoint(x: 0.95, y: 0.20 + adjustment),
control: CGPoint(x: 1.00, y: 0.25 + adjustment)
)
]
}
뱃지 뷰 생성하기
뱃지를 생성하기 위해서 SwiftUI안에 있는 백터 드로잉 API를 사용하여 뱃지 뷰를 만들어 본다.
File > New > File에서 SwiftUI View 템플릿을 선택하고 파일명을 Badge로 입력하여 새로운 파일을 생성한다.
paths를 사용하여 선, 곡선 및 기타 드로잉 프리미티브를 결합하여 뱃지의 육각형 배경과 같이 더 복잡한 모양을 형성한다.
path에 시작점을 추rkgksek.
move(to:) 메서드는 가상 펜이나 연필이 해당 영역 위로 마우스를 가져가서 그리기 시작을 기다리는 것처럼 모양의 경계 내에서 그리기 커서를 이동한다.
import SwiftUI
struct Badge: View {
var body: some View {
Path{ path in
var width: CGFloat = 100.0
let height = width
path.move(to: CGPoint(x: width * 0.95, y: height * 0.20))
}
.fill(Color.black)
}
}
struct Badge_Previews: PreviewProvider {
static var previews: some View {
Badge()
}
}
모양 데이터의 각 점에 대한 선을 그려 대략 6각형 모양을 만든다.
addLine(to)메서드는 단일 포인트를 가져와서 그린다. addLine(to: )에 대한 연속적인 호출은 이전 지점에서 라인을 시작하고 새 지점으로 계속한다.
import SwiftUI
struct BadgeBackground: View {
var body: some View {
GeometryReader { geometry in
Path { path in
var width: CGFloat = min(geometry.size.width, geometry.size.height)
let height = width
let xScale: CGFloat = 0.832
let xOffset = (width * (1.0 - xScale)) / 2.0
width *= xScale
path.move(
to: CGPoint(
x: width * 0.95 + xOffset,
y: height * (0.20 + HexagonParameters.adjustment)
)
)
HexagonParameters.segments.forEach { segment in
path.addLine(
to: CGPoint(
x: width * segment.line.x + xOffset,
y: height * segment.line.y
)
)
path.addQuadCurve(
to: CGPoint(
x: width * segment.curve.x + xOffset,
y: height * segment.curve.y
),
control: CGPoint(
x: width * segment.control.x + xOffset,
y: height * segment.control.y
)
)
}
}
.fill(.linearGradient(
Gradient(colors: [Self.gradientStart, Self.gradientEnd]),
startPoint: UnitPoint(x: 0.5, y: 0),
endPoint: UnitPoint(x: 0.5, y: 0.6)
))
}
.aspectRatio(1, contentMode: .fit)
}
static let gradientStart = Color(red: 239.0 / 255, green: 120.0 / 255, blue: 221.0 / 255)
static let gradientEnd = Color(red: 239.0 / 255, green: 172.0 / 255, blue: 120.0 / 255)
}
struct BadgeBackground_Previews: PreviewProvider {
static var previews: some View {
BadgeBackground()
}
}
BadgeSymbol.swift
import SwiftUI
struct RotatedBadgeSymbol: View {
let angle: Angle
var body: some View {
BadgeSymbol()
.padding(-60)
.rotationEffect(angle, anchor: .bottom)
}
}
struct RotatedBadgeSymbol_Previews: PreviewProvider {
static var previews: some View {
RotatedBadgeSymbol(angle: Angle(degrees: 5))
}
}
RotatedBadgeSymbol.swft
import SwiftUI
struct RotatedBadgeSymbol: View {
let angle: Angle
var body: some View {
BadgeSymbol()
.padding(-60)
.rotationEffect(angle, anchor: .bottom)
}
}
struct RotatedBadgeSymbol_Previews: PreviewProvider {
static var previews: some View {
RotatedBadgeSymbol(angle: Angle(degrees: 5))
}
}
import SwiftUI
struct Badge: View {
var badgeSymbols: some View {
ForEach(0..<8) { index in
RotatedBadgeSymbol(
angle: .degrees(Double(index) / Double(8)) * 360.0
)
}
.opacity(0.5)
}
var body: some View {
ZStack {
BadgeBackground()
GeometryReader { geometry in
badgeSymbols
.scaleEffect(1.0 / 4.0, anchor: .top)
.position(x: geometry.size.width / 2.0, y: (3.0 / 4.0) * geometry.size.height)
}
}
.scaledToFit()
}
}
struct Badge_Previews: PreviewProvider {
static var previews: some View {
Badge()
}
}