Fix the periodic zoom pop at its root: disable Translate's pixel rounding
Root-caused the "pop" from the Scale+Translate centered zoom (reverted a few commits back) to pixlet's own source: render/animation/translate.go rounds a Translate's x/y to the nearest whole pixel every frame by default (rounding = "round"), while animation/scale.go never rounds Scale. A continuously-interpolating Scale combined with a rounded Translate holds still for several frames, then jumps a whole pixel at once -- a real, confirmed pixlet behavior, not a flaw in this app's formula. Transformation accepts a `rounding` parameter; passing "none" disables the snapping. Confirmed via frame-by-frame pixel-delta analysis: the per-frame change is now even throughout the animation (consistently ~900 AE out of 1024 possible, every frame) instead of long near-zero stretches punctuated by sudden full-frame jumps. Re-enables the centered zoom (Scale + Translate) that was reverted for jerkiness, now smooth. ZOOM_LEVELS["strong"] stays capped at 1.45 -- that black-border ceiling is unrelated to rounding and still applies. Verified against the live station: no pop, no black border at any zoom level, payload ~370KB (up from ~220-320KB, since rounding="none" means WebP can dedupe fewer near-identical frames) but still well under the 460KB device limit.
This commit is contained in:
1 parent
9f63adbfbf
commit
4a2b3caac8
3 files changed
+73
-47
No files matched your search
@@ -46,20 +46,30 @@ app's config when adding it to a device.
|
||||
attempts produced a real, on-device black border; see the fuller
|
||||
history below.
|
||||
|
||||
`animation.Scale`'s pivot defaults to the top-left corner (confirmed
|
||||
empirically — an explicit `origin` parameter has no effect at all), so
|
||||
zooming in crops a bit more off the bottom/right than the top/left. A
|
||||
centered version (pairing Scale with a computed `animation.Translate`)
|
||||
was built and visually worked, but combining Scale with Translate turned
|
||||
out to make pixlet periodically re-rasterize the whole image with a
|
||||
visible "pop" every ~0.7-1s — confirmed with both WebP and GIF output,
|
||||
independent of zoom amplitude, so it's a property of pixlet's animation
|
||||
engine, not this app's math. Scale *alone* has none of that popping.
|
||||
Given the choice between a subtle, constant crop asymmetry and a
|
||||
periodic visible pop, this app accepts the asymmetry. (`dev/calibration_test.star`
|
||||
has a working centered version if anyone wants to revisit this trade-off.)
|
||||
Verified payload stays well under the 460KB device limit at every zoom
|
||||
level, measured against the live station.
|
||||
`animation.Scale`'s pivot defaults to the *center* of the widget per
|
||||
pixlet's own docs, so Scale alone is already close to centered — just
|
||||
slightly skewed toward the top-left as the zoom amount increases.
|
||||
Paired with a computed `animation.Translate` to cancel out that residual
|
||||
skew. Combining Scale with Translate at all was tried once before and
|
||||
reverted after it produced a periodic rendering "pop" roughly every
|
||||
0.7-1s — confirmed with both WebP and GIF output, independent of zoom
|
||||
amplitude. Root-caused to pixlet's own source
|
||||
(`render/animation/translate.go`): a Translate's x/y are rounded to the
|
||||
nearest whole pixel every frame by default, while Scale is never
|
||||
rounded, so a continuously-changing Scale combined with a rounded
|
||||
Translate holds still for several frames and then jumps a whole pixel
|
||||
at once. Passing `rounding = "none"` on the `Transformation` disables
|
||||
that snapping and fixes it — confirmed via frame-by-frame pixel-delta
|
||||
analysis (the amount of change is now even from frame to frame, instead
|
||||
of long still stretches punctuated by sudden jumps). "strong" is capped
|
||||
at 1.45 (not pushed further): above ~1.46 the centered crop 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. Verified payload stays well under the 460KB device limit at
|
||||
every zoom level, measured against the live station (though with
|
||||
`rounding = "none"`, WebP can no longer dedupe as many near-identical
|
||||
frames, so payloads run larger than the "pop" version did — ~370KB
|
||||
vs. ~220-320KB — still comfortably within budget).
|
||||
|
||||
**Why a loop, not a one-shot reveal, and why it's short:** a one-way
|
||||
version looked jumpy in practice — since the app re-renders on
|
||||
|
||||