DADAHAE's Log
비싼 장난감 가지고 노는 중 (❁´▽`❁)*✲゚*
[TIL] 22-10-20: Typography, SwiftUI 기초(숫자 게임)
22-10-20 목요일
6주차

 

 

 

 

🦢 SwiftUI

 

✔️ SwiftUI Demo 앱 만들기

  • @State
  • Slider
    • value : 실수형 값, 바인딩을 넣어야 한다고 강제
    • in : 어디부터 어디까지 범위
  • TextField
    • .textFieldStyle(RoundedBorderTextFieldStyle())
  • Picker
  • Spacer
  • Divider
  • AsyncImage

 

import SwiftUI

struct ContentView: View {
    
    var colors: [Color] = [.black, .red, .green, .blue]
    var colornames = ["Black", "Red", "Green", "Blue"]
    
    @State private var colorIndex = 0
    @State private var rotation: Double = 0
    @State private var text: String = "welcome to swiftUI"
    
    var body: some View {
        
        VStack {
            AsyncImage(url: URL(string: "<https://img.sbs.co.kr/newsnet/etv/upload/2022/09/19/30000790950_1280.jpg>")) { image in
                image.resizable()
            } placeholder: {
                ProgressView()
            }
            .aspectRatio(contentMode: .fit)
            
            Spacer()
            Text(text)
                .font(.largeTitle)
                .fontWeight(.heavy)
                .rotationEffect(.degrees(self.rotation))
                .animation(.easeInOut(duration:1), value: self.rotation)
                .foregroundColor(self.colors[self.colorIndex])
            Spacer()
            Divider()
            
            // 실수형 값, 어디부터 어디까지 범위!
            Slider(value: $rotation, in: 0...360, step: 0.1)
            
            TextField("Enter text here", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
            
            Picker(selection: $colorIndex, label: Text("color")) {
                ForEach (0 ..< colornames.count, id: \\.self) {
                    Text(self.colornames[$0])
                        .foregroundColor(self.colors[$0])
                }
            }.padding()
            
        }
        .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

 

 

 

✔️ Mission: 숫자 맞추기 앱

Apple Developer Documentation

 

Apple Developer Documentation

 

developer.apple.com

1.  특정한 숫자 규칙을 만든다.

2.  ex) 1~100 사이의 정수

3.  숫자 규칙에 맞는 랜덤한 숫자를 고르고, 사용자에게 보여주지 않는다.

4.  사용자는 텍스트 입력(혹은 다른 방법)으로 숫자를 입력한다.

  • 숫자를 맞추면 축하 메시지와 함께 다음 판을 시작한다.
  • 숫자를 맞추지 못하면 Up, Down으로 상황을 알려준다 (option)

 

ver 1. 간단한 숫자 맞추기 앱

 

더보기

전체 코드

 

import SwiftUI

struct ContentView: View {
    @State private var num = Int.random(in: 0...100)
    @State private var inputText: String = ""
    @State private var isAnswer: Bool = false
    @State private var result: String = "두근두근..."
    
    var body: some View {
        VStack {
            Text("당신의 숫자는?")
                .font(.largeTitle)
                .fontWeight(.bold)
                .padding()
            Spacer()
            
            Text(isAnswer ? "\(num)으로 정답입니다." : "1~100까지 정수를 맞춰보세요!")
            
            HStack {
                TextField("1부터 100까지 숫자를 입력해주세요.", text: $inputText)
                    .textFieldStyle(.roundedBorder)
                    
                Button("확인", action: {
                    guard let userInput = Int(inputText) else {
                        print("입력값을 넣어주세요.")
                        return
                    }
                    if (userInput == num){
                        self.result = "축하합니다."
                        self.isAnswer = true
                    } else if (userInput > num) {
                        self.result = "Down"
                    } else {
                        self.result = "Up"
                    }
                }).padding()
            }
            
            Spacer()
            
            Label(self.result, systemImage: "gamecontroller.fill")
            
            Button("새로 하시겠어요?") {
                self.num = Int.random(in: 0...100)
                self.result = "두근두근..."
            }
            .padding()
        }
        .padding()
    }
}

 

 

 

ver 2. 팀원들과 함께 만들어보기

컨셉은 타짜다. 욕심내서 이것저것 많이 건드려보았다.

 

ㅋㅋㅋ 재밌었다… 팀원 분들이 사진도 준비해주시고, 아이디어도 많이 적용해주셔서 재밌게 작업할 수 있었다. 헷

  • ‘확인 들어갑니다~’ Button
    • 랜덤 숫자 확인
    • 숫자는 아래 광 이미지에 보여진다.
  • ‘깽판’ Button
    • RESET
  • ‘예림이 그패 봐봐~’ TextField
    • 숫자를 입력한다.
  • ‘사쿠라여?’ Button
    • 입력한 숫자가 맞는지 확인한다.
  • Image
    • 조승우(숫자 나올 곳을 가리키고 있음)
    • Up, Down, Default, 맞춤
      • 입력한 숫자가 랜덤 숫자에 맞거나 up, down에 따라 이미지가 달리 출력된다.

 

더보기

전체 코드

 

import SwiftUI

struct ContentView: View {
    // 상태 프로퍼티 (순서대로)
    // 랜덤 넘버, 사용자 입력값, 상태 구분자, 토글 상태
    @State private var randomNum: Int = 0
    @State private var userAnswer: String = ""
    @State private var index = 3
    @State private var toggleStatus: Bool = false

    var body: some View {
        ZStack{
            // 배경 컬러 지정
            Color(red: 54 / 255, green: 67 / 255, blue: 37 / 255)
                .ignoresSafeArea()

            VStack {                
                HStack {
                    // 토글 버튼으로 정답 확인
                    Toggle(isOn: self.$toggleStatus) {
                      Text("확인 들어갑니다~")
                    }
	                    .toggleStyle(.button)
                    
                    Spacer()
                    
                    // 랜덤 넘버 리셋
                    Button("깽판") {
                        self.randomNum = Int.random(in: 1...100)
                        self.index = 3
                    }
	                    .font(.largeTitle)
	                    .frame(alignment: .trailing)
	                    .foregroundColor(Color.red)
	                    .buttonStyle(.bordered
                }
               
                HStack{
                    Spacer()
                    ZStack{
                        // 배경이 지정(화투패)
                        Image("newCard")
                            .resizable()
                            .frame(width: 70, height: 110)
                        
                        // 정답 숫자 (토글 버튼으로 표시 on/off)
                        Text(toggleStatus ? String(randomNum) : "")
                            .font(.largeTitle)
                            .foregroundColor(.black)
                            .padding(.bottom)
                    }

                    Image("basic")
                        .resizable()
                        .frame(width: 250, height: 150)
                }

                
                HStack {
                    // 사용자가 답을 입력하는 텍스트 필드
                    // (foregroundColor는 글자를 입력했을 때 나타남)
                    TextField("예림이 그패 봐봐-", text: $userAnswer)
                        .background(Color(red: 158 / 255, green: 17 / 255, blue: 2 / 255))
                        .cornerRadius(5.0)

                    // 사용자 값과 정답을 비교
                    // if문을 통해 인덱스 값 변경
                    Button("사쿠라여?") {
                        if (Int(userAnswer) ?? 0 < randomNum) {
                            index = 0
                        } else if (Int(userAnswer) ?? 0 > randomNum) {
                            index = 1                            
                        } else {
                            index = 2
                        }
                    }
                    .padding()
                    .foregroundColor(.white)
                    // 구조체로 설정을 완성한 후 대입
                    .buttonStyle(GradientButtonStyle())                    
                }
                .frame(width: 350, height: 100)
                .padding((EdgeInsets(top: 0, leading: 0, bottom: 40, trailing: 0)))
                
                // 인덱스 넘버에 따른 이미지 표시
                switch index{
                case 0:
                    Image("upImg")
                        .resizable()
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                        .frame(width: 300, height: 170)
                case 1:
                    Image("downImg")
                        .resizable()
                        .frame(width: 300, height: 150)
                        .clipShape(RoundedRectangle(cornerRadius: 10))

                case 2:
                    Image("goImg")
                        .resizable()
                        .frame(width: 300, height: 150)
                        .clipShape(RoundedRectangle(cornerRadius: 10))

                default:
                    Image("realTeam04")
                        .resizable()
                        .frame(width: 325, height: 200)
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                }
            }
            .padding()            
        }
    }
}


// 구조체로 설정한 버튼 스타일
struct GradientButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(Color.white)
            .padding()
            .background(LinearGradient(gradient: Gradient(colors: [Color.red, Color.orange]), startPoint: .leading, endPoint: .trailing))
            .cornerRadius(15.0)
    }
}

 

 

 

 

 

 


 

 

 

 

 

 

◤ 🎨 디-자인 스쿨 ep.3 : Typography◥

Typography

시각디자인 1학년 1학기 과정..? 아주 기초적이고 간단한 것을 알려줄 것이다.

중요하다잇.

 

 

Typography

  • Typo → 그리스어 typos → impression
  • graphy → 그리스어 graphis → writing
글쓰기에 인상을 주는 기술 글쓰기에 인상을 준다.

전통적인 의미는 ‘활판 인쇄술’이다. 디자이너들 사이에서는 글자 다루는 법이라고 인식한다.

 

 

Attribute of Type

아래와 같은 문장이 있다고 하자.

Valuable experience of learning Swift
  • Baseline
    • 기준선
    • 밑줄
  • X-height
    • Baseline과 소문자x까지 윗줄까지의 높이
  • Ascender
    • X-height 위로 올라간 부분
  • Descender
    • Baseline 아래로 내려간 부분
  • font size는 Ascender와 Descender 사이의 길이가 된다.

 

 

Typeface

느낌과 인상이 비슷한 글자들의 모임

주로 글꼴, 글자체, 서체 등으로 불린다.

 

 

Two Style of Typeface

삐침의 유무

  • Sans Serif : 세리프 없다
  • Serif : 세리프 있다

 

What is “Serif”

고대 로마시대에서는 법조문같은 것을 돌에다 새겼는데, 글의 끝 마감을 하기가 쉽지 않았다. 그래서 끌로 끝을 탁~ 치면 세리프가 생긴다. 이곳에서 유래했다는 말이 있다.

 

 

Weight

글자의 두께. 글자의 무게이다!

이것보다 다양할 수는 이는데, 요게 기본이다.

roman(일반체)이 기본이다.

weight는 글의 ‘인상’이다. 앱이 가볍고 날렵한 인상을 주려고 하는데, bold로 글자들을 칠갑해놓았다? 그럼 좀 날렵한 인상을 주기 힘들죠오. 진지한 인상을 주려면 또 어울릴거고. 그런 ‘인상’을 준다.

 

 

Size

글씨가 크면 소리지르는 느낌이고, 작을수록 디테일해 보인다. 디자이너들은 글씨를 작게 쓰려고 한다. 디테일해보이고 싶어서!

 

 

Italic / Oblique

둘 다 기울임의 차이가 있다.

  • Itatlic
    • 이탈리아 캘리그라피에서 옴
    • 기울어진 글꼴 자체를 만든 것이다.
    • 원본 글씨에서 기울이면 꼬랑지가 생긴다.
  • oblique
    • 가만히 있는 글을 옆으로 기울인 것

컴퓨터에서는 강제로 기울일 수 있는데 (수학적으로 계산하니까) 그러면 깨지는게 있다. 그러니까 디자이너가 oblique를 만들어 놓은 곳이만 기울이다.

엄밀히 따지면 한글에는 ltalic은 없고 사체만 있다.

 

 

Monospace

단일 공간

위의 글자는 글자 공간이 다 다른데, 아래쪽은 모두 동일하다. IDE, 프로그래밍용 언어는 monospace를 쓰는게 국룰이다.

왜? 인덴테이션할 때 얼마나 들여썼는지 모르기 때문이다. 그래서 monospace 글꼴을 선택하면 ‘아! 요거는 코드구나’ 알 수 있다.

 

 

Condensed

말그대로 압축되었다는 뜻.

요것도 디자이너가 글씨가 압축되었을 때 모양을 잘 만들어준 것이기 때문에 안정적이다. 억지로 바꿀 수 있는데 고것은 그냥.. 엄… 그냥 커피다.

 

 

 

 

 

Typeface vs. Font

둘은 다른거다. 잘 알아보자!

 

What is Font

납활자 시기에는 한 typeface의 활자 묶음을 의미했다.

디지털 시대에는 한 typeface가 담겨 있는 파일을 뜻한다. 엄밀히 말하면 font는 file이다. 글씨체가 아니다. file로 묶여야 font이다.

더보기

Font 깨진다?

 

폰트 파일에 오류가 있어요. 근데 보통 font 깨진다는 표현은 파일 오류가 아니라 글자체가 잘 안보인다는 뜻이니까 엄밀히 말하면 다르긴하다~ 근데 그냥 쓰자~~

 

  •  Typeface
    • 타입 생김새, 느낌, 인상
    • 서체, 글씨라고 말한다.

 

  • Font
    • 이렇게 파일로 묶여야 font이다.

 

 

 

Family

컴퓨터로 Bold를 주는건 컴퓨터로 계산해주는거다. 디자이너들은 보통 이런 거 안쓰고 만들어져있는 bold체를 쓴다. 이렇게 제공해주면, 제공해주는 것을 쓰자.

이렇게 작은 것 하나하나를 신경쓰지 않으면 뭔가 이빨빠진 디자인이 된다.

 

 

 

Basic Principles

신기한게 디자인이 심리학의 범주에 들어간다. 모두를 만족시키는 디자인은 없다.

 

Goal of Studying Typography

가독성

과거에는 글이 모두가 아는 게 아니였다. 지식인의 것이었다.

현재는 인쇄술의 발달로 글을 읽을 수 있는 모두에게 지식이 전파될 수 있다. 그래서 현재 타이포그래피의 목표는 ‘텍스트 가독형의 향상’이다.

 

 

Readbility vs. legibility

가독성 vs. 이독성
  • 텍스트를 읽고 이해하기 쉬운 정도
  • 개별 글자를 판독하기 좋은 정도

 

Kerning

글자 사이, 자간

글자 높이의 1/5을 떼어서 준다. 덩어리가 잘 안보인다. 읽을 수는 있는데, 가독성이 좀 떨어진다.

요즘에는 글꼴이 다 잘 나와서 글자 사이 간격이 잘 되어 있는데, 옛날에 나온 글꼴은 좀 넓어서 내가 따로 지정해주어야 한다.

좁히면 밀도있어 보인다.

 

 

Leading

글줄 사이, 행간

납 활자

예전에는 저 납 덩어리를 중간에 꼈다. 저때는 납판을 넣어서 자간을 썻다. 그래서 ‘래딩’이라고 읽기도 한다.

디지털에 한정된 이야기

 

 

Line Length

글줄 길이

30~50글자 사이면 적절하더라

 

 

Purpose

  • 헤드라인용
  • 본문용

 

Spacing

간격
  • 글자 사이 < 글줄 사이 < 문단단위
  • 본문 < 중제목 < 대제목
  • 라이센스무료 폰트라고 해서 저작권이 내것이라는 것이 아니다.
  • 원칙적으로는 제작자에게 이메일을 보내서 확ㅇ니해야 한다.
  • 폰트는 라이센스를 잘 봐야 한다.

 

 

◣ 🎨 ep.3 END ◢

 

 

 

 

 

 

 

와아안~

 

 

  Comments,     Trackbacks