Jump to content


Offset draggable bounds

Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

One nice thing about using an element instead of min/max values for a Draggable's bounds is that the bounds automatically adjust if the bounding element resizes. But sometimes you don't want the bounds to extend all the way to an element's edges, so you have to pass in min/max values. The problem with this is that your bounds won't change on a resize, so you have to manually calculate and apply a new bounds object. What if we could combine the two approaches?


There are many times where I want the bounds to be offset just a little bit from it's container, and have to decide between passing in min/max values or creating a new element specifically for the bounds. It would be nice if I could skip this, and just pass in an element with optional min/max values. 


Consider the following...

Draggable.create(".box", {
  bounds: { target: "#container", minX: 10, maxX: "+=50", maxY: "-=25" }

If the .box element is 100 x 100 and the #container element is 500 x 500, then the bounds would be calculated as:

minX: 10,

minY: 0,

maxX: 450,

maxY: 375


Here's a demo of what this would like in action. The container is in black, and the offset is in red. If you resize the window, it still maintains the offset bounds.

See the Pen 209886d85a136b79ff9bdafae542e3e1 by osublake (@osublake) on CodePen

Link to comment
Share on other sites

Interesting concept. What if the API was one of these?:

bounds:{target: "#container", margin:"0 50 -25 10"}
// - OR -
bounds: "#container",
boundsOffset: {top:0, left:10, right:-25, bottom:50}

I worry a little bit about adding yet one more property/feature that makes the API feel complex, but I see what you mean about the convenience of offsets. I'll have to chew on it a bit. If others have a need for this, please chime in and cast your vote. 

  • Like 1
Link to comment
Share on other sites

The margin one would probably confuse people trying to remember TRBL. But the offset one is actually what I first thought of, but changed it because I was thinking about being able to use both relative and absolute values.

Link to comment
Share on other sites

Hi guys :)


Blake , have you tried something like this?  :

Draggable.create(".box", {
        B = document.getElementById('container').getBoundingClientRect();


function Bounds( D , bounds , offsetRight, offsetBottom ){
  var B = document.getElementById(bounds).getBoundingClientRect();
  D.applyBounds({ top:0 , left:0 , width:B.width-offsetRight , height:B.height-offsetBottom });

Draggable.create(".box", {
  onPress:function(){ Bounds(this,'container',100,50) }

See the Pen wBLqKE by MAW (@MAW) on CodePen

  • Like 2
Link to comment
Share on other sites

Interesting approach. I've done that before creating a draggable, but never during a press.

Link to comment
Share on other sites

  • 1 year later...

Did you guys ever introduce anything into Draggable regarding this? I noticed it was a little over a year old. I'm trying to set an outer offset for a nested SVG group but it's rather involved. I tried using Diaco's solution but the problem is, the bounds is being set on an SVG wrapper that's inside a Draggable div. To make things even more fun, I have a resize handle for the group that resizes the SVG inside the group and the group is the Draggable element inside the bounds area.


I'm trying to allow the group to be draggable up to half the SVG width/height outside the bounds. So, if you wanted to place it a little "off-stage" you could. Basically I want to be able to drag it all the way to the point you have just enough to drag without losing it. So, really, more than halfway.


As long as the stage-container is not draggable it sort of works - had to use a few cluge factors to get it working right even then. But as soon as you drag the stage-container, it falls apart. I tried playing around with different position parameters on various elements but no luck.


Here's the codepen I'm using to play with this. 

See the Pen dXqaZd by swampthang (@swampthang) on CodePen


Structure is like:

#stage-container -# Draggable applied to it
  #handle Drag handle -# position: absolute, height: 30px, top: -30px
  svg#stage{width: 800, height: 400}
    g#gp-0.svg-wrapper -# Draggable the wrapper for the actual svg image
      svg#svg-0{class: 'svg inline'}


What if there were a bounds option that was tied to the mouse position rather than the object itself? So, maybe one of the options could be:

{useMousePosition: true}

Did a little digging and found out that I had access to this.pointerX this.pointerY inside the onDrag function. Playing with that some right now.


This works but falls apart after rotating the SVG...

See the Pen PzdgPW?editors=1010 by swampthang (@swampthang) on CodePen

Link to comment
Share on other sites

Ok, all good now. Had to store the Draggable obj in a variable and use disable()/enable().


I personally think this could be a really cool thing to include in Draggable. In order to get it to work correctly though, you have to set {throwProps:false} because it can get away from you at the edges before it disables and you'd be able to throw it out of bounds and lose it.


My 2-cents.


See the Pen PzdgPW?editors=1010 by swampthang (@swampthang) on CodePen

Link to comment
Share on other sites

Thanks for the suggestion. We'll keep it in mind as a possibility for the future especially if a lot of people request it. Cheers!

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.