-
-
Save prachigauriar/c508799bad359c3aa271ccc0865de231 to your computer and use it in GitHub Desktop.
extension Binding where Value == Double { | |
/// Returns a new version of the binding that scales the value logarithmically using the specified base. That is, | |
/// when getting the value, `log_b(value)` is returned; when setting it, the new value is `pow(base, newValue)`. | |
/// | |
/// - Parameter base: The base to use. | |
func logarithmic(base: Double = 10) -> Binding<Double> { | |
Binding( | |
get: { | |
log10(self.wrappedValue) / log10(base) | |
}, | |
set: { (newValue) in | |
self.wrappedValue = pow(base, newValue) | |
} | |
) | |
} | |
} | |
extension Slider where Label == EmptyView, ValueLabel == EmptyView { | |
/// Creates a new `Slider` with a base-10 logarithmic scale. | |
/// | |
/// ## Example | |
/// | |
/// @State private var frequency = 1.0 | |
/// | |
/// var body: some View { | |
/// Slider.withLog10Scale(value: $frequency, in: 1 ... 100) | |
/// } | |
/// | |
/// - Parameters: | |
/// - value: A binding to the unscaled value. | |
/// - range: The unscaled range of values. | |
/// - onEditingChanged: Documentation forthcoming. | |
static func withLog10Scale( | |
value: Binding<Double>, | |
in range: ClosedRange<Double>, | |
onEditingChanged: @escaping (Bool) -> Void = { _ in } | |
) -> Slider { | |
return self.init( | |
value: value.logarithmic(), | |
in: log10(range.lowerBound) ... log10(range.upperBound), | |
onEditingChanged: onEditingChanged | |
) | |
} | |
} |
2021 Apri update
…
Thank you! I’ve updated the gist to incorporate these changes. Glad it was of use to you!
When I tried using this on macOS, I encountered some glitches with the Slider. As far as I can tell, the issue is because certain values along the slider don't map back to the same floating-point value when run through log
and pow()
.
Visually, the slider hitches back to a previous value and makes the slider no longer smooth. I tried to round the value before passing it to the slider, but that also causes issues with a mismatch between the two "sources of truth."
Best idea I could think of is making the log() representation the source of truth, as the zoomable scroll view can be more forgiving.
When I tried using this on macOS, I encountered some glitches with the Slider. As far as I can tell, the issue is because certain values along the slider don't map back to the same floating-point value when run through
log
andpow()
.Visually, the slider hitches back to a previous value and makes the slider no longer smooth. I tried to round the value before passing it to the slider, but that also causes issues with a mismatch between the two "sources of truth."
Best idea I could think of is making the log() representation the source of truth, as the zoomable scroll view can be more forgiving.
@darknoon Can you post some sample code? I don’t see the glitches you’re describing. What range are you using?
Thanks for this, btw. I'm working on one I can use for different kinds of mappings and this got me started. It's still in progress.
https://gist.github.com/carlynorama/ad0a7449367b9a08e8c8525d5dcc2f8a
2021 Apri update