こんにちはコーヤです。
このページでは、パスを使用して図形を描画する方法を紹介します。
以下のバージョンで動作確認しています。
- Xcode 13.4.1
- Swift 5.6.1
パスの概要
パスとは画面上に自由に描画できる機能です。
画面をxy座標として、座標を指定しながら線を引いていきます。
前提知識としてプログラミングにおけるxy座標系を抑えておきましょう。数学のxy座標系とは異なり、プログラミングのxy座標系は原点が左上にあり、x軸は右、y軸は下に伸びています。
直線の描画方法
直線を描画するときは、直線の始点と終点の2点を指定します。
始点の指定方法
.move(to: CGPoint(x: 始点の座標, y: 始点の座標))
moveを使うことで始点を移動することができます。
終点の指定方法
.addLine(to: CGPoint(x: 終点の座標, y: 終点の座標))
addLineの引数で終点を指定します。
struct ContentView: View {
var body: some View {
ZStack {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 200, y: 200))
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
}
}
連続しない直線を描画する場合
連続しない直線を描画する場合は途中でmoveを使って始点移動を行います。
struct ContentView: View {
var body: some View {
ZStack {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 200, y: 200))
path.move(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: 100, y: 200))
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
}
}
連続する直線を描画する場合
連続する直線を描画する場合はaddLineを連続して使えばOKです。前の直線の終点が次の直線の始点になります。
struct ContentView: View {
var body: some View {
ZStack {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 200, y: 200))
path.addLine(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: 100, y: 200))
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
}
}
他にもaddLinesを使用する方法があります。考え方は上記のaddLineと同じで、コードの書き方が若干異なるだけです。
.addLines([
CGPoint(x: 座標, y: 座標),
CGPoint(x: 座標, y: 座標),
...
CGPoint(x: 座標, y: 座標)
])
struct ContentView: View {
var body: some View {
ZStack {
Path { path in
path.addLines([
CGPoint(x: 0, y: 0),
CGPoint(x: 200, y: 200),
CGPoint(x: 0, y: 100),
CGPoint(x: 100, y: 200)
])
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
}
}
円弧の描画方法
.addArc(
center: CGPoint(x: 中心の座標, y: 中心の座標),
radius: 半径,
startAngle: .degrees(始点の偏角),
endAngle: .degrees(終点の偏角),
clockwise: 時計回り反時計回り
)
struct ContentView: View {
var body: some View {
HStack {
Spacer()
ZStack {
Path { path in
path.addArc(
center: CGPoint(x: 100, y: 100),
radius: 100,
startAngle: .degrees(0),
endAngle: .degrees(120),
clockwise: true
)
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
ZStack {
Path { path in
path.addArc(
center: CGPoint(x: 100, y: 100),
radius: 100,
startAngle: .degrees(0),
endAngle: .degrees(120),
clockwise: false
)
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
}
}
}
図形の描画方法
SwiftUIで用意されている図形をパスで描画することができます。
.addRect(CGRect(x: 中心の座標, y: 中心の座標, width: 横の長さ, height: 縦の長さ))
.addEllipse(in: CGRect(x: 中心の座標, y: 中心の座標, width: 横の長さ, height: 縦の長さ))
.addRoundedRect(in: CGRect(x: 中心の座標, y: 中心の座標, width: 横の長さ, height: 縦の長さ), cornerSize: CGSize(width: 角の横方向の半径, height: 角の縦方向の半径))
struct ContentView: View {
var body: some View {
HStack {
Spacer()
ZStack {
Path { path in
path.addRect(CGRect(x: 50, y: 25, width: 100, height: 150))
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
ZStack {
Path { path in
path.addEllipse(in: CGRect(x: 25, y: 50, width: 150, height: 100))
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
ZStack {
Path { path in
path.addRoundedRect(in: CGRect(x: 50, y: 50, width: 100, height: 100), cornerSize: CGSize(width: 20, height: 40))
}
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
}
}
}
閉曲線の注意点
始点と終点の座標を一致させても閉曲線にはなりません。閉曲線にするにはcloseSubpathを使います。
.closeSubpath()
struct ContentView: View {
var body: some View {
HStack {
Spacer()
ZStack {
Path { path in
path.addLines([
CGPoint(x: 100, y: 0),
CGPoint(x: 0, y: 200),
CGPoint(x: 200, y: 200),
CGPoint(x: 100, y: 00)
])
}
.stroke(Color.green, lineWidth: 30)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
ZStack {
Path { path in
path.addLines([
CGPoint(x: 100, y: 0),
CGPoint(x: 0, y: 200),
CGPoint(x: 200, y: 200),
CGPoint(x: 100, y: 00)
])
path.closeSubpath()
}
.stroke(Color.green, lineWidth: 30)
.frame(width: 200, height: 200)
Rectangle()
.stroke(Color.black, lineWidth: 2)
.frame(width: 200, height: 200)
}
Spacer()
}
}
}
以上です。ご参考になれば幸いです。
コメント欄