ButtonUp, ButtonDown 📦
用來當作 Tab Bar Button 彈起與按下的兩個狀態,這兩個只是單純的 View 而已,還不能真的按。
Last updated
Was this helpful?
用來當作 Tab Bar Button 彈起與按下的兩個狀態,這兩個只是單純的 View 而已,還不能真的按。
Last updated
Was this helpful?
import SwiftUI
import ViewModifiers
public struct ButtonUp: View {
// button properties
let size: CGFloat // icon size
let icon: String // icon name (SF Symbol)
// public init
public init(icon: String, size: CGFloat = 32){
self.icon = icon
self.size = size
}
// button body
public var body: some View {
ZStack {
// 1. 用漸層為底紙,遮在圖示下面
Neu.buttonUpIconBackground
.frame(width: size, height: size) // 這個大小只夠遮住 icon
// 2. 再鋪上挖洞的方紙
Rectangle()
.foregroundColor(Neu.color.cardBackground) // 上色
.frame(width: size * 2, height: size * 2) // 方紙為圖示的兩倍大
.inverseMask(IconCard(icon, size: size)) // 以圖示挖洞
// shadow & highlight
.shadow(color: Neu.color.iconShadow, radius: 6, x: 6, y: 6)
.shadow(color: .white, radius: 3, x: -3, y: -3)
.cornerRadius(size * 0.5) // 剪圓角
} // container (ZStack)
// ⭐️ 合併所有圖層(為了幫整個 ZStack 製作陰影)
.compositingGroup()
// ⭐️ 讓打光與陰影都「收斂」一點(radius 大,x y 小)
.shadow(color: Color.white.opacity(0.9), radius: 4, x: -2, y: -2)
.shadow(color: Neu.color.iconShadow.opacity(0.9), radius: 4, x: 2, y: 2)
}
}
import SwiftUI
import ViewModifiers // for `.inverseMask`
import Workaround // for `SystemImage`
public struct ButtonDown: View {
// button properties
let size: CGFloat // icon size
let icon: String // icon name (SF Symbol)
// public init
public init(icon: String, size: CGFloat = 32){
self.icon = icon
self.size = size
}
// button body
public var body: some View {
// 0.5 - 0.125 = 0.375
let rimMask = Rectangle().cornerRadius(size * 0.375).padding(size * 0.125)
// ⭐️ container
return ZStack {
// 1. 鋪上放大一點的圓角方紙
Rectangle()
.foregroundColor(Neu.color.cardBackground) // 上色
.frame(width: size * 2.25, height: size * 2.25) // 方紙為圖示的 2.25 倍
.cornerRadius(size * 0.5) // 剪圓角
// 2. 設計「按下按鈕」的陰影效果
Rectangle()
// 2-1. 紙張上色、放大一點、剪圓角
.fill(Neu.buttonDownShadow) // 上色
.frame(width: size * 2.25, height: size * 2.25) // 方紙為圖示的 2.25 倍
.cornerRadius(size * 0.5) // 剪圓角
// 2-2. 剪下圓角邊緣 (padding = 0.125 * size)
.inverseMask(rimMask)
// 2-3. 打光、下陰影
.shadow(color: Neu.color.iconShadow, radius: 6, x: 6, y: 6)
.shadow(color: .white, radius: 6, x: -4, y: -4)
// 2-4. 剪掉外圍陰影
.cornerRadius(size * 0.5)
// 3. 圖示
Gradient.bottomRight(.black, .purple, .pink, .yellow) // 準備圖示顏色
.frame(width: size, height: size) // 限制圖示大小
.mask(SystemImage(icon)) // 剪下圖示的部分
.font(.system(size: 24, weight: .bold)) // 字體加粗
.offset(x: 2, y: 2) // ⭐️ 稍微往右下角移動,「按下的效果」更好
} // container (ZStack)
}
}