🌅Outlined
可以幫一個 Shape 填色 (fill) 又描邊 (stroke)。
Last updated
可以幫一個 Shape 填色 (fill) 又描邊 (stroke)。
Last updated
import SwiftUI
// 🌅 Outlined
// - Outlined(shape)
// - Outlined(shape, stroke: stroke)
public struct Outlined<S: Shape, FillContent: ShapeStyle, StrokeContent: ShapeStyle>: View {
// vars
let shape : S
let fillContent : FillContent
let fillStyle : FillStyle
let strokeContent: StrokeContent
let strokeStyle : StrokeStyle
// init
public init(
_ shape: S,
fill : FillContent,
fillStyle : FillStyle = .init(),
stroke : StrokeContent,
strokeStyle: StrokeStyle = .init(lineWidth: 1)
) {
self.shape = shape
self.fillContent = fill
self.fillStyle = fillStyle
self.strokeContent = stroke
self.strokeStyle = strokeStyle
}
// body
public var body: some View {
shape
.fill(fillContent, style: fillStyle)
.overlay(shape.stroke(strokeContent, style: strokeStyle))
}
}
// generic type with specialized init
// - Outlined(shape, fill: .pink, stroke: .purple)
extension Outlined where FillContent == Color, StrokeContent == Color {
public init(
_ shape: S,
fill : FillContent = Color.pink,
fillStyle : FillStyle = .init(),
stroke : StrokeContent = Color.black,
strokeStyle: StrokeStyle = .init(lineWidth: 1)
) {
self.shape = shape
self.fillContent = fill
self.fillStyle = fillStyle
self.strokeContent = stroke
self.strokeStyle = strokeStyle
}
}
import SwiftUI
import PlaygroundSupport
let w: CGFloat = 100
let h: CGFloat = 50
let dw = w/2
let dh = h/2
// 🌅 Outlined
let r1 = Outlined(Rectangle()).padding(1).frame(w, h) // 🌀view.frame(w, h)
let r2 = Outlined(Rectangle(), fill: .orange).padding(1).frame(h, w)
let r3 = Outlined(Rectangle(), fill: .green).padding(1).frame(w, h)
let r4 = Outlined(Rectangle(), fill: .blue).padding(1).frame(h, w)
// live view
struct ContentView: View {
// ⭐️ view state
@State private var change = false
// animation parameters
var d: CGFloat { change ? 100 : 0 }
// view body
var body: some View {
VStack(spacing: 20) {
ZStack { // ZS2
// ⭐️ 每個 view 的平移、旋轉等變換,都是相對於它的 direct parent view,
// 也就是每個 parent view 都會有屬於自己的座標系統。
ZStack { // ZS1
// ⭐️ 這些平移,都是相對於 ZS1 的座標系統。
r1.offset( dw, -dh).offset(x: d) // 🌀view.offset(x, y)
r3.offset(-dw, dh).offset(x: -d)
r2.offset( dh, dw).offset(y: d)
r4.offset(-dh, -dw).offset(y: -d)
Outlined(Circle(), fill: .purple)
.opacity(0.7)
.frame(100, 400)
.border(Color.black.opacity(0.5))
}// ZStack
.compositingGroup()
// ⭐️ rotatin effect
// ⭐️ 這個旋轉是整個 ZS1 的旋轉(相對於 ZS2),因此雖然內部的
// 長方形都只是在做平移,但配合外部整個 ZS1 在旋轉,會讓
// 這些長方形看起來是邊移動、邊旋轉。
.rotationEffect(.degrees(change ? 90 : 0))
Circle().stroke(Color.secondary, lineWidth: 4)
}// VStack
.padding()
.border(Color.black)
.animation(.easeInOut)
.onTapGesture { self.change.toggle() }
}// container: VStack
.shadow(radius: 8)
.padding()
.aspectRatio(1, contentMode: .fit)
.background(Color.gray)
.cornerRadius(10)
}
}
PlaygroundPage.current.setLiveView(ContentView())
🌀 view .offset(x, y)
🌀 view .frame(w, h)
How to draw filled and stroked shape? - StackOverflow