Skip to content

Image overlay: video does not scale during dismiss animation #165

@Kelbie

Description

@Kelbie

Problem

When the image overlay is dismissed (drag-to-dismiss or tap backdrop), the video content does not scale down with the animation. Only the frame/container (the view with rImageStyle) shrinks back to the feed thumbnail position and size; the video itself appears to stay at full expanded size and gets clipped, so it looks like the video "remains the same size and only the frame changes."

Images behave correctly: during dismiss they scale down in sync with the container because single-image content is wrapped in <Animated.View style={rPagerScaleStyle}>, which applies a transform (translate + scale) so the content fills the current container size (viewW/viewH from imageWidth/imageHeight). As those animate to the thumbnail, the image scales with them.

Desired behavior

On dismiss, the video should scale from expanded size down to the feed preview (thumbnail) size in sync with the position/size animation, the same way images do. The video content should visibly shrink as the overlay animates back to the thumbnail.

What we tried

  1. Same scale wrapper as images
    Wrapping single-video in <Animated.View style={rPagerScaleStyle}> around MemoizedMediaPagerPage.

    • Result: Caused Reanimated error and/or app lag: "Perhaps you are trying to pass an animated style to a non-animated component" — likely because the animated transform was applied in a way that affected expo-video’s VideoView, which may not be a Reanimated-aware component.
  2. Extra plain View between Animated.View and video
    Structure: Animated.View (rPagerScaleStyle)View (StyleSheet.absoluteFill)MemoizedMediaPagerPage (video).

    • Goal: Apply the transform only to the Animated.View so the transform is not directly on the video subtree and avoid the Reanimated/video issue.
    • Result: When releasing after drag-to-dismiss, during the shared-element animation back to the thumbnail, the video still did not scale correctly: "the video remains the same size and only the frame its within changes." So the scale transform either is not affecting the video content or VideoView does not respect the parent’s transform.
  3. Drive video size from container (no scale transform)

    • MediaPagerPage: Added optional containerWidthSv and containerHeightSv. When both are provided, the animated style uses them for the view’s width/height instead of expandedWidthSv/expandedHeightSv.
    • Overlay: For single video only, pass containerWidthSv={imageWidth} and containerHeightSv={imageHeight} so the video view’s layout size tracks the container.
    • Goal: The video view’s layout would shrink as imageWidth/imageHeight animate during dismiss, so the content would scale with the container without relying on a transform.
    • Result: Still could not get the video to scale correctly with the dismiss animation.

Relevant code

  • Overlay (single-media branch):
    components/blocks/nostr/image-overlay/AnimatedImageOverlay.tsx

    • Single image: wrapped in <Animated.View style={rPagerScaleStyle}>MemoizedMediaPagerPage (works).
    • Single video: MemoizedMediaPagerPage with containerWidthSv={imageWidth}, containerHeightSv={imageHeight} (no scale wrapper).
  • Scale style:
    rPagerScaleStyle in AnimatedImageOverlay.tsx: keeps content at expanded size (ew, eh) and applies translateX/Y and scale = max(viewW/ew, viewH/eh) so it fills the current container. As viewW/viewH (from imageWidth/imageHeight, with thumbnail clamp) animate, the scaled content should shrink.

  • Media page:
    components/blocks/nostr/image-overlay/MediaPagerPage.tsx

    • Optional containerWidthSv / containerHeightSv; when set, animated style uses them for width/height so the media view can track container size.
  • Video rendering:
    MediaPagerPage for video: Animated.View (animated style with size) → VideoView (expo-video) with StyleSheet.absoluteFill, contentFit="contain".

Environment

  • React Native + Expo.
  • react-native-reanimated, expo-video (VideoView).
  • Image overlay uses shared values for position/size (imageXCoord, imageYCoord, imageWidth, imageHeight) and animates them with withSpring on close.

Ask

We need a way to make the video content scale (or visually shrink) in sync with the dismiss animation, so it matches the behavior of images. If Reanimated’s transform cannot be applied in a way that affects VideoView, alternatives might include:

  • A different way to drive the video’s size or transform that works with expo-video.
  • Applying the scale only when isClosing for video to avoid interaction with normal playback.
  • Or another approach that keeps the shared-element dismiss feel without breaking video or causing Reanimated errors.

Any suggestions or prior art for "scaling video during a shared-element-style dismiss" in RN/Expo would be helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions