Skip to content

Add more complex transformations example#3124

Open
j-piasecki wants to merge 2 commits intomainfrom
@jpiasecki/complex-transformations
Open

Add more complex transformations example#3124
j-piasecki wants to merge 2 commits intomainfrom
@jpiasecki/complex-transformations

Conversation

@j-piasecki
Copy link
Copy Markdown
Member

Description

Extracted new transformations example from #2919, so that the entire thing isn't blocked by #2929

@j-piasecki j-piasecki mentioned this pull request Sep 25, 2024
m-bert added a commit that referenced this pull request Apr 10, 2026
## Description

Anchor and focal points were not converted to local view coordinates
before being sent. This PR fixes this problem.

Fixes #2929 

## Test plan

Tested on example from #3124
@j-piasecki j-piasecki force-pushed the @jpiasecki/complex-transformations branch from 8b20d90 to 7172bbf Compare April 14, 2026 10:27
Copilot AI review requested due to automatic review settings April 14, 2026 10:27
@j-piasecki
Copy link
Copy Markdown
Member Author

The V3 coordinates are wrong (at least on iOS). Changing render to

    <InterceptingGestureDetector>
      <VirtualGestureDetector gesture={gesture}>
        <Animated.View
          onLayout={({ nativeEvent }) => {
            setSize({
              width: nativeEvent.layout.width,
              height: nativeEvent.layout.height,
            });
          }}
          style={[styles.container, style]}>
          <Image source={SIGNET} style={styles.image} resizeMode="contain" />
        </Animated.View>
      </VirtualGestureDetector>
    </InterceptingGestureDetector>

fixes it so it seems like the wrong coordinate space is being used. This needs to be investigated.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new, more advanced “Transformations” example to the New API example set (extracted from #2919) and updates the legacy v2 transformations example to use the same matrix-based approach for pan/pinch/rotate composition.

Changes:

  • Register a new “Transformations” entry in the New API “Complicated” examples list.
  • Add a new New API transformations example that composes pan/pinch/rotation/double-tap using a 4×4 matrix accumulator.
  • Rework the legacy v2 transformations example to use the same matrix/origin approach (instead of simple translate/scale/rotate values).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
apps/common-app/src/new_api/index.tsx Adds the Transformations example to the New API list.
apps/common-app/src/new_api/complicated/transformations/index.tsx New complex matrix-based transformations example using hook gestures.
apps/common-app/src/legacy/v2_api/transformations/index.tsx Updates legacy example to match the complex matrix/origin approach and add layout sizing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +189 to +193
if (!isRotating.value && !isScaling.value) {
origin.value = {
x: -(e.anchorX - size.width / 2),
y: -(e.anchorY - size.height / 2),
};
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On web, anchorX/anchorY are not in the view’s local coordinate space (issue #2929), so computing origin from these values makes rotations behave incorrectly. Consider excluding this example on web or adding a web-specific conversion from window to local coordinates before using anchorX/anchorY.

Copilot uses AI. Check for mistakes.
Comment on lines +218 to +222
if (!isRotating.value && !isScaling.value) {
origin.value = {
x: -(e.focalX - size.width / 2),
y: -(e.focalY - size.height / 2),
};
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On web, focalX/focalY are not in the view’s local coordinate space (issue #2929), so this origin calculation will be incorrect and scaling will drift relative to the view. Consider excluding this example on web or adding a web-specific conversion from window to local coordinates before using focalX/focalY.

Copilot uses AI. Check for mistakes.
Comment on lines +182 to +186
if (!isRotating.value && !isScaling.value) {
origin.value = {
x: -(e.anchorX - size.width / 2),
y: -(e.anchorY - size.height / 2),
};
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On web, anchorX/anchorY are not in the view’s local coordinate space (issue #2929), so computing origin from these values makes rotations behave incorrectly. Consider excluding this example on web or adding a web-specific conversion from window to local coordinates before using anchorX/anchorY.

Copilot uses AI. Check for mistakes.
Comment on lines +212 to +216
if (!isRotating.value && !isScaling.value) {
origin.value = {
x: -(e.focalX - size.width / 2),
y: -(e.focalY - size.height / 2),
};
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On web, focalX/focalY are not in the view’s local coordinate space (issue #2929), so this origin calculation will be incorrect and scaling will drift relative to the view. Consider excluding this example on web or adding a web-specific conversion from window to local coordinates before using focalX/focalY.

Copilot uses AI. Check for mistakes.
Comment on lines +194 to +198
.onEnd(() => {
'worklet';
transform.value = applyTransformations(
translation.value,
scale.value,
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup/commit logic is attached to .onEnd, which won’t run for cancelled/failed gestures. That can leave isRotating/transient values stuck and the matrix uncommitted. Prefer .onFinalize (or handle success in .onEnd and also reset state in .onFinalize) so the reset/commit runs for END/CANCELLED/FAILED.

Copilot uses AI. Check for mistakes.
Comment on lines +224 to +228
.onEnd(() => {
'worklet';
transform.value = applyTransformations(
translation.value,
scale.value,
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup/commit logic is attached to .onEnd, which won’t run for cancelled/failed gestures. That can leave isScaling/transient values stuck and the matrix uncommitted. Prefer .onFinalize (or add a matching .onFinalize cleanup) so the reset/commit runs for END/CANCELLED/FAILED.

Copilot uses AI. Check for mistakes.
Comment on lines +248 to +252
.onEnd(() => {
'worklet';
transform.value = applyTransformations(
translation.value,
scale.value,
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup/commit logic is attached to .onEnd, which won’t run for cancelled/failed gestures. If the pan is interrupted (e.g., pointer count changes during a simultaneous gesture), translation/scale/rotation may not be reset and the matrix may not be committed. Prefer .onFinalize (or add a matching .onFinalize cleanup) so cleanup runs for END/CANCELLED/FAILED.

Copilot uses AI. Check for mistakes.
{ name: 'Velocity Test', component: VelocityExample },
{ name: 'Chat Heads', component: ChatHeadsExample },
{ name: 'Camera', component: CameraExample },
{ name: 'Transformations', component: TransformationsExample },
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example relies on rotation anchor / pinch focal coordinates being in the view’s coordinate space, which is currently not true on web (see issue #2929). As-is, the Transformations example will behave incorrectly on web; consider marking it as unsupportedPlatforms: new Set(['web']) (or applying a web-specific coordinate-space workaround) until the underlying web behavior is fixed.

Suggested change
{ name: 'Transformations', component: TransformationsExample },
{
name: 'Transformations',
component: TransformationsExample,
unsupportedPlatforms: new Set(['web']),
},

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants