SwiftUI 入門やるよ!チュートリアルしてみる!v4 線と図形 描画

SwiftUI
SwiftUI 入門やるよ!チュートリアルしてみる!v3 ユーザー入力操作
前回はこちらユーザー入力!Handling user inputsection 1 お気に入りにマークするModel/LandmarkにisFavoriteを追加LandmarkRowに...

線と図形描画 – Drawing paths and shapes

section 1 バッヂビューで描画データ生成 Create drawing data for a badge view

File > New > File Swift File作成 – HexagonParameters.swift.

六角形のstruct作成

segment 区分、部分? struct

import CoreGraphics

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)
        )
    ]
}

六角形の頂点データですが、とりあえずという感じですね^^;

section 2 バッヂの背景描画

SwiftUI View を作成 BadgeBackground.swift

import SwiftUI

struct BadgeBackground: View {
    var body: some View {
        Path {
            path in
            var width: CGFloat = 100.0
            let height = width
            path.move(to: CGPoint(
                x: width * 0.95,
                y: height * 0.20
            ))

            HexagonParameters.segments.forEach{
                segment in
                path.addLine(to: CGPoint(
                    x:width * segment.line.x,
                    y:height * segment.line.y
                ))
            }

        }
        .fill(.black)
    }
}

#Preview {
    BadgeBackground()
}

Pathって線っぽいイメージですが、道筋、軌道、「軌道」は線に方向があるイメージですね

100×100の中で、x, y,を順に頂点をつけて、七角形?が出来ているようです

addQuadCurve(to:control:) で Quadは四角形でしょうか?QuadCurve…
Appends a quadratic Bézier curve to the path. ベジェ曲線をパスに追加と
これだけだと右上が少しズレていて
最初の点に
y: height * (0.20 + HexagonParameters.adjustment)
とすると綺麗に揃いました…んーなかなか

イマイチピンときませんがとりあえず進めます^^

GeometryReader で geometry を使って 100指定していたサイズを画面の縦横の小さい方に設定されたようです

横幅を調整したようです

色グラデーションを付けたようです、中央へ

section 3 バッヂシンボル描画

サンプルプロジェクトファイルにある
Resources / landmark_app_icon_1024x1024.pngをAssets catalog の AppIconのところに入れる

SwiftUI View : BadgeSymbol.swift を生成
山の形を作るらしい

こちらはシンプルな描画なのでわかりやすいですね

struct BadgeSymbol: View {
    static let symbolColor = Color(red:79.0/255,green:79.0/255,blue:191.0/255)
    var body: some View {
        
        GeometryReader{
            geometry in
            Path { path in
                let width = min(geometry.size.width, geometry.size.height)
                let height = width * 0.75
                let spacing = width * 0.03
                let middle = width * 0.5
                let topWidth = width * 0.226
                let topHeight = height * 0.488
                
                path.addLines([
                    CGPoint(x:middle, y:spacing),
                    CGPoint(x:middle - topWidth, y:topHeight - spacing),
                    CGPoint(x:middle, y:topHeight/2 + spacing),
                    CGPoint(x:middle+topWidth, y: topHeight - spacing),
                    CGPoint(x: middle, y: spacing)
                ])
                
                path.move(to: CGPoint(x:middle, y: topHeight/2 + spacing))
                
                path.addLines([
                    CGPoint(x: middle - topWidth, y:topHeight + spacing),
                    CGPoint(x:spacing, y: height - spacing),
                    CGPoint(x:width - spacing, y: height - spacing),
                    CGPoint(x: middle + topWidth, y:topHeight + spacing),
                    CGPoint(x: middle, y: topHeight/2 + spacing*3)
                    
                ])
            }
            .fill(Self.symbolColor)
        }
    }
}

SwiftUI View : RotatedBadgeSymbol.swift を作成し、傾ける

struct RotatedBadgeSymbol: View {
    let angle: Angle
    var body: some View {
        BadgeSymbol()
            .padding(-60)
            .rotationEffect(angle, anchor:.bottom)
    }
}

#Preview {
    RotatedBadgeSymbol(angle: Angle(degrees:5))
}

section 4 バッジの前景と背景をあわせる

foregroundって前景だけどなんか前景って馴染みないですね

SwiftUI View : Badge.swiftを作成

単純に、zstack で BadgeBackgroundとBadgeSymbolを重ねるとこんな感じ

BadgeSymbolをいくつか変形

角度を変更して8つ並べる

こんな感じで出来ました。

難しくはないけど、これ作ろう!と思ってこの手順で進めるのは慣れないと

Check Your Understanding

英語難しい^^;

グラフなど描画するのに使う感じですかね?

お気軽にコメントください!

スパム対応のためコメント認証に数日かかることがありますが、お気軽にコメントいただけると嬉しいです^^

コメント

タイトルとURLをコピーしました