LoginSignup
91
38

More than 3 years have passed since last update.

SwiftUIで作るドラえもん【顔編】

Last updated at Posted at 2020-03-01

はじめに

日曜日で暇なので, SwiftUIを使ってドラえもんを作ってみました.

この記事で完成するドラえもんは以下の画像です.
口を開けているドラえもんは難しそうなので断念しました.
かなり本物に近くないですか?笑

DoraFace

さぁ作って行きましょう.

土台づくり

まず,以下の画像のような土台となる青の円とその中にある円から作って行きましょう.
ドラえもんって意識してませんでしたが,地味に楕円なんだと感じました.
確かによくよく見たら楕円なんですよね.

土台の色のみ,Asset Catalogで色を管理しています.
(鼻も管理した方が良さそう...)

土台

以下コードです.

ContentView.swift

struct base: View {
    var body: some View {
        ZStack {
            // 土台
            Ellipse()
            .overlay(
              Ellipse()
             .stroke(Color.black,lineWidth: 2)
            )
            .frame(width: 300, height: 290)
            .foregroundColor(Color("DoraColor"))

            // 顔
            Ellipse()
                .frame(width: 270 , height: 250)
                .foregroundColor(Color.white)
                .overlay(
                  Ellipse()
                 .stroke(Color.black,lineWidth: 2)
                )
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 100 } )
        }
    }
}

次に目です.

eyeeye

ContentView.swift
struct eyes: View {
    var body: some View {
        HStack(spacing:0) {
            // 左目
            ZStack {
                Ellipse()
                    .frame(width: 60, height: 80)
                    .foregroundColor(Color.white)
                    .overlay(
                      Ellipse()
                     .stroke(Color.black,lineWidth: 2)
                    )
                ZStack {
                    Ellipse()
                        .frame(width: 20, height: 30)
                        .foregroundColor(Color.black)

                    Ellipse()
                        .frame(width:5, height: 10)
                        .foregroundColor(Color.white)
                }
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -5 })

            }

            ZStack {
                // 右目
                Ellipse()
                    .frame(width: 60, height: 80)
                    .foregroundColor(Color.white)
                    .overlay(
                      Ellipse()
                     .stroke(Color.black,lineWidth: 2)
                    )

                ZStack {
                    Ellipse()
                        .frame(width: 20, height: 30)
                        .foregroundColor(Color.black)

                    Ellipse()
                        .frame(width:5, height: 10)
                        .foregroundColor(Color.white)
                }
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 25 } )
            }
        }
    }
}

続いては鼻ですね.

nosenose

ContentView.swift
struct nose: View {
    var body: some View {
        Group {
            // 鼻
            ZStack{
                Circle()
                    .frame(width: 50, height: 50)
                    .foregroundColor(Color.red)
                    .overlay(
                      Ellipse()
                     .stroke(Color.black,lineWidth: 2)
                    )
                Circle()
                    .frame(width: 20, height: 10)
                    .foregroundColor(Color.white)
                    .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 20})
                    .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 15})
            }
            .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 60 } )

            // 人中?
            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 110, height: 2)
                .rotationEffect(Angle(degrees: 90))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -45 } )
        }
    }
}

ここまでくるとそれっぽくなってきました.

CatBeardCatBeard

ContentView.swift
struct CatBeard: View {
    var body: some View {
        Group {
            // 左髭
            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 120 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 0))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -20 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 120 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: -15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -50 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 120 } )

            // 右髭
            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: -15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -50 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 0))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -20 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -50 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -50 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -50 } )
        }
    }
}

最後に口です.

mouthmouth

ContentView.swift
struct Mouth: View {
    var body: some View {
        Circle()
            .trim(from: 0.05, to: 0.45)
            .stroke(Color.black,lineWidth: 3)
            .frame(width: 200, height: 200)
    }
}

完成

無理やりですがなんとか完成しました.
DoraFace

全文
ContentView.swift

import SwiftUI

struct base: View {
    var body: some View {
        ZStack {
            // 土台
            Ellipse()
            .overlay(
              Ellipse()
             .stroke(Color.black,lineWidth: 2)
            )
            .frame(width: 300, height: 290)
            .foregroundColor(Color("DoraColor"))

            // 顔
            Ellipse()
                .frame(width: 270 , height: 250)
                .foregroundColor(Color.white)
                .overlay(
                  Ellipse()
                 .stroke(Color.black,lineWidth: 2)
                )
                .alignmentGuide(.leading, computeValue: { _ in 10 } )
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 100 } )
        }
    }
}

struct eyes: View {
    var body: some View {
        HStack(spacing:0) {
            // 左目
            ZStack {
                Ellipse()
                    .frame(width: 60, height: 80)
                    .foregroundColor(Color.white)
                    .overlay(
                      Ellipse()
                     .stroke(Color.black,lineWidth: 2)
                    )
                ZStack {
                    Ellipse()
                        .frame(width: 20, height: 30)
                        .foregroundColor(Color.black)

                    Ellipse()
                        .frame(width:5, height: 10)
                        .foregroundColor(Color.white)
                }
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -5 })

            }

            ZStack {
                // 右目
                Ellipse()
                    .frame(width: 60, height: 80)
                    .foregroundColor(Color.white)
                    .overlay(
                      Ellipse()
                     .stroke(Color.black,lineWidth: 2)
                    )

                ZStack {
                    Ellipse()
                        .frame(width: 20, height: 30)
                        .foregroundColor(Color.black)

                    Ellipse()
                        .frame(width:5, height: 10)
                        .foregroundColor(Color.white)
                }
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 25 } )
            }
        }
    }
}

struct nose: View {
    var body: some View {
        Group {
            // 鼻
            ZStack{
                Circle()
                    .frame(width: 50, height: 50)
                    .foregroundColor(Color.red)
                    .overlay(
                      Ellipse()
                     .stroke(Color.black,lineWidth: 2)
                    )
                Circle()
                    .frame(width: 20, height: 10)
                    .foregroundColor(Color.white)
                    .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 20})
                    .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 15})
            }
            .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 60 } )
            // 人中?
            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 110, height: 2)
                .rotationEffect(Angle(degrees: 90))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -45 } )
        }
    }
}

struct CatBeard: View {
    var body: some View {
        Group {
            // 左髭
            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 120 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 0))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -20 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 120 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: -15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -50 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in 120 } )

            // 右髭
            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: -15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 10 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -50 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 0))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -20 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -50 } )

            Rectangle()
                .foregroundColor(Color.black)
                .frame(width: 70, height: 2)
                .rotationEffect(Angle(degrees: 15))
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in -50 } )
                .alignmentGuide(HorizontalAlignment.center, computeValue: { _ in -50 } )
        }
    }
}

struct Mouth: View {
    var body: some View {
        Circle()
            .trim(from: 0.05, to: 0.45)
            .stroke(Color.black,lineWidth: 3)
            .frame(width: 200, height: 200)
    }
}

struct DoraFace: View {
    var body: some View {
        ZStack{
            // 土台
            base()
            // 目
            eyes()
                .alignmentGuide(VerticalAlignment.center, computeValue: { _ in 130})
            // 鼻
            nose()
            // 髭
            CatBeard()
            // 口
            Mouth()
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack{
            Text("ドラえもん")
                .font(.largeTitle)
            DoraFace()
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

終わりに

あまり綺麗ではありませんが,なんとか完成させることができました.
次の暇な日曜日にでも綺麗なコードに修正していこうと思います.

ちなみに,今回のタイトルに,【顔編】とありますが,【体編】を作る予定はありません.笑

SwiftUI初心者なのでもっと良い書き方があればご教示ください.

GitHub URL: https://github.com/tukuyo/Doraemon_SwiftUI

91
38
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
91
38