はじめに
日曜日で暇なので, SwiftUIを使ってドラえもんを作ってみました.
この記事で完成するドラえもんは以下の画像です.
口を開けているドラえもんは難しそうなので断念しました.
かなり本物に近くないですか?笑
さぁ作って行きましょう.
土台づくり
まず,以下の画像のような土台となる青の円とその中にある円から作って行きましょう.
ドラえもんって意識してませんでしたが,地味に楕円なんだと感じました.
確かによくよく見たら楕円なんですよね.
土台の色のみ,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 } )
}
}
}
目
次に目です.
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 } )
}
}
}
}
鼻
続いては鼻ですね.
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 } )
}
}
}
髭
ここまでくるとそれっぽくなってきました.
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 } )
}
}
}
口
最後に口です.
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)
}
}
完成
全文
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