[SwiftUI] Drawing Paths and Shapes

์›๋ฌธ: ํŠœํ† ๋ฆฌ์–ผ ํŽ˜์ด์ง€

Drawing Paths and Shapes

combining path์™€ shapes๋ฅผ ๊ฐ€์ง€๊ณ  ๋งŒ๋“ค์–ด๋ณด๋Š” badge. ๊ทผ๋ฐ ๋ณดํ†ต ์•„์ด์ฝ˜์„โ€ฆ ๋””์ž์ด๋„ˆ๋ถ„๊ป˜ ๋ฐ›์•„์„œ ์“ฐ์ง€ ์•Š๋‚˜์š”โ€ฆ? ์•„๋‹Œ๊ฐ€

Create Drawing Data for a Badge View

์šฐ์„ ์€ ์œก๊ฐํ˜•์˜ ๋ฐฐ์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. ํŠœํ† ๋ฆฌ์–ผ ํŽ˜์ด์ง€์— ๋‚˜์˜จ ์ด๋ฏธ์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • HexagonParameters.swift ์ƒ์„ฑ (Swift file)
    • ์œก๊ฐํ˜• ๋ชจ์–‘์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” structure ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด HexagonParameters.swift ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.
  • HexagonParameters ๊ตฌ์กฐ์ฒด ๋‚ด๋ถ€์— ์œก๊ฐํ˜• badge ๋ชจ์–‘์„ ์œ„ํ•ด ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
struct HexagonParameters {
    struct Segment {
        let line: CGPoint
        let curve: CGPoint
        let control: CGPoint
    }

    static let adjustment: CGFloat = 0.085

    static let segments = [
        Segment(
            line:    CGPoint(x: 0.60, y: 0.05),
            curve:   CGPoint(x: 0.40, y: 0.05),
            control: CGPoint(x: 0.50, y: 0.00)
        ),
        Segment(
            line:    CGPoint(x: 0.05, y: 0.20 + adjustment),
            curve:   CGPoint(x: 0.00, y: 0.30 + adjustment),
            control: CGPoint(x: 0.00, y: 0.25 + adjustment)
        ),
        Segment(
            line:    CGPoint(x: 0.00, y: 0.70 - adjustment),
            curve:   CGPoint(x: 0.05, y: 0.80 - adjustment),
            control: CGPoint(x: 0.00, y: 0.75 - adjustment)
        ),
        Segment(
            line:    CGPoint(x: 0.40, y: 0.95),
            curve:   CGPoint(x: 0.60, y: 0.95),
            control: CGPoint(x: 0.50, y: 1.00)
        ),
        Segment(
            line:    CGPoint(x: 0.95, y: 0.80 - adjustment),
            curve:   CGPoint(x: 1.00, y: 0.70 - adjustment),
            control: CGPoint(x: 1.00, y: 0.75 - adjustment)
        ),
        Segment(
            line:    CGPoint(x: 1.00, y: 0.30 + adjustment),
            curve:   CGPoint(x: 0.95, y: 0.20 + adjustment),
            control: CGPoint(x: 1.00, y: 0.25 + adjustment)
        )
    ]
}

CGPoint๋Š” Foundation์— ํฌํ•จ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— CoreGraphics๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

Draw the Badge Background

SwiftUI์˜ graphics API๋ฅผ ์‚ฌ์šฉํ•ด custom badge ๋ชจ์–‘์„ ๊ทธ๋ ค๋ณธ๋‹ค.

  • BadgeBackground.swift ์ƒ์„ฑ (SwiftUI View)
  • body์—์„œ haxagonParameters์˜ Path ๊ฐ’์„ ์ถ”๋ ฅโ€ฆ. ํ•˜์ง€๋งŒ ์ดํ•ดํ•  ์ˆ˜ ์—†์—ˆ๋‹คโ€ฆ
struct BadgeBackground: View {
    var body: some View {
        GeometryReader { geometry in
            Path { path in
                var width: CGFloat = min(geometry.size.width, geometry.size.height)
                let height = width
                let xScale: CGFloat = 0.832
                let xOffset = (width * (1.0 - xScale)) / 2.0
                width *= xScale
                path.move(
                    to: CGPoint(
                        x: width * 0.95 + xOffset,
                        y: height * (0.20 + HexagonParameters.adjustment)
                    )
                )
                
                HexagonParameters.segments.forEach { segment in
                    path.addLine(
                        to: CGPoint(
                            x: width * segment.line.x + xOffset,
                            y: height * segment.line.y
                        )
                    )
                    
                    path.addQuadCurve(
                        to: CGPoint(
                            x: width * segment.curve.x + xOffset,
                            y: height * segment.curve.y
                        ),
                        control: CGPoint(
                            x: width * segment.control.x + xOffset,
                            y: height * segment.control.y
                        )
                    )
                }
            }
            .fill(.linearGradient(
                Gradient(colors: [Self.gradientStart, Self.gradientEnd]),
                startPoint: UnitPoint(x: 0.5, y: 0),
                endPoint: UnitPoint(x: 0.5, y: 0.6)
            ))
        }
        .aspectRatio(1, contentMode: .fit)
    }
    static let gradientStart = Color(red: 239.0 / 255, green: 120.0 / 255, blue: 221.0 / 255)
    static let gradientEnd = Color(red: 239.0 / 255, green: 172.0 / 255, blue: 120.0 / 255)
}

Draw the Badge Symbol

image ํŠœํ† ๋ฆฌ์–ผ ํŽ˜์ด์ง€์˜ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์—์„œ AppIcon์„ ๊ฐ€์ ธ์™”๋‹ค. ์ด์ œ ์ด๊ฑธ๋กœ badge symbol์„ ๋งŒ๋“ ๋‹ค.

  • BadgeSymbol ํŒŒ์ผ ์ƒ์„ฑ (SwiftUI View) image

  • RotatedBadgeSymbol ํŒŒ์ผ ์ƒ์„ฑ (SwiftUI View) image

Combine the Badge Foreground and Background

  • Badge ํŒŒ์ผ ์ƒ์„ฑ (SwiftUI View) image

RotatedSymbol์„ 8๊ฐœ ๋Œ๋ ค์„œ ๋งˆํฌ๋ฅผ ๋งŒ๋“ค๊ณ , badgeBackground ์œ„์— ์–น์„ ์ˆ˜ ์žˆ๋„๋ก ZStack์œผ๋กœ ๊ฒน์น˜๊ธฐ

๋งˆ๋ฌด๋ฆฌ

์‚ฌ์‹ค ์ด ์ฑ•ํ„ฐ๋Š” ๋‹ค์Œ ์žฅ์„ ์œ„ํ•ด ๋Œ€์ถฉ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒโ€ฆ ํ•˜์ง€๋งŒ ์ดํ•ด๋Š” ํ•˜๊ณ  ์‹ถ์€๋ฐ ์–ธ์ œ์ฏค ๋ ๊นŒ..? ์ˆซ์ž๋งŒ ๋‚˜์˜ค๋ฉด ๋จธ๋ฆฌ์— ์ฅ๊ฐ€ ๋‚œ๋‹ค.. ๐Ÿ˜ญ

Leave a comment