Revert jerky zoom fix; cap strong zoom level instead
Dividing the centering shift by top_scale (previous commit) avoided the strong-zoom black border, but made the shift a nonlinear function of the scale value being interpolated -- mid-animation, the pan no longer tracked the zoom at a constant rate, which read as jerky/skippy motion. Reverted shift to the original linear formula, (1-s)*(ART_SIZE/2), which moves smoothly in lockstep with Scale's own eased interpolation. Instead, capped ZOOM_LEVELS["strong"] at 1.45 (down from 1.7) -- the highest value where this plain linear formula stays safely inside the art's bounds, verified with the calibration tool (no black border across the full animation cycle, at both 1.45x and against a live station).
This commit is contained in:
1 parent
9f2216c692
commit
5f42319e26
2 files changed
+19
-17
No files matched your search
+18
-16
@@ -91,12 +91,16 @@ COLOR_SCHEMES = {
|
||||
DEFAULT_COLOR_SCHEME = "cyberpunk" # matches the station's own site theme
|
||||
|
||||
# How far in the album art zoom goes, relative to its fully-zoomed-out rest
|
||||
# state (see _art_widget below for why scale never goes below 1.0).
|
||||
# state (see _art_widget below for why scale never goes below 1.0). "strong"
|
||||
# is capped at 1.45, not pushed further: with the centering Translate in
|
||||
# _art_widget, empirically anything above ~1.46 starts revealing a real
|
||||
# black border in the bottom-right corner (verified with the calibration
|
||||
# tool) -- this is the safe ceiling, not an arbitrary choice.
|
||||
ZOOM_LEVELS = {
|
||||
"off": 1.0,
|
||||
"subtle": 1.15,
|
||||
"moderate": 1.4,
|
||||
"strong": 1.7,
|
||||
"strong": 1.45,
|
||||
}
|
||||
DEFAULT_ZOOM_LEVEL = "moderate"
|
||||
|
||||
@@ -233,21 +237,19 @@ def _art_widget(art_bytes, zoom_scale):
|
||||
# Scale with a Translate re-centers the zoom so it crops evenly from
|
||||
# all sides instead -- verified against a calibration grid image.
|
||||
#
|
||||
# The naive "final pixel shift" formula, (1-s)*(ART_SIZE/2), looked
|
||||
# right at a moderate zoom (1.4x) but pushed past the image's actual
|
||||
# edge at a strong one (1.7x) -- a real, on-device black border in the
|
||||
# bottom-right corner. That means Translate isn't applied in final
|
||||
# output pixels here; empirically, dividing by `top_scale` keeps the
|
||||
# crop inside the image's bounds at every zoom level this app offers
|
||||
# (verified via the calibration tool at both 1.4x and 1.7x), at the
|
||||
# cost of the *most* extreme (1.7x) zoom being very slightly
|
||||
# off-center rather than perfectly centered -- a trade worth making
|
||||
# since going outside the art's bounds is worse than a slight
|
||||
# asymmetry. This is safe because scale never drops below 1.0 here:
|
||||
# the black-border bug from an earlier version came from combining
|
||||
# Translate with scale *below* 1.0, not from Translate itself.
|
||||
# shift = (1-s)*(ART_SIZE/2) is linear in the scale value, which keeps
|
||||
# it moving smoothly in lockstep with Scale's own eased interpolation
|
||||
# throughout the animation. A tempting "fix" for a black-border bug at
|
||||
# strong zoom was dividing this by `top_scale` to pull the shift in at
|
||||
# high scale values -- that avoided the border, but made the shift a
|
||||
# *nonlinear* function of the scale being interpolated, so partway
|
||||
# through the animation the pan no longer tracked the zoom at a
|
||||
# constant rate -- visibly jerky. Reverted: instead, ZOOM_LEVELS caps
|
||||
# "strong" at a value where this plain linear formula is already safe
|
||||
# (verified via the calibration tool), rather than changing the
|
||||
# formula's shape.
|
||||
top_scale = max(zoom_scale, 1.0)
|
||||
shift = (1.0 - top_scale) * (ART_SIZE / 2.0) / top_scale
|
||||
shift = (1.0 - top_scale) * (ART_SIZE / 2.0)
|
||||
zoom = animation.Transformation(
|
||||
child = art,
|
||||
duration = ART_ZOOM_DURATION,
|
||||
|
||||