Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Asderex

Bounding React draggables inside another React component

Recommended Posts

Hi

 

Just discovered GSAP and what a great library it is!  I am having a problem with bounding my draggable components in my React testing.  I have followed the great instructions found here (https://greensock.com/react) to get a reference to the React generated DOM element and haven't had any problems making them draggable. 

 

The draggables sit inside of another React component which should act as the bounding element.  I am again getting a reference to this element as previously described and passing this into the draggable components as props - to be referenced by the draggable childrens draggable.create. This works (in that it doesn't throw any errors and my console logs are showing the correct DOM element being passed in) but the draggable bounds are behaving very oddly.

 

A demo paints a million words so you can see what I mean here (I'm a bit more comfortable in codesandbox.io):

 

The draggable elements appear to be bounded by something (not a DOM element I recognise) that is exactly 4 times their size and not their parent component?

 

I have seen demo's, such as this 

See the Pen dvgePz?editors=0010 by expdev (@expdev) on CodePen

where they are successfully bounding a child react component in its parent.  The only obvious difference to me appears to be the use of a class component over a functional component but, again, I'm not sure why that would make a difference?

 

Note: I'm not adverse to using a class component but would love to understand why this is behaving the way it is. Any tips or suggestions welcome!

See the Pen by s (@s) on CodePen

Link to comment
Share on other sites

23 minutes ago, Asderex said:

I have seen demo's, such as this one where they are successfully bounding a child react component in its parent.  

 

That link is not working.

 

24 minutes ago, Asderex said:

The only obvious difference to me appears to be the use of a class component over a functional component but, again, I'm not sure why that would make a difference?

 

Note: I'm not adverse to using a class component but would love to understand why this is behaving the way it is. Any tips or suggestions welcome!

 

I don't see a parent element being passed down. Try using classes and let us know how it goes.

  • Like 2
Link to comment
Share on other sites

Hi and welcome to the GreenSock forums.

 

Unfortunately I don't have a lot of time to check the details of your demo and see what could be causing the issue.

 

As far as passing a Component Ref down as prop, those are objects and there is definitely nothing against passing objects as props, since you're not actually passing the object but the reference, but is not something I would do. Instead of passing the result of the Ref callback (as that suspicious article you mention says ;)) I would try to use Forwarding Refs in order to get the DOM elements of each element you want to make draggable in the parent and create the draggable instances there, where you have direct access to the reference of the actual DOM node that would act as the bounds. Since you're using functional components it should be fairly easy. In this sample instead of creating a TweenLite instance you would create a Draggable one:

 

https://stackblitz.com/edit/react-forwarding-refs-gsap

 

Another alternative is to take advantage of the fact that bounds can be passed as an object, so you can use the dimensions of the parent component and pass it down as a prop to the child component and use that rectangle to enforce such bounds using positioned elements, offsetTop and offsetLeft to calculate the bounds when the Draggable instance is created.

 

As you can see there are a couple of alternatives that I can think right of the top of my head. i'm pretty sure that other solutions are possible and that hopefully these will help you getting started.

 

Happy Tweening!!

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Thank you both for coming back with suggestions!  I looked into forwarding refs (great suggestion).  I was worried about putting behavior/logic related to the children into the parent component so I thought I could create a forwarded ref for the parent component and pass this same ref down to the children to use as the "bounds" property.  Demo.

 

I think that in my original example the Draggables were being created before the DOM was actually rendered.  The elements therefore didn't exist which is why @OSUblake noted he couldn't see the parent element being passed down.  The new solution is showing the correct DOM element in the console but I still seem to be getting the same weird drag result (exactly 4 x the area of the draggable div's centered on screen).

 

I could try your original suggestion @Rodrigo (forward refs from the parent to the children and define the draggable in the parent) but I'm not sure how to handle the case of an arbitrary and dynamic number (and type) of children being added to the draggable area i.e. Could be 4 squares, then 2 Circles could be added, the 3 triangles....it can't be defined at design time.

 

And apologies -  I had it in my head that the second example in my original post was a nested react component but it's not, it's just a single component so I don't think the class / functional debate comes into it.  Thanks again for your suggestions.

 

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, Asderex said:

I think that in my original example the Draggables were being created before the DOM was actually rendered.  The elements therefore didn't exist which is why @OSUblake noted he couldn't see the parent element being passed down.  The new solution is showing the correct DOM element in the console but I still seem to be getting the same weird drag result (exactly 4 x the area of the draggable div's centered on screen).

 

That seems to be caused when the object has no dimensions or isn't an element. Not sure if that something @GreenSock should look into preventing. ?

 

Draggable.create(domElement, {
  bounds: {} // creates a weird bounding box
});

 

 

But it looks like you're close to getting the correct bounds. This works with your latest demo.

 

Draggable.create(domElement, {
  bounds: parentDOMElement.current.current
});

 

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Thank you @Rodrigo for pointing me in the right direction and @OSUblake for getting me over the line. Looking at the forums and I have to say GSAP has a very helpful community here.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×