motion icon indicating copy to clipboard operation
motion copied to clipboard

[BUG] dragConstraints by ref doesn't consider changes after initial render

Open RealMeson opened this issue 3 years ago • 9 comments

1. Read the FAQs 👇

2. Describe the bug

If dragConstraints are set by giving a ref of an element, then the size of the draggable element is based off the initial render and not the current size.

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/s/framer-motion-drag-constraints-with-changing-size-7ixkj0?file=/src/Example.tsx

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Go to Sandbox.
  2. Click on button in top left corner.
  3. Draggable area for box is the same.

5. Expected behavior

The draggable area should change to accomodate the change in size.

RealMeson avatar Dec 13 '22 15:12 RealMeson

I have just encountered exactly the same issue. I need to scale draggable element and dragConstraints don't reflect that. Is there any workaround in the mean time?

EDIT: For those looking for workaround like me, you can pass number as a key to the draggable component and increase it on draggable component scale. It causes recalculation and constraints work as intended.

vavra7 avatar Feb 25 '23 20:02 vavra7

Ok since my previous workaround is not so good as I thought and this issue quite troubles me I decided to put my hands on the code a bit.

Version: 10.0.1

Description: When scale is passed in draggable element the constraints behave correctly on initial render but on every consequential rendering the constraints are broken.

Investigation: resolveRefConstraints method resolves constraints incorrectly https://github.com/framer/motion/blob/f06854066a1de33561578ce2c4fd785e78fdf3be/packages/framer-motion/src/gestures/drag/VisualElementDragControls.ts#L311 the reason is that projection.layout.layoutBox contains incorrect measurement https://github.com/framer/motion/blob/f06854066a1de33561578ce2c4fd785e78fdf3be/packages/framer-motion/src/gestures/drag/VisualElementDragControls.ts#L335 it has incorrect measurement because getBoundingClientRect on our draggable instance returns different values than we are expecting https://github.com/framer/motion/blob/f06854066a1de33561578ce2c4fd785e78fdf3be/packages/framer-motion/src/projection/utils/measure.ts#L14 Why? Compare the following styles on the instance: initial render

width: 200px; height: 200px; background: white; border-radius: 20px; transform: scale(1.2) translateZ(0px); user-select: none; touch-action: none;

every consequential render

width: 200px; height: 200px; background: white; border-radius: 20px; transform: none; user-select: none; touch-action: none;

So, something somewhere is updating transform property on the element and in time of the measurement the transform is set to value none. Unfortunately I did not manage to locate responsible part of the code. Maybe @mattgperry, could you give me a hand here?

vavra7 avatar Mar 04 '23 08:03 vavra7

Encountered the same bug, in my case I was changing the initial width of the element. I got to the same conclusion to just pass the width as a key and rerender the component with restraints each time the width changed

abn5x avatar Apr 13 '23 05:04 abn5x

I have the same issue. I experimented with updating the dragConstraints based on a window resize of the browser and the dragConstraints sadly don't update when my hook is called.

vogone1 avatar Jun 03 '23 11:06 vogone1

@mattgperry this issue is different from #2399 .

  • the bug still exists in the latest 10.16.7

Updated a sandbox for this issue just for your convenience to confirm it still exists in the latest framer-motion version.

And the following use case would also fail as of 10.16.7:

dragConstraints: !isMoved ? false : { top: 200 },

o-alexandrov avatar Nov 19 '23 12:11 o-alexandrov

Has this issue been resolved? Or has anyone found a workaround for this that is reliable?

prathameshkurunkar7 avatar Jun 26 '24 12:06 prathameshkurunkar7

Would love to know as well.

For me, I'm passing a ref to dragConstraints of a Div which itself is being transformed/animated on scroll. It works fine on desktop, but goes bonkers in iOS.

ynamite avatar Jan 22 '25 08:01 ynamite

Same problem here.

Passing to child motion.div dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0, }}

not working even inside a motion.div with initial={{ scale: 0 }} animate={{ scale: 1 }}

pd: unusable, had to implement the drag myself using PointerEvents, but I miss the "elastic" part from motion

kvnzrch avatar Mar 21 '25 13:03 kvnzrch

Just encountered this, I need a fix for it!

aaadamgo avatar Mar 24 '25 17:03 aaadamgo