Skip to content

[BUG] snapToCursor accumulates position drift on repeated drags with initial coordinates #3805

Description

@jaysin586

Description

We discovered this while testing React Motion parity in @humanspeak/svelte-motion. After noticing repeated snap-to-cursor drift in our Svelte implementation, we independently reproduced the same behavior using public React Motion APIs.

When an element has initial x/y coordinates, the first controlled drag snaps correctly. Subsequent starts progressively offset the element from the pointer.

Reproduction

StackBlitz reproduction

The example uses:

const controls = useDragControls();

<button
  onPointerDown={(event) =>
    controls.start(event, { snapToCursor: true })
  }
>
  Start Initial Drag
</button>

<motion.div
  drag
  dragControls={controls}
  dragListener={false}
  dragMomentum={false}
  initial={{ x: 100, y: 40 }}
/>

Steps to reproduce

  1. Press and hold Start Initial Drag.
  2. Move the pointer approximately 150 pixels right and 50 pixels down.
  3. Release.
  4. Repeat the same gesture from the button several times.

Expected behavior

Every pointerdown should center the element beneath the pointer, regardless of its previous position. Repeating the same gesture should produce the same final position.

Actual behavior

Subsequent starts accumulate an offset. The element drifts upward and away from the pointer instead of centering beneath it.

Versions

  • motion, framer-motion, motion-dom: 13.2.0
  • react, react-dom: 19.1.1
  • Reproduced in Chromium.

Investigation

The snap calculation appears to combine a stored projection layout measurement with the changing current motion value, causing the correction to accumulate across sessions.

This may be related to #3445, which addressed first-drag snapping with initial coordinates. We haven’t bisected the history to establish when the repeated-start behavior was introduced.

We have a failing real-browser regression test in our Svelte repository and would be happy to contribute a focused upstream fix with browser regression coverage.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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