Motion: [FEATURE] Support dragging one element to move another ( drag handles )

Created on 19 Dec 2019  路  7Comments  路  Source: framer/motion

Is your feature request related to a problem? Please describe.
Hello, I'm wondering if there is a supported way to implement drag handles ( a draggable section of an element, or dragging a child to move the parent ) at the moment. I've had some luck with /dev/examples/dragExternalValues but the need for _props and lack of documentation isn't ideal.

Describe the solution you'd like
Ideally, a dragHandle prop that accepts a ref with the element we want to use as a handle.

<Container drag dragHandle={dragHandle}>
  <Handle ref={dragHandle} />
  ...
</Parent>

Dragging the handle element would move the container element, dragging inside the container but outside the handle would not register as a drag. Essentially the top bar of a macos window would be a dragHandle to the main window.

Describe alternatives you've considered
The only current alternative seems to be the _dragX, _dragY, and __dragTransitionControls props. These work well but are not documented as far as I can tell and don't feel as clean as the rest of the library.

Thanks again for the library. It's fantastic.

feature

Most helpful comment

@alacroix You can probably add a mousedown/pointerdown event to the element itself (via a ref) and calling event.preventDefault. But yeah we can take this a step further and look into adding a prop or something that suppresses this.

Approach 1

<motion.div drag="x" dragListener={false} dragControls={dragControls} />

Approach 2

function onMouseDown(event) {
  dragControls.start(event, { axis: "x" })
}

return <motion.div dragControls={dragControls} />

All 7 comments

Those props are only for internal use so you could expect those to break. There isn't currently a clean method of doing this other than something like this:

const x = useMotionValue(0)

return (
  <Container style={{ x }}>
    <Handle
      drag
      dragConstraints={{ top: 0, left: 0, right: 0, bottom: 0 }}
      dragElastic={0}
      onDrag={(_, { delta }) => x.set(x.get() + delta)}
    />
  </Container>
)

There's a few related issues with dragging, for instance initiating dragging manually from something other than the element itself as a drag source. When I come to look at those I'll consider this usecase also.

Sounds good. Thank you for response.

Hey @InventingWithMonster, thanks for the quick implementation.

I'm in a similar case as @DexterShepherd and I can't figure it out to prevent dragging from the Container component when using useDragControls.

Here is a small codesandbox : https://codesandbox.io/s/usedragcontrols-handle-l62i0

Is there any way to prevent the drag input from the Container and only allow the handle to drag it?

Thanks

@alacroix You can probably add a mousedown/pointerdown event to the element itself (via a ref) and calling event.preventDefault. But yeah we can take this a step further and look into adding a prop or something that suppresses this.

Approach 1

<motion.div drag="x" dragListener={false} dragControls={dragControls} />

Approach 2

function onMouseDown(event) {
  dragControls.start(event, { axis: "x" })
}

return <motion.div dragControls={dragControls} />

Thanks for your quick reply @InventingWithMonster.

I tried to implement your solution but it seems that motion.div overtakes the onMouseDown even when passing a ref. (https://codesandbox.io/s/usedragcontrols-handle-bxdsg)

I like both approaches. For the approach 2, we will still able to set drag props like dragConstraints on the motion.div? We just need to set the axis option on the dragControls.start, or I misunderstood the approach?

Yeah because drag might only optionally be on the component, and it's where we define axis, we'd have to define it somewhere else. But everything else would be on the component.

However I'm thinking approach 1 would probably be better. Keeps the number of permutations saner.

Yeah it's more explicit also. Do you need any help to implement this? I'm not an expert but I can try, if you give me indictions on where to look.

Was this page helpful?
0 / 5 - 0 ratings