πŸ“± [SwiftUI] Shape: λ„ν˜• 닀루기

μ΄μ„œΒ·2023λ…„ 9μ›” 30일
0

πŸ“± SwiftUI νŠΈλž™

λͺ©λ‘ 보기
2/7

πŸŽοΈπŸ’¨Β μ‚‘μ‚‘ μ•ˆλ…•ν•˜μ„Έμš” μ΄μ„œμž…λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ…μ— λŒ€ν•΄μ„œλŠ” SwiftUIκ°€ μ œκ³΅ν•˜λŠ” λ„ν˜•μ— λŒ€ν•΄μ„œ ν¬μŠ€νŒ…ν•˜κ³ μž ν•΄μš”. πŸ“Β βΉοΈΒ πŸŸ¨

κ°œμš”

SwiftUIμ—μ„œ ShapeλŠ” λ‹€μ–‘ν•œ λ„ν˜•μ„ 그리고 λ””μžμΈν•˜λŠ” 데 μ‚¬μš©ν•΄μš”. Shape ν”„λ‘œν† μ½œ(protocol)은 UI λ””μžμΈμ— ν•„μš”ν•œ κΈ°λŠ₯을 μ œκ³΅ν•˜λ©°, λ‹€μ–‘ν•œ κΈ°λ³Έ λ„ν˜• 및 μ‚¬μš©μž 지정 λ„ν˜•μ„ 생성할 수 μžˆμ–΄μš”. κΈ°λ³Έ λ„ν˜•μ—λŠ” μ‚¬κ°ν˜•, 원, 타원, λ‘₯κ·Ό μ‚¬κ°ν˜•, λ‘₯κ·Ό μ–‘ 끝의 캑슐 등이 있으며, μ΄λŸ¬ν•œ λ„ν˜•μ€ 색상, μ„  μŠ€νƒ€μΌ, μ„  λ‘κ»˜ λ“± λ‹€μ–‘ν•œ μŠ€νƒ€μΌλ‘œ μŠ€νƒ€μΌλ§ν•  수 μžˆμ–΄μš”.

κΈ°λ³Έ λ„ν˜•

SwiftUIμ—μ„œ 기본적으둜 μ œκ³΅ν•΄μ£ΌλŠ” λ„ν˜•μ€ λ‹€μŒκ³Ό κ°™μ•„μš”. κΈ°λ³Έ λ„ν˜•μ„ 톡해 쉽고 λΉ λ₯΄κ²Œ λ„ν˜•μ„ λ§Œλ“€ 수 μžˆμ–΄μš”.

  1. Rectangle: μ‚¬κ°ν˜•
  2. Circle: 원
  3. Ellipse: 타원
  4. RoundedRectangle: λ‘₯κ·Ό μ‚¬κ°ν˜•
  5. Capsule: 캑슐

κΈ°λ³Έλ„ν˜•

import SwiftUI

struct ShapeBasic: View {
    var body: some View {
        VStack {
            Rectangle().frame(width: 50, height: 50)
            Circle().frame(width: 50, height: 50)
            Ellipse().frame(width: 50, height: 50)
            RoundedRectangle(cornerRadius:15).frame(width: 50, height: 50)
            Capsule().frame(width: 80, height: 50)
        }
    }
}

#Preview {
    ShapeBasic()
}

μ‚¬μš©μž μ •μ˜ λ„ν˜•

μ‚Όκ°ν˜•κ³Ό 같은 λ„ν˜•μ€ SwiftUIμ—μ„œ 기본적으둜 μ œκ³΅ν•˜μ§€ μ•Šμ•„μš”. ν•˜μ§€λ§Œ Path structλ₯Ό 톡해 μš°λ¦¬κ°€ μ›ν•˜λŠ” λ„ν˜•μ„ λ§Œλ“€ 수 μžˆμ–΄μš”.

Path { path in
    path.move(to: CGPoint(x: 200, y: 0)) // μ‹œμž‘μ 
    path.addLine(to: CGPoint(x: 50, y: 200))
    path.addLine(to: CGPoint(x: 350, y: 200))
}

μ‚¬μš©μž_μ •μ˜_λ„ν˜•

μŠ€νƒ€μΌλ§

SwiftUI의 ShapeλŠ” μŠ€νƒ€μΌμ„ 지정할 수 μžˆμ–΄μš” 😎. 예λ₯Ό λ“€λ©΄ λ„ν˜•μ˜ 색상, μ„  μŠ€νƒ€μΌ, μ„  λ‘κ»˜ 등을 μ„€μ •ν•˜μ—¬ μ›ν•˜λŠ” λ„ν˜•μ„ λ§Œλ“€ 수 μžˆμ–΄μš”. λ‹€μ–‘ν•œ μŠ€νƒ€μΌ 지정 방법에 λŒ€ν•΄μ„œ μ•Œμ•„λ³Όκ²Œμš”.

크기 μ„€μ •: .frame()

Rectangle()
	.frame(width: 100, height: 100)

Rectangle()
	.frame(minWidth: 200) // λ„ν˜•μ˜ μ΅œμ†Œ λ„ˆλΉ„λ₯Ό 200으둜 μ„€μ •ν–ˆμ–΄μš”.
	// λ‹€λ₯Έ 뷰에 μ˜ν•΄ λ°˜μ‘ν˜•μœΌλ‘œ 크기가 쀄어듀어도 200μ΄ν•˜λ‘œλŠ” 쀄지 μ•Šμ•„μš”.

Rectangle()
	.frame(minHeight: 200)

minWidth 와 minHeightλ§€κ°œλ³€μˆ˜λŠ” λ·°κ°€ μ΅œμ†Œν•œμ˜ λ„ˆλΉ„μ™€ 높이λ₯Ό κ°€μ Έμ•Όν•˜λŠ” κ²½μš°μ— μ‚¬μš©ν•΄μš”. μ΄λŸ¬ν•œ μ œμ•½μ„ 톡해 λ·°κ°€ μ΅œμ†Œ 크기λ₯Ό κ°–κ²Œ ν•˜κ±°λ‚˜ νŠΉμ • 크기 미만으둜 μΆ•μ†Œλ˜μ§€ μ•Šλ„λ‘ 방지할 수 μžˆμ–΄μš”.

배경색: .fill()

Rectangle()
	.fill(.blue)
	.frame(width: 100, height: 100) // *frame을 섀정해주지 μ•ŠμœΌλ©΄, λ„ν˜•μ΄ 보이지 μ•Šμ•„μš”!*

μ„  μŠ€νƒ€μΌ: .stroke()

μ„ μ˜ ꡡ기와 같은 μŠ€νƒ€μΌμ€ StrokeStyle structλ₯Ό 톡해 μŠ€νƒ€μΌλ§ν•  수 μžˆμ–΄μš”. μ•„λž˜λŠ” StrokeStyle을 μ΄ˆκΈ°ν™”ν•  λ•Œ μ‚¬μš©λ˜λŠ” μ˜΅μ…˜λ“€μ΄μ—μš”. λͺ¨λ“  μ˜΅μ…˜μ„ λ‹€ μ‚¬μš©ν•  ν•„μš”λŠ” μ—†μœΌλ©°, λ‚΄κ°€ μ›ν•˜λŠ” μ˜΅μ…˜λ§Œ μƒμ„±μž λ§€κ°œλ³€μˆ˜μ— λ„£μ–΄μ£Όλ©΄ λΌμš”.

/// μ„ μ˜ λ„ˆλΉ„.
/// The width of the stroked path.
public var lineWidth: CGFloat

/// μ„ μ˜ 끝점 μŠ€νƒ€μΌ.
/// The endpoint style of a line.
public var lineCap: CGLineCap

/// μ„ μ˜ κ²°ν•© μœ ν˜•.
/// The join type of a line.
public var lineJoin: CGLineJoin

/// κ²°ν•© λŒ€μ‹ μ— miterλ₯Ό μ‚¬μš©ν• μ§€ μ—¬λΆ€λ₯Ό κ²°μ •ν•˜λŠ” μž„κ³„κ°’.
/// A threshold used to determine whether to use a bevel instead of a miter at a join.
public var miterLimit: CGFloat

/// λŒ€μ‹œ(dash)된 선을 λ§Œλ“€ λ•Œ μ‚¬μš©λ˜λŠ” κ·Έλ¦Όκ³Ό λΉ„κ·Έλ¦Ό μ„Έκ·Έλ¨ΌνŠΈμ˜ 길이.
/// The lengths of painted and unpainted segments used to make a dashed line.
public var dash: [CGFloat]

/// λŒ€μ‹œ νŒ¨ν„΄μ—μ„œ 선이 μ‹œμž‘ν•˜λŠ” μœ„μΉ˜.
/// How far into the dash pattern the line starts.
public var dashPhase: CGFloat

πŸ’‘Β μ„Έκ·Έλ¨ΌνŠΈ(Segment): 주둜 μ„ , 경둜 λ˜λŠ” 곑선과 같은 κ·Έλž˜ν”½ μš”μ†Œμ—μ„œ νŠΉμ • 뢀뢄을 λ‚˜νƒ€λ‚΄λŠ” μš©μ–΄μ—μš”.

πŸ’‘Β κ·Έλ¦Ό(Painted) μ„Έκ·Έλ¨ΌνŠΈ: μ„ μ˜ μƒ‰μƒμœΌλ‘œ μ±„μ›Œμ§„ 뢀뢄을 λ‚˜νƒ€λ‚΄μš”. λ‹€μ‹œ 말해, μ„ μ˜ μ‹€μ œ 색상이 λ‚˜νƒ€λ‚˜λŠ” λΆ€λΆ„μ΄μ—μš”.

πŸ’‘Β λΉ„κ·Έλ¦Ό(Unpainted) μ„Έκ·Έλ¨ΌνŠΈ: 선이 λΉ„μ–΄μžˆκ±°λ‚˜ 색상이 μ±„μ›Œμ§€μ§€ μ•Šμ€ 뢀뢄을 λ‚˜νƒ€λ‚΄μš”.

StrokeStyle의 μƒμ„±μžλ₯Ό κ°€μ Έμ™€λ΄€μ–΄μš”. κΈ°λ³Έκ°’κ³Ό μ–΄λ–€ νƒ€μž…μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό λ°›κ³  μžˆλŠ” 지 ν™•μΈν•΄λ³΄μ„Έμš”.

// StrokeStyle
public init(
	lineWidth: CGFloat = 1, 
	lineCap: CGLineCap = .butt, 
	lineJoin: CGLineJoin = .miter, 
	miterLimit: CGFloat = 10, 
	dash: [CGFloat] = [CGFloat](), 
	dashPhase: CGFloat = 0
)

μ„ _μŠ€νƒ€μΌ

Rectangle()
	.stroke(style: .init(
	    lineWidth: 5
	))
	.frame(width: 200, height: 200)
	
Rectangle()
	.stroke(style: .init(
	    lineWidth: 5,
	    dash: [20, 5]
	))
	.frame(width: 200, height: 200)

투λͺ…도: .opacity()

Rectangle()
	.opacity(0.5)
	.frame(width: 200, height: 200)

그림자: .shadow()

그림자

Rectangle()
	.shadow(color: .gray, radius: 5, x: 10, y: 10)
	.frame(width: 200, height: 200)

color: 그림자의 색상을 μ„€μ •ν•©λ‹ˆλ‹€. 이 μ˜ˆμ œμ—μ„œλŠ” νšŒμƒ‰ (Color.gray)으둜 μ„€μ •ν–ˆμ–΄μš”.

radius: 그림자의 λΈ”λŸ¬(Blur) λ°˜κ²½μ„ μ„€μ •ν•΄μš” 값이 클수둝 κ·Έλ¦Όμžκ°€ λΈ”λŸ¬ μ²˜λ¦¬λΌμš”.

x와 y: 그림자의 x 와 y μ˜€ν”„μ…‹μ„ μ„€μ •ν•΄μš”. 그림자의 μœ„μΉ˜λ₯Ό μ‘°μ •ν•  수 μžˆμ–΄μš”. x 값이 μ–‘μˆ˜μΈ 경우 였λ₯Έμͺ½μœΌλ‘œ, 음수인 경우 μ™Όμͺ½μœΌλ‘œ μ΄λ™ν•˜κ³ , y 값이 μ–‘μˆ˜μΈ 경우 μ•„λž˜λ‘œ, 음수인 경우 μœ„λ‘œ μ΄λ™ν•΄μš”.

마무리

마무리

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” SwiftUIμ—μ„œ λ„ν˜•(Shape)을 λ‹€λ£¨λŠ” 방법과 μŠ€νƒ€μΌλ§ν•˜λŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜μ–΄μš”. λ„ν˜•μ€ iOS κ°œλ°œμ— 많이 μ‚¬μš©λ˜λ‹ˆ, 잘 μ΅ν˜€λ‘μ–΄ 창의적인 μ•± κ°œλ°œμ— ν™œμš©ν•˜μ…¨μœΌλ©΄ μ’‹κ² μ–΄μš” 😎!

profile
πŸŽοΈπŸ’¨ Beep Beep

0개의 λŒ“κΈ€