【じっくりSw1ftUI58】実践編28〜第40章 基本的なSwiftUIグラフィック描画
さてと、前回
まででメニュー画面については、一応終わったので、今回から
具体的にビューの中身を作る
ところに入ってく🕺
オイラの学びなんて要らないなんて人は、
にサンプルコードなんか全部転がってそうだから、そっちを参照してねん💦
んだば、今回も早速、
じっくり第20章を読んでく👓
概要としは、
SwiftUIでの描画
について書いてんね🌱
早速、動かしてこ
import SwiftUI
struct Essentials40ContentsView: View {
var body: some View {
E40DrawingStandardView()
}
}
struct E40DrawingStandardView: View {
var body: some View {
Rectangle()
}
}
#Preview {
Essentials40ContentsView()
}
てな感じで〜〜〜
ここでポイント①:だからモディファイアが重要
とまあ、上の2つの図を見ただけで、モディファイアがいかに重要かが分かる例だから敢えて表示してんだよね。
Shapeビューだけだとこーなっちゃうから、これと
モディファイア:いい感じに調整する
で自分で良さげなビューにするのがアプリクリエイターの仕事だからね🧐
さてと操作に戻って〜〜〜
モディファイアを追加する
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
Circle()
Circle()
.fill(.red)
.frame(width: 200,height: 200)
}
}
}
てな感じに変更してあげて
さらに、
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
.fill(.pink)
.frame(width: 250, height: 250)
Circle()
Circle()
.fill(.red)
.frame(width: 200,height: 200)
}
}
}
てやれば、
ここでポイント②:SafeAreaをどうするかは要求次第
流石にセーフエリアからはみ出してるとかっちょ悪いので〜〜〜
import SwiftUI
struct Essentials40ContentsView: View {
var body: some View {
ScrollView{
E40DrawingStandardView()
}
.safeAreaPadding()
}
}
struct E40DrawingStandardView: View {
var body: some View {
Rectangle()
.fill(.pink)
.frame(width: 250, height: 250)
Circle()
Circle()
.fill(.red)
.frame(width: 200,height: 200)
}
}
#Preview {
Essentials40ContentsView()
}
てな感じで変更してあげて
要求次第で、はみ出てる方がいいって場合もあれば、セーフエリア内で収めてほしいって場合もあるので、どちらにも対応できるように、メソッドやモディファイアをその時に使えるようにしとけばいいだけの話。
ま、当たり前の話だけど👀💦
さてと、本編の続きに戻って
struct E40DrawingStandardView: View {
var body: some View {
Rectangle()
.fill(.pink)
.frame(width: 250, height: 250)
Circle()
.stroke(lineWidth: 10)
.fill(.green)
.frame(width: 250,height: 250)
Circle()
.fill(.red)
.frame(width: 200,height: 200)
}
}
上から2番目をCapsule()ビューに変更してみると、、、
struct E40DrawingStandardView: View {
var body: some View {
Rectangle()
.fill(.pink)
.frame(width: 250, height: 250)
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
Circle()
.fill(.red)
.frame(width: 200,height: 200)
}
}
破線で表示
import SwiftUI
struct Essentials40ContentsView: View {
var body: some View {
ScrollView{
E40DrawingStandardView()
}
.safeAreaPadding()
}
}
struct E40DrawingStandardView: View {
var body: some View {
Rectangle()
.fill(.pink)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
Circle()
.fill(.red)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
RoundedRectangle(cornerRadius: CGFloat(15))
.stroke(style: StrokeStyle(lineWidth: 15,dash: [CGFloat(10)]))
.foregroundStyle(.cyan)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
}
}
#Preview {
Essentials40ContentsView()
}
さらに、
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
.fill(.pink)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Circle()
.fill(.red)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
RoundedRectangle(cornerRadius: CGFloat(15))
.stroke(style: StrokeStyle(lineWidth: 15,dash: [CGFloat(10)]))
.foregroundStyle(.cyan)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.stroke(style: StrokeStyle(lineWidth:25,dash: [CGFloat(11),CGFloat(4),CGFloat(8)],dashPhase: CGFloat(12)))
.foregroundStyle(.brown)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
オーバーレイを使う
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
.fill(.pink)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Circle()
.fill(.red)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
RoundedRectangle(cornerRadius: CGFloat(15))
.stroke(style: StrokeStyle(lineWidth: 15,dash: [CGFloat(10)]))
.foregroundStyle(.cyan)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.stroke(style: StrokeStyle(lineWidth:25,dash: [CGFloat(11),CGFloat(4),CGFloat(8)],dashPhase: CGFloat(12)))
.foregroundStyle(.brown)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.fill(.orange)
.overlay(Ellipse().stroke(.blue,lineWidth: 15))
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
Pathを使う
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
てなビューを追加して、
ここでポイント③:Pathで使うメソッド
addArc – 半径と角度の値に基づいて円弧を追加。
addCurve – 指定された終点と制御点を使用して 3 次ベジェ曲線を追加。
addLine – 指定されたポイントで終わる直線を追加。
addLines – 指定された終点の配列間に直線を追加。
addQuadCurve – 指定された制御点と終点を使用して二次ベジェ曲線を追加。
closeSubPath – 終了点を開始点に接続してパスを閉じる。
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.fill(.purple)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
て感じでfillメソッドを追加するだけで
構造体に定義もできる
struct E40Shape:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.minY),control: CGPoint(x: rect.minX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.closeSubpath()
return path
}
}
みたいな構造体を追加して、
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.fill(.purple)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
E40Shape()
.fill(.yellow)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
てな感じで追加すると
struct E40Shape2:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY),control: CGPoint(x: rect.maxX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}
みたいにして、XとYの値を変更するだけで、
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.fill(.purple)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
E40Shape()
.fill(.yellow)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
E40Shape2()
.fill(.green)
.frame(minWidth: 350,maxWidth: .infinity,minHeight: 360,maxHeight: .infinity)
.padding()
}
}
で追加すると、
グラデーションと影
struct E40DrawingGradientShadowView: View {
var body: some View {
ScrollView{
HStack{
//Gradient
Circle()
.fill(.pink.gradient)
.frame(width: 100,height: 100)
//Shadow.drop
Circle()
.fill(.pink.shadow(.drop(color: .black, radius: 10)))
.frame(width: 100,height: 100)
//Shadow.inner
Circle()
.fill(.pink.shadow(.inner(color: .black, radius: 10)))
.frame(width: 100,height: 100)
}
}
}
}
てな感じでビューを追加すると
グラデーションで遊ぶと、、、
struct E40DrawingGradientShadowView: View {
let gradientColors = Gradient(colors: [
Color.red,
Color.yellow,
Color.green,
Color.blue,
Color.orange,
Color.purple,
Color.pink,
Color.brown,
Color.cyan
])
var body: some View {
ScrollView{
VStack{
HStack{
//Gradient
Circle()
.fill(.pink.gradient)
.frame(width: 100,height: 100)
//Shadow.drop
Circle()
.fill(.pink.shadow(.drop(color: .black, radius: 10)))
.frame(width: 100,height: 100)
//Shadow.inner
Circle()
.fill(.pink.shadow(.inner(color: .black, radius: 10)))
.frame(width: 100,height: 100)
}
Circle()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(360)))
}
}
}
}
Circle()
.fill(AngularGradient(
gradient: gradientColors,
center: .center)
)
をさらに追加すると、
Rectangle()
.fill(LinearGradient(
gradient: gradientColors,
startPoint: .leading,
endPoint: .trailing
))
.frame(width: 300,height: 300)
でやってみると〜〜〜
さっき自分で作った構造体にもグラデをつけると〜〜〜〜
E40Shape()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(180)))
.frame(width: 300,height: 300)
.background(LinearGradient(
gradient:Gradient(
colors: [
Color.white,
Color.blue
]),
startPoint: .leading,
endPoint: .trailing))
}
以上。
今回のまとめコード
import SwiftUI
struct Essentials40ContentsView: View {
var body: some View {
ScrollView{
E40DrawingStandardView()
E40DrawingPathView()
E40DrawingGradientShadowView()
}
.safeAreaPadding()
}
}
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
.fill(.pink)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Circle()
.fill(.red)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
RoundedRectangle(cornerRadius: CGFloat(15))
.stroke(style: StrokeStyle(lineWidth: 15,dash: [CGFloat(10)]))
.foregroundStyle(.cyan)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.stroke(style: StrokeStyle(lineWidth:25,dash: [CGFloat(11),CGFloat(4),CGFloat(8)],dashPhase: CGFloat(12)))
.foregroundStyle(.brown)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.fill(.orange)
.overlay(Ellipse().stroke(.blue,lineWidth: 15))
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
struct E40Shape:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.minY),control: CGPoint(x: rect.minX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct E40Shape2:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY),control: CGPoint(x: rect.maxX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.fill(.purple)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
E40Shape()
.fill(.yellow)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
E40Shape2()
.fill(.green)
.frame(minWidth: 350,maxWidth: .infinity,minHeight: 360,maxHeight: .infinity)
.padding()
}
}
struct E40DrawingGradientShadowView: View {
let gradientColors = Gradient(colors: [
Color.red,
Color.yellow,
Color.green,
Color.blue,
Color.orange,
Color.purple,
Color.pink,
Color.brown,
Color.cyan
])
var body: some View {
ScrollView{
VStack{
HStack{
//Gradient
Circle()
.fill(.pink.gradient)
.frame(width: 100,height: 100)
//Shadow.drop
Circle()
.fill(.pink.shadow(.drop(color: .black, radius: 10)))
.frame(width: 100,height: 100)
//Shadow.inner
Circle()
.fill(.pink.shadow(.inner(color: .black, radius: 10)))
.frame(width: 100,height: 100)
}
Circle()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(360)))
Circle()
.fill(AngularGradient(
gradient: gradientColors,
center: .center)
)
Rectangle()
.fill(LinearGradient(
gradient: gradientColors,
startPoint: .leading,
endPoint: .trailing
))
.frame(width: 300,height: 300)
E40Shape()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(180)))
.frame(width: 300,height: 300)
.background(LinearGradient(
gradient:Gradient(
colors: [
Color.white,
Color.blue
]
),
startPoint: .leading,
endPoint: .trailing)
)
}
}
}
}
#Preview {
Essentials40ContentsView()
}
Apple公式
さてと、次回は
描画の基本もわかったところで、
第41章 SwiftUI アニメーションとトランジション
をやってく〜〜〜
記事公開後、
いつもどおり、
でやった操作を〜〜〜
サンプルコード
◆Essentials40.swift
import SwiftUI
import WebKit
//タイトル
let essentialsChapter40NavigationTitle = "第40章"
let essentialsChapter40Title = "第40章 基本的なSwiftUIグラフィック描画"
let essentialsChapter40SubTitle = "第40章 基本的なSwiftUIグラフィック描画"
//コード
let codeEssentials40 = """
struct Essentials40ContentsView: View {
var body: some View {
ScrollView{
E40DrawingStandardView()
E40DrawingPathView()
E40DrawingGradientShadowView()
}
.safeAreaPadding()
}
}
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
.fill(.pink)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Circle()
.fill(.red)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
RoundedRectangle(cornerRadius: CGFloat(15))
.stroke(style: StrokeStyle(lineWidth: 15,dash: [CGFloat(10)]))
.foregroundStyle(.cyan)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.stroke(style: StrokeStyle(lineWidth:25,dash: [CGFloat(11),CGFloat(4),CGFloat(8)],dashPhase: CGFloat(12)))
.foregroundStyle(.brown)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.fill(.orange)
.overlay(Ellipse().stroke(.blue,lineWidth: 15))
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
struct E40Shape:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.minY),control: CGPoint(x: rect.minX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct E40Shape2:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY),control: CGPoint(x: rect.maxX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.fill(.purple)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
E40Shape()
.fill(.yellow)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
E40Shape2()
.fill(.green)
.frame(minWidth: 350,maxWidth: .infinity,minHeight: 360,maxHeight: .infinity)
.padding()
}
}
struct E40DrawingGradientShadowView: View {
let gradientColors = Gradient(colors: [
Color.red,
Color.yellow,
Color.green,
Color.blue,
Color.orange,
Color.purple,
Color.pink,
Color.brown,
Color.cyan
])
var body: some View {
ScrollView{
VStack{
HStack{
//Gradient
Circle()
.fill(.pink.gradient)
.frame(width: 100,height: 100)
//Shadow.drop
Circle()
.fill(.pink.shadow(.drop(color: .black, radius: 10)))
.frame(width: 100,height: 100)
//Shadow.inner
Circle()
.fill(.pink.shadow(.inner(color: .black, radius: 10)))
.frame(width: 100,height: 100)
}
Circle()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(360)))
Circle()
.fill(AngularGradient(
gradient: gradientColors,
center: .center)
)
Rectangle()
.fill(LinearGradient(
gradient: gradientColors,
startPoint: .leading,
endPoint: .trailing
))
.frame(width: 300,height: 300)
E40Shape()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(180)))
.frame(width: 300,height: 300)
.background(LinearGradient(
gradient:Gradient(
colors: [
Color.white,
Color.blue
]
),
startPoint: .leading,
endPoint: .trailing)
)
}
}
}
}
#Preview {
Essentials40ContentsView()
}
"""
//ポイント
let pointEssentials40 = """
1、だからモディファイアが重要
とまあ、上の2つの図を見ただけで、モディファイアがいかに重要かが分かる例だから敢えて表示してんだよね。Shapeビューだけだとこーなっちゃうから、これとモディファイア:いい感じに調整するで自分で良さげなビューにするのがアプリクリエイターの仕事だからね🧐
2、SafeAreaをどうするかは要求次第
流石にセーフエリアからはみ出してるとかっちょ悪いので〜〜〜要求次第で、はみ出てる方がいいって場合もあれば、セーフエリア内で収めてほしいって場合もあるので、どちらにも対応できるように、メソッドやモディファイアをその時に使えるようにしとけばいいだけの話。
ま、当たり前の話だけど👀💦
3、Pathで使うメソッド
⚫︎addArc – 半径と角度の値に基づいて円弧を追加。
⚫︎addCurve – 指定された終点と制御点を使用して3 次ベジェ曲線を追加。
⚫︎addLine – 指定されたポイントで終わる直線を追加。
⚫︎addLines – 指定された終点の配列間に直線を追加。
⚫︎addQuadCurve – 指定された制御点と終点を使用して二次ベジェ曲線を追加。
⚫︎closeSubPath – 終了点を開始点に接続してパスを閉じる。
"""
//URL
let urlEssentials40 = "https://note.com/m_kakudo/n/n8d37d5d8e96b"
//ビュー管理構造体
struct ListiOSApp17DevelopmentEssentialsCh40: Identifiable {
var id: Int
var title: String
var view: ViewEnumiOSApp17DevelopmentEssentialsCh40
}
//遷移先の画面を格納する列挙型
enum ViewEnumiOSApp17DevelopmentEssentialsCh40{
case Sec1
}
//各項目に表示するリスト項目
let dataiOSApp17DevelopmentEssentialsCh40: [ListiOSApp17DevelopmentEssentialsCh40] = [
ListiOSApp17DevelopmentEssentialsCh40(id: 1, title: essentialsChapter40SubTitle, view: .Sec1),
]
struct iOSApp17DevelopmentEssentialsCh40: View {
var body: some View {
VStack {
Divider()
List (dataiOSApp17DevelopmentEssentialsCh40) { data in
self.containedViewiOSApp17DevelopmentEssentialsCh40(dataiOSApp17DevelopmentEssentialsCh40: data)
}
.edgesIgnoringSafeArea([.bottom])
}
.navigationTitle(essentialsChapter40NavigationTitle)
.navigationBarTitleDisplayMode(.inline)
}
//タップ後に遷移先へ遷移させる関数
func containedViewiOSApp17DevelopmentEssentialsCh40(dataiOSApp17DevelopmentEssentialsCh40: ListiOSApp17DevelopmentEssentialsCh40) -> AnyView {
switch dataiOSApp17DevelopmentEssentialsCh40.view {
case .Sec1:
return AnyView(NavigationLink (destination: Essentials40()) {
Text(dataiOSApp17DevelopmentEssentialsCh40.title)
})
}
}
}
#Preview {
iOSApp17DevelopmentEssentialsCh40()
}
struct Essentials40: View {
var body: some View {
VStack{
TabView {
Essentials40ContentsView()
.tabItem {
Image(systemName: contentsImageTab)
Text(contentsTextTab)
}
Essentials40Code()
.tabItem {
Image(systemName: codeImageTab)
Text(codeTextTab)
}
Essentials40Points()
.tabItem {
Image(systemName: pointImageTab)
Text(pointTextTab)
}
Essentials40WEB()
.tabItem {
Image(systemName: webImageTab)
Text(webTextTab)
}
}
}
}
}
#Preview {
Essentials40()
}
struct Essentials40Code: View {
var body: some View {
ScrollView{
Text(codeEssentials40)
}
}
}
#Preview {
Essentials40Code()
}
struct Essentials40Points: View {
var body: some View {
ScrollView{
Text(pointEssentials40)
}
}
}
#Preview {
Essentials40Points()
}
struct Essentials40WebView: UIViewRepresentable {
let searchURL: URL
func makeUIView(context: Context) -> WKWebView {
let view = WKWebView()
let request = URLRequest(url: searchURL)
view.load(request)
return view
}
func updateUIView(_ uiView: WKWebView, context: Context) {
}
}
struct Essentials40WEB: View {
private var url:URL = URL(string: urlEssentials40)!
var body: some View {Essentials40WebView(searchURL: url)
}
}
#Preview {
Essentials40WEB()
}
struct Essentials40ContentsView: View {
var body: some View {
ScrollView{
E40DrawingStandardView()
E40DrawingPathView()
E40DrawingGradientShadowView()
}
.safeAreaPadding()
}
}
struct E40DrawingStandardView: View {
var body: some View {
ScrollView{
Rectangle()
.fill(.pink)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Capsule()
.stroke(lineWidth: 10)
.fill(.green)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Circle()
.fill(.red)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
RoundedRectangle(cornerRadius: CGFloat(15))
.stroke(style: StrokeStyle(lineWidth: 15,dash: [CGFloat(10)]))
.foregroundStyle(.cyan)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.stroke(style: StrokeStyle(lineWidth:25,dash: [CGFloat(11),CGFloat(4),CGFloat(8)],dashPhase: CGFloat(12)))
.foregroundStyle(.brown)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
Ellipse()
.fill(.orange)
.overlay(Ellipse().stroke(.blue,lineWidth: 15))
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
}
}
struct E40Shape:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.minY),control: CGPoint(x: rect.minX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct E40Shape2:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to:CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY),control: CGPoint(x: rect.maxX, y: rect.midY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct E40DrawingPathView: View {
var body: some View {
ScrollView{
Path{ path in
path.move(to:CGPoint(x:8,y:0))
path.addLine(to: CGPoint(x:100,y:320))
path.addLine(to: CGPoint(x: 270, y: 270))
path.closeSubpath()
}
.fill(.purple)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
}
E40Shape()
.fill(.yellow)
.frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
.padding()
E40Shape2()
.fill(.green)
.frame(minWidth: 350,maxWidth: .infinity,minHeight: 360,maxHeight: .infinity)
.padding()
}
}
struct E40DrawingGradientShadowView: View {
let gradientColors = Gradient(colors: [
Color.red,
Color.yellow,
Color.green,
Color.blue,
Color.orange,
Color.purple,
Color.pink,
Color.brown,
Color.cyan
])
var body: some View {
ScrollView{
VStack{
HStack{
//Gradient
Circle()
.fill(.pink.gradient)
.frame(width: 100,height: 100)
//Shadow.drop
Circle()
.fill(.pink.shadow(.drop(color: .black, radius: 10)))
.frame(width: 100,height: 100)
//Shadow.inner
Circle()
.fill(.pink.shadow(.inner(color: .black, radius: 10)))
.frame(width: 100,height: 100)
}
Circle()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(360)))
Circle()
.fill(AngularGradient(
gradient: gradientColors,
center: .center)
)
Rectangle()
.fill(LinearGradient(
gradient: gradientColors,
startPoint: .leading,
endPoint: .trailing
))
.frame(width: 300,height: 300)
E40Shape()
.fill(RadialGradient(
gradient: gradientColors,
center: .center,
startRadius: CGFloat(0),
endRadius: CGFloat(180)))
.frame(width: 300,height: 300)
.background(LinearGradient(
gradient:Gradient(
colors: [
Color.white,
Color.blue
]
),
startPoint: .leading,
endPoint: .trailing)
)
}
}
}
}
#Preview {
Essentials40ContentsView()
}
◆EssentialsMenu.swift
//フレームワーク
import SwiftUI
import WebKit
//ビュー管理構造体
struct ListiOSApp17DevelopmentEssentials: Identifiable {
var id: Int
var title: String
var view: ViewEnumiOSApp17DevelopmentEssentials
}
//遷移先の画面を格納する列挙型
enum ViewEnumiOSApp17DevelopmentEssentials {
case Ch1
//じっくり13で追加
case Ch2
//じっくり14で追加
case Ch3
//じっくり15で追加
case Ch4
//じっくり16で追加
case Ch5
//じっくり17で追加
case Ch6
//じっくり18で追加
case Ch7
//じっくり19で追加
case Ch8
//じっくり20、21で追加
case Ch9
//じっくり22、23で追加
case Ch10
//じっくり24で追加
case Ch11
//じっくり25で追加
case Ch12
//じっくり26で追加
case Ch13
//じっくり27,28で追加
case Ch14
//じっくり29で追加
case Ch15
//じっくり31で追加
case Ch16
//じっくり32で追加
case Ch17
//じっくり33で追加
case Ch18
//じっくり34で追加
case Ch19
//じっくり35で追加
case Ch20
//じっくり36で追加
case Ch21
//じっくり37で追加
case Ch22
//じっくり40で追加
case Ch23
//じっくり41で追加
case Ch24
//じっくり43で追加
case Ch25
//じっくり44で追加
case Ch26
//じっくり45で追加
case Ch27
//じっくり46で追加
case Ch28
//じっくり47で追加
case Ch29
//じっくり48で追加
case Ch30
//じっくり49で追加
case Ch31
//じっくり50で追加
case Ch32
//じっくり51で追加
case Ch33
//じっくり52で追加
case Ch34
//じっくり53で追加
case Ch35
//じっくり54で追加
case Ch36
//じっくり55で追加
case Ch37
//じっくり56で追加
case Ch38
//じっくり57で追加
case Ch39
//じっくり58で追加
case Ch40
}
//各項目に表示する文字列
let dataiOSApp17DevelopmentEssentials: [ListiOSApp17DevelopmentEssentials] = [
ListiOSApp17DevelopmentEssentials(id: 1, title: essentialsChapter1Title, view: .Ch1),
//じっくり13で追加
ListiOSApp17DevelopmentEssentials(id: 2, title: essentialsChapter2Title, view: .Ch2),
//じっくり13で追加
ListiOSApp17DevelopmentEssentials(id: 3, title: essentialsChapter3Title, view: .Ch3),
//じっくり15で追加
ListiOSApp17DevelopmentEssentials(id: 4, title: essentialsChapter4Title, view: .Ch4),
//じっくり16で追加
ListiOSApp17DevelopmentEssentials(id: 5, title: essentialsChapter5Title, view: .Ch5),
//じっくり17で追加
ListiOSApp17DevelopmentEssentials(id: 6, title: essentialsChapter6Title, view: .Ch6),
//じっくり18で追加
ListiOSApp17DevelopmentEssentials(id: 7, title: essentialsChapter7Title, view: .Ch7),
//じっくり19で追加
ListiOSApp17DevelopmentEssentials(id: 8, title: essentialsChapter8Title, view: .Ch8),
//じっくり20、21で追加
ListiOSApp17DevelopmentEssentials(id: 9, title: essentialsChapter9Title, view: .Ch9),
//じっくり22、23で追加
ListiOSApp17DevelopmentEssentials(id: 10, title: essentialsChapter10Title, view: .Ch10),
//じっくり24で追加
ListiOSApp17DevelopmentEssentials(id: 11, title: essentialsChapter11Title, view: .Ch11),
//じっくり25で追加
ListiOSApp17DevelopmentEssentials(id: 12, title: essentialsChapter12Title, view: .Ch12),
//じっくり26で追加
ListiOSApp17DevelopmentEssentials(id: 13, title: essentialsChapter13Title, view: .Ch13),
//じっくり27,28で追加
ListiOSApp17DevelopmentEssentials(id: 14, title: essentialsChapter14Title, view: .Ch14),
//じっくり29で追加
ListiOSApp17DevelopmentEssentials(id: 15, title: essentialsChapter15Title, view: .Ch15),
//じっくり31で追加
ListiOSApp17DevelopmentEssentials(id: 16, title: essentialsChapter16Title, view: .Ch16),
//じっくり32で追加
ListiOSApp17DevelopmentEssentials(id: 17, title: essentialsChapter17Title, view: .Ch17),
//じっくり33で追加
ListiOSApp17DevelopmentEssentials(id: 18, title: essentialsChapter18Title, view: .Ch18),
//じっくり34で追加
ListiOSApp17DevelopmentEssentials(id: 19, title: essentialsChapter19Title, view: .Ch19),
//じっくり35で追加
ListiOSApp17DevelopmentEssentials(id: 20, title: essentialsChapter20Title, view: .Ch20),
//じっくり36で追加
ListiOSApp17DevelopmentEssentials(id: 21, title: essentialsChapter21Title, view: .Ch21),
//じっくり37で追加
ListiOSApp17DevelopmentEssentials(id: 22, title: essentialsChapter22Title, view: .Ch22),
//じっくり40で追加
ListiOSApp17DevelopmentEssentials(id: 23, title: essentialsChapter23Title, view: .Ch23),
//じっくり41で追加
ListiOSApp17DevelopmentEssentials(id: 24, title: essentialsChapter24Title, view: .Ch24),
//じっくり43で追加
ListiOSApp17DevelopmentEssentials(id: 25, title: essentialsChapter25Title, view: .Ch25),
//じっくり44で追加
ListiOSApp17DevelopmentEssentials(id: 26, title: essentialsChapter26Title, view: .Ch26),
//じっくり45で追加
ListiOSApp17DevelopmentEssentials(id: 27, title: essentialsChapter27Title, view: .Ch27),
//じっくり46で追加
ListiOSApp17DevelopmentEssentials(id: 28, title: essentialsChapter28Title, view: .Ch28),
//じっくり47で追加
ListiOSApp17DevelopmentEssentials(id: 29, title: essentialsChapter29Title, view: .Ch29),
//じっくり48で追加
ListiOSApp17DevelopmentEssentials(id: 30, title: essentialsChapter30Title, view: .Ch30),
//じっくり49で追加
ListiOSApp17DevelopmentEssentials(id: 31, title: essentialsChapter31Title, view: .Ch31),
//じっくり50で追加
ListiOSApp17DevelopmentEssentials(id: 32, title: essentialsChapter32Title, view: .Ch32),
//じっくり51で追加
ListiOSApp17DevelopmentEssentials(id: 33, title: essentialsChapter33Title, view: .Ch33),
//じっくり52で追加
ListiOSApp17DevelopmentEssentials(id: 34, title: essentialsChapter34Title, view: .Ch34),
//じっくり53で追加
ListiOSApp17DevelopmentEssentials(id: 35, title: essentialsChapter35Title, view: .Ch35),
//じっくり54で追加
ListiOSApp17DevelopmentEssentials(id: 36, title: essentialsChapter36Title, view: .Ch36),
//じっくり55で追加
ListiOSApp17DevelopmentEssentials(id: 37, title: essentialsChapter37Title, view: .Ch37),
//じっくり56で追加
ListiOSApp17DevelopmentEssentials(id: 38, title: essentialsChapter38Title, view: .Ch38),
//じっくり57で追加
ListiOSApp17DevelopmentEssentials(id: 39, title: essentialsChapter39Title, view: .Ch39),
//じっくり58で追加
ListiOSApp17DevelopmentEssentials(id: 40, title: essentialsChapter40Title, view: .Ch40),
]
struct iOSApp17DevelopmentEssentials: View {
var body: some View {
VStack {
Divider()
List (dataiOSApp17DevelopmentEssentials) { data in
self.containedViewiOSApp17DevelopmentEssentials(dataiOSApp17DevelopmentEssentials: data)
}
.edgesIgnoringSafeArea([.bottom])
}
.navigationTitle("iOS開発の章目次")
.navigationBarTitleDisplayMode(.inline)
}
//タップ後に遷移先へ遷移させる関数
func containedViewiOSApp17DevelopmentEssentials(dataiOSApp17DevelopmentEssentials: ListiOSApp17DevelopmentEssentials) -> AnyView {
switch dataiOSApp17DevelopmentEssentials.view {
case .Ch1:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh1()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり13で追加
case .Ch2:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh2()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり13で追加
case .Ch3:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh3()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり15で追加
case .Ch4:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh4()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり16で追加
case .Ch5:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh5()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり17で追加
case .Ch6:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh6()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり18で追加
case .Ch7:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh7()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり19で追加
case .Ch8:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh8()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり20、21で追加
case .Ch9:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh9()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり22、23で追加
case .Ch10:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh10()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり24で追加
case .Ch11:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh11()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり25で追加
case .Ch12:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh12()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり26で追加
case .Ch13:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh13()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり27,28で追加
case .Ch14:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh14()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり29で追加
case .Ch15:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh15()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり31で追加
case .Ch16:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh16()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり32で追加
case .Ch17:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh17()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり33で追加
case .Ch18:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh18()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり34で追加
case .Ch19:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh19()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり35で追加
case .Ch20:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh20()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり36で追加
case .Ch21:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh21()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり37で追加
case .Ch22:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh22()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり40で追加
case .Ch23:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh23()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり41で追加
case .Ch24:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh24()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり43で追加
case .Ch25:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh25()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり44で追加
case .Ch26:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh26()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり45で追加
case .Ch27:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh27()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり46で追加
case .Ch28:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh28()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり47で追加
case .Ch29:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh29()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり48で追加
case .Ch30:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh30()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり49で追加
case .Ch31:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh31()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり50で追加
case .Ch32:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh32()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり51で追加
case .Ch33:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh33()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり52で追加
case .Ch34:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh34()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり53で追加
case .Ch35:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh35()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり54で追加
case .Ch36:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh36()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり55で追加
case .Ch37:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh37()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり56で追加
case .Ch38:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh38()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり57で追加
case .Ch39:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh39()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
//じっくり58で追加
case .Ch40:
return AnyView(NavigationLink (destination: iOSApp17DevelopmentEssentialsCh40()) {
Text(dataiOSApp17DevelopmentEssentials.title)
})
}
}
}
#Preview {
iOSApp17DevelopmentEssentials()
}
以上。
さてと、今日は今から新聞の続きと文藝春秋ちゃんだけで
明日からまた仕事楽しもうっと🕺