iOS: show stem level inside the fader track
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ae5eead73b
commit
567e557968
1 file changed
+13
-16
@@ -806,20 +806,10 @@ private struct StemFader: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
let color = Color(hex: Stems.color(name))
|
let color = Color(hex: Stems.color(name))
|
||||||
FaderRow(dot: setting.muted ? p.label3 : color, label: Stems.label(name), percent: Int(stemTaper(setting.level) * 100), dim: setting.muted, height: height, stacked: roomy) {
|
FaderRow(dot: setting.muted ? p.label3 : color, label: Stems.label(name), percent: Int(stemTaper(setting.level) * 100), dim: setting.muted, height: height, stacked: roomy) {
|
||||||
VStack(spacing: 0) {
|
// Live level, -48..0 dBFS, drawn as a light band inside the fader's fill.
|
||||||
FaderSlider(value: setting.level, fill: setting.muted ? p.label3 : color, detent: StemSetting.unity, enabled: enabled, thumb: roomy ? 26 : 24) {
|
|
||||||
pm.setStemLevel(name, $0)
|
|
||||||
}
|
|
||||||
// Live level under the fader, -48..0 dBFS.
|
|
||||||
GeometryReader { geo in
|
|
||||||
let f = CGFloat(min(1, max(0, (20 * log10(level + 1e-5) + 48) / 48)))
|
let f = CGFloat(min(1, max(0, (20 * log10(level + 1e-5) + 48) / 48)))
|
||||||
ZStack(alignment: .leading) {
|
FaderSlider(value: setting.level, fill: setting.muted ? p.label3 : color, detent: StemSetting.unity, enabled: enabled, thumb: roomy ? 26 : 24, meter: enabled && !setting.muted ? f : nil) {
|
||||||
Capsule().fill(p.fill)
|
pm.setStemLevel(name, $0)
|
||||||
Capsule().fill(color).frame(width: geo.size.width * f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(height: 3)
|
|
||||||
.padding(.horizontal, 12)
|
|
||||||
}
|
}
|
||||||
} trailing: {
|
} trailing: {
|
||||||
if enabled {
|
if enabled {
|
||||||
@@ -905,17 +895,19 @@ struct FaderSlider: View {
|
|||||||
var detent: Float?
|
var detent: Float?
|
||||||
var enabled = true
|
var enabled = true
|
||||||
var thumb: CGFloat = 24
|
var thumb: CGFloat = 24
|
||||||
|
/// 0...1 live level, shown as a lighter band over the filled part of the track.
|
||||||
|
var meter: CGFloat?
|
||||||
let onChange: (Float) -> Void
|
let onChange: (Float) -> Void
|
||||||
|
|
||||||
@Environment(\.palette) private var p
|
@Environment(\.palette) private var p
|
||||||
@State private var start: Float?
|
@State private var start: Float?
|
||||||
@State private var caught = false
|
@State private var caught = false
|
||||||
|
|
||||||
init(value: Float, fill: Color, detent: Float? = nil, enabled: Bool = true, thumb: CGFloat = 24, onChange: @escaping (Float) -> Void) {
|
init(value: Float, fill: Color, detent: Float? = nil, enabled: Bool = true, thumb: CGFloat = 24, meter: CGFloat? = nil, onChange: @escaping (Float) -> Void) {
|
||||||
self.value = value; self.fill = fill; self.detent = detent; self.enabled = enabled; self.thumb = thumb; self.onChange = onChange
|
self.value = value; self.fill = fill; self.detent = detent; self.enabled = enabled; self.thumb = thumb; self.meter = meter; self.onChange = onChange
|
||||||
}
|
}
|
||||||
|
|
||||||
private var bar: CGFloat { thumb >= 26 ? 5 : 4 }
|
private var bar: CGFloat { meter == nil ? (thumb >= 26 ? 5 : 4) : 6 }
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
@@ -924,6 +916,11 @@ struct FaderSlider: View {
|
|||||||
ZStack(alignment: .leading) {
|
ZStack(alignment: .leading) {
|
||||||
Capsule().fill(p.fillStrong).frame(height: bar).padding(.horizontal, thumb / 2)
|
Capsule().fill(p.fillStrong).frame(height: bar).padding(.horizontal, thumb / 2)
|
||||||
Capsule().fill(fill).frame(width: x + thumb / 2, height: bar).padding(.leading, thumb / 2 - 0.01)
|
Capsule().fill(fill).frame(width: x + thumb / 2, height: bar).padding(.leading, thumb / 2 - 0.01)
|
||||||
|
if let meter, meter > 0.01 {
|
||||||
|
Capsule().fill(.white.opacity(0.5)).frame(width: meter * (x + thumb / 2), height: bar)
|
||||||
|
.padding(.leading, thumb / 2 - 0.01)
|
||||||
|
.animation(.linear(duration: 1 / 30), value: meter)
|
||||||
|
}
|
||||||
if let detent {
|
if let detent {
|
||||||
p.label3.frame(width: 2, height: 10).offset(x: CGFloat(detent) * track + thumb / 2 - 1)
|
p.label3.frame(width: 2, height: 10).offset(x: CGFloat(detent) * track + thumb / 2 - 1)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user