fix(zoom): keep aspect ratio during the avatar zoom-in animation
The grow animation used independent scaleX/scaleY derived from the source rect (square avatar) and the image rect (often landscape), so at the start of the transition the full image was squashed into the avatar's square footprint before lerping back to its real proportions. Switches to a uniform scale based on max(src.width/img.width, src.height/img.height) and centers the image on the tapped rect. The image now keeps its aspect ratio throughout, covering the source rect in at least one dimension at progress=0 and growing uniformly to fullscreen. Also extends the entry guard to require non-zero source rect; without it a not-yet-measured thumbnail would yield startScale=0 and collapse the first frame to an invisible point before the animation expanded it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+14
-7
@@ -274,15 +274,22 @@ private fun DialogContent(
|
||||
.graphicsLayer {
|
||||
val src = sourceBounds
|
||||
val img = imageBounds
|
||||
if (src != null && img != null && img.width > 0f && img.height > 0f) {
|
||||
if (src != null && img != null &&
|
||||
src.width > 0f && src.height > 0f &&
|
||||
img.width > 0f && img.height > 0f
|
||||
) {
|
||||
transformOrigin = TransformOrigin(0f, 0f)
|
||||
val startScaleX = src.width / img.width
|
||||
val startScaleY = src.height / img.height
|
||||
// Uniform scale so non-square images keep their aspect ratio during
|
||||
// the grow animation. max() so the image covers the source rect in
|
||||
// at least one dimension; the other overflows centered on the tap.
|
||||
val startScale = maxOf(src.width / img.width, src.height / img.height)
|
||||
val srcCenter = src.center
|
||||
val imgCenter = img.center
|
||||
val p = progress()
|
||||
scaleX = lerp(startScaleX, 1f, p)
|
||||
scaleY = lerp(startScaleY, 1f, p)
|
||||
translationX = lerp(src.left - img.left * startScaleX, 0f, p)
|
||||
translationY = lerp(src.top - img.top * startScaleY, 0f, p)
|
||||
scaleX = lerp(startScale, 1f, p)
|
||||
scaleY = lerp(startScale, 1f, p)
|
||||
translationX = lerp(srcCenter.x - startScale * imgCenter.x, 0f, p)
|
||||
translationY = lerp(srcCenter.y - startScale * imgCenter.y, 0f, p)
|
||||
} else {
|
||||
// No source bounds: fall back to a plain fade.
|
||||
alpha = progress()
|
||||
|
||||
Reference in New Issue
Block a user