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
@@ -30,7 +30,7 @@ ART_ZOOM_DURATION = 200
|
|||||||
def _art_widget(art_bytes, zoom_scale):
|
def _art_widget(art_bytes, zoom_scale):
|
||||||
art = render.Image(src = art_bytes, width = ART_SIZE, height = ART_SIZE)
|
art = render.Image(src = art_bytes, width = ART_SIZE, height = ART_SIZE)
|
||||||
top_scale = max(zoom_scale, 1.0)
|
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(
|
zoom = animation.Transformation(
|
||||||
child = art,
|
child = art,
|
||||||
duration = ART_ZOOM_DURATION,
|
duration = ART_ZOOM_DURATION,
|
||||||
|
|||||||
+18
-16
@@ -91,12 +91,16 @@ COLOR_SCHEMES = {
|
|||||||
DEFAULT_COLOR_SCHEME = "cyberpunk" # matches the station's own site theme
|
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
|
# 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 = {
|
ZOOM_LEVELS = {
|
||||||
"off": 1.0,
|
"off": 1.0,
|
||||||
"subtle": 1.15,
|
"subtle": 1.15,
|
||||||
"moderate": 1.4,
|
"moderate": 1.4,
|
||||||
"strong": 1.7,
|
"strong": 1.45,
|
||||||
}
|
}
|
||||||
DEFAULT_ZOOM_LEVEL = "moderate"
|
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
|
# Scale with a Translate re-centers the zoom so it crops evenly from
|
||||||
# all sides instead -- verified against a calibration grid image.
|
# all sides instead -- verified against a calibration grid image.
|
||||||
#
|
#
|
||||||
# The naive "final pixel shift" formula, (1-s)*(ART_SIZE/2), looked
|
# shift = (1-s)*(ART_SIZE/2) is linear in the scale value, which keeps
|
||||||
# right at a moderate zoom (1.4x) but pushed past the image's actual
|
# it moving smoothly in lockstep with Scale's own eased interpolation
|
||||||
# edge at a strong one (1.7x) -- a real, on-device black border in the
|
# throughout the animation. A tempting "fix" for a black-border bug at
|
||||||
# bottom-right corner. That means Translate isn't applied in final
|
# strong zoom was dividing this by `top_scale` to pull the shift in at
|
||||||
# output pixels here; empirically, dividing by `top_scale` keeps the
|
# high scale values -- that avoided the border, but made the shift a
|
||||||
# crop inside the image's bounds at every zoom level this app offers
|
# *nonlinear* function of the scale being interpolated, so partway
|
||||||
# (verified via the calibration tool at both 1.4x and 1.7x), at the
|
# through the animation the pan no longer tracked the zoom at a
|
||||||
# cost of the *most* extreme (1.7x) zoom being very slightly
|
# constant rate -- visibly jerky. Reverted: instead, ZOOM_LEVELS caps
|
||||||
# off-center rather than perfectly centered -- a trade worth making
|
# "strong" at a value where this plain linear formula is already safe
|
||||||
# since going outside the art's bounds is worse than a slight
|
# (verified via the calibration tool), rather than changing the
|
||||||
# asymmetry. This is safe because scale never drops below 1.0 here:
|
# formula's shape.
|
||||||
# the black-border bug from an earlier version came from combining
|
|
||||||
# Translate with scale *below* 1.0, not from Translate itself.
|
|
||||||
top_scale = max(zoom_scale, 1.0)
|
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(
|
zoom = animation.Transformation(
|
||||||
child = art,
|
child = art,
|
||||||
duration = ART_ZOOM_DURATION,
|
duration = ART_ZOOM_DURATION,
|
||||||
|
|||||||