SwiftUI Tutorials - Drawing Paths and Shapes
最終的にはリスト内にある場所に行った時にバッジをつけることができるようにします。このチューリアルではそのバッジを作ります。
全体の流れですが、まず、六角形の座標を決め、その背景を作ります。その六角形の中にシンボルとなる形を作り上げ、色を付けて出来上がりです。
Create Drawing Data for a Badge View
新しくHexagonParameters.swiftファイルを追加して構造体"HexagonParameters"を作りデータ構造を定義しておきます。。
六角形を作っていくので6辺の区切り、各辺の位置を決めます。左上の座標が
(x, y) = (0, 0)
となり、"X"は右方面が"正"、"y"は下方面が"正"となります。
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)
)
]
}
六角形の形状を調整する調整値を設定しています。
static let adjustment: CGFloat = 0.085
Draw the Badge Background
実際の表示部分を作っていきます。新しいSwiftUIのファイルを作ります。
ここでPath()の使い方ですが
でわかりやすく解説されています。
続きです。
ファイル名をBadgeBackground.swiftとして構造体BadgeBackgroundを作ります。"Path()"を使って図形をつくり色を付けます。
var body: some View {
Path { path in
}
.fill(Color.black)
}
そして描画する範囲を決め、描画を開始する座標を指定します。
Path { path in
var width: CGFloat = 100.0
let height = width
path.move(
to: CGPoint(
x: width * 0.95,
y: height * 0.20
)
)
}
ここでは範囲は100×100pxで座標が(x:100*0.95, y:100*0.2)としています。
次に先に決めている"segments"を使って線を描画します・
HexagonParameters.segments.forEach { segment in
path.addLine(
to: CGPoint(
x: width * segment.line.x,
y: height * segment.line.y
)
)
}
ここでちょっと表示してみると六角形が変形しています。でも、
Don’t worry if your hexagon looks a little unusual; that’s because you’re ignoring the curved part of each segment at the shape’s corners. You’ll account for that next.
ということで湾曲部の調整が必要です。
Path { path in
var width: CGFloat = 100.0
let height = width
path.move(
to: CGPoint(
x: width * 0.95,
y: height * 0.20
)
)
}
y: height * (0.20 + HexagonParameters.adjustment)
として数値を追加し、
path.addQuadCurve(
to: CGPoint(
x: width * segment.curve.x,
y: height * segment.curve.y
),
control: CGPoint(
x: width * segment.control.x,
y: height * segment.control.y
)
)
カーブを追加します。
そしてここで
GeometryReader { geometry in
Path { path in
var width: CGFloat = min(geometry.size.width, geometry.size.height)
let height = width
path.move(
to: CGPoint(
x: width * 0.95,
y: height * (0.20 + HexagonParameters.adjustment)
)
)
}
GeometryReader
を使って実際の表示画面を取得して画面いっぱいの表示をするようにします。
次に
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
)
)
}
}
let xScale: CGFloat = 0.832
let xOffset = (width * (1.0 - xScale)) / 2.0
をセットして、"x"のパラメータの部分に"xOffset"を当てて、中央に持っていきます。。
最後に図形の背景の色を決めていきます。
.fill(LinearGradient(
gradient: Gradient(colors: [Self.gradientStart, Self.gradientEnd]),
startPoint: UnitPoint(x: 0.5, y: 0),
endPoint: UnitPoint(x: 0.5, y: 0.6)
))
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)
}
六角形の座標を決め、その背景までできました。
この記事が気に入ったらサポートをしてみませんか?