# StrokeStyle

{% hint style="info" %}

* <mark style="color:red;">**cap**</mark> : 線頭的部分
* <mark style="color:red;">**join**</mark> : 線轉彎時的連接方式
* <mark style="color:red;">**dash**</mark> : 虛線樣式
* <mark style="color:orange;">**width**</mark> : 線寬
  {% endhint %}

{% tabs %}
{% tab title="🌀  StrokeStyle" %}
![](https://1830103165-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5-JmwCZMKh_d7RfBaN%2F-MIP66aJrNeoSaBWPmsj%2F-MIP6EEKOe_2gCV66FAO%2Fstroke%20style.png?alt=media\&token=84c9b3c9-f925-4f6d-8ac6-8875e019a8f3)

```swift
import SwiftUI

public extension StrokeStyle {
    
    /// # Line Cap
    /// 線頭的表現方式：
    /// - `.butt`：平頭。(⭐️ 預設值)
    /// - `.round`：圓頭。
    /// - `.square`：方頭。
    /// ## ⚠️ 注意：
    /// - 除了 `.butt` 之外，其他兩種都會突出線頭外‼️
    /// - Parameters:
    ///   - cap: 線頭的表現方式，有 `.butt`、`.round` 或 `.square` 三種。
    public func lineCap(_ cap: CGLineCap) -> StrokeStyle {
        var style = self
        style.lineCap = cap
        return style
    }
    
    /// # Line Join
    /// 線的銜接方式：
    /// - `.miter`：用「尖角」的方式銜接。(⭐️ 預設值)
    /// - `.bevel`：把尖角「削平」。
    /// - `.round`：用「圓角」的方式。
    /// - Parameters:
    ///   - join: 線的銜接方式，有 `.miter`、`.bevel`、`.round` 三種。
    public func lineJoin(_ join: CGLineJoin) -> StrokeStyle {
        var style = self
        style.lineJoin = join
        return style
    }
    
    /// # Line Width
    public func lineWidth(_ width: CGFloat) -> StrokeStyle {
        var style = self
        style.lineWidth = width
        return style
    }
    
    /// # Dash
    /// 虛線的樣式。例如：
    /// - `[10, 5]`：代表 `10 points` 畫線，`5 points` 空白。
    /// - `style.dash([10, 5])`
    public func dash(_ dash: [CGFloat]) -> StrokeStyle {
        var style = self
        style.dash = dash
        return style
    }
    
    /// Example: `style.dash(10, 5)`
    public func dash(_ dash: CGFloat...) -> StrokeStyle {
        self.dash(dash)
    }
    
}
```

{% endtab %}

{% tab title="💈 範例 " %}
⬆️ 需要： [vector2d](https://lochiwei.gitbook.io/ios/custom/package/geometrykit/vector2d "mention"), [watermark](https://lochiwei.gitbook.io/ios/custom/ext/view/watermark "mention")

```swift
import SwiftUI

// 設計圖尺寸
let s: CGFloat = 100          // 邊長
let w: CGFloat = 40           // 線寬
let d = s + w                 // 總寬度 = 邊長 + 線頭可能突出的部分

// 設計圖頂點
let p1 = CGPoint(w, w) * 0.5  // 起點    // ⭐️ required: 🅿️ Vector2D
let p2 = p1 + [s, 0]          // 轉折點
let p3 = p2 + [0, s]          // 終點

// 設計圖畫線樣式 (先設定寬度)
let style = StrokeStyle().lineWidth(w)

// 設計圖線條路線
let path = Path { p in
    p.move   (to: p1)
    p.addLine(to: p2)
    p.addLine(to: p3)
}

// 設計圖
struct LineStyle: View {
    
    // 可設定「線條樣式」
    let style: StrokeStyle
    // LineStyle(strokeStyle)
    init(_ s: StrokeStyle) { self.style = s }
    
    // 設計圖內容
    var body: some View {
        ZStack {
            
            // 1. 先將設計路線以「線條加寬樣式」加邊線，然後著色。
            path
                .strokedPath(style)        // ⭐️ still a `Path`
                .foregroundColor(.pink)
                .frame(width: d, height: d)
                
            // 2. 畫「設計圖路線」本身
            path
                .stroke()                  // ⭐️ a `Shape`
                .foregroundColor(.white)
                .frame(width: d, height: d)
                
            // 3. 描出「加寬的邊線」
            path
                .strokedPath(style)
                .stroke(lineWidth: 2)
                .foregroundColor(.black)
                .frame(width: d, height: d)
            
        } // container (ZStack)
            .background(Rectangle().opacity(0.6))
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            
            // Line Join
            Text("Line Join").fontWeight(.bold)
            HStack {
                LineStyle(style.lineJoin(.miter)) // ⭐️ default
                    .watermark("⭐️miter", .bottomLeading)
                LineStyle(style.lineJoin(.bevel))
                    .watermark("bevel", .bottomLeading)
                LineStyle(style.lineJoin(.round)) 
                    .watermark("round", .bottomLeading)
            }
                
            // Line Cap
            Text("Line Cap").fontWeight(.bold)
            HStack {
                LineStyle(style.lineCap(.butt))   // ⭐️ default
                    .watermark("⭐️butt", .bottomLeading)
                LineStyle(style.lineCap(.square))
                    .watermark("square", .bottomLeading)
                LineStyle(style.lineCap(.round))
                    .watermark("round", .bottomLeading)
            }
            
        } // container (VStack)
            .padding()
            .background(Color.gray)
            .shadow(color: Color.black.opacity(0.8), radius: 4, x: 4, y: 4)
    }
}
```

{% endtab %}

{% tab title="💈其他" %}

* [💈 MarchingAnts](https://lochiwei.gitbook.io/ios/swiftui/shapes/transform-shape/shape.stroke/marchingants)
  {% endtab %}

{% tab title="📘 手冊" %}

* SwiftUI  ⟩  [StrokeStyle](https://developer.apple.com/documentation/swiftui/strokestyle)
  {% endtab %}

{% tab title="📗 參考" %}

* [x] [How to create a marching ants border effect](https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-a-marching-ants-border-effect) - Hacking with Swift
* [ ] [SwiftUI basic Shape operations](https://sarunw.com/posts/swiftui-basic-shape-operations/) - Sarun

{% endtab %}

{% tab title="相依套件" %}

* [.watermark()](https://lochiwei.gitbook.io/ios/custom/ext/view/watermark)
* [🅿️ Vector2D](https://lochiwei.gitbook.io/ios/custom/package/geometrykit/vector2d)
  {% endtab %}
  {% endtabs %}
