Jump to content
GreenSock

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

Draggable invert bounds behavior

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

Hello,

 

Is there a way to invert the behavior of the bounds management.

Having a box with bigger size than the container, that could be draggable but must fill the container.

 

Best,

 

Nico J.

Link to comment
Share on other sites

Ok, maybe a solution, but not sure that this the right way.

 

with a simple example :

a container 300x300px

a box 350x350px

 

the draggable type = x,y

 

on drag end event and using the ThrowPropsPlugin plugin. I put on x and y properties min values to -50 and max to 0.

 

It seems to work, but is there a better way ?

Link to comment
Share on other sites

There are 2 separate issues here. The constraints imposed upon the object while it is being dragged and while it is being thrown.

 

During Drag:

Setting edgeTolerance to 0 on your Draggable object will ensure that the object stays fully inside the container at all times. 

 

Side note: in the latest version of Draggable, we changed edgeTolerance to edgeResistance which ultimately we find to be more intuitive but the values are the opposite of edgeTolerance:

 

edgeResistance:0 (no resistance, object can be dragged way out of bounds with no resistance, friction, slow-down)

edgeResistance:1 (full resistance, object can NOT be dragged out of bounds at all)

 

We still support edgeTolerance for backwards compatibility.

 

In your case use edgeTolerance:0 or edgeResistance:1 (assuming you have latest version of Draggable)

 

While being thrown

To keep your thrown object within the container during the animation, yes, you will have to use the min and max values for x and y inside your ThrowProps vars. 

 

Hope this helps.

  • Like 1
Link to comment
Share on other sites

Thanks Carl for your answer,

 

in fact, as my box is bigger than the container edgeResistance must be set to 0.

What could be interesting for me is exactly the invert.:

setting the edgeResistance to 1, and then, any edges of the box could not go inside the container.

But I assume that this not possible with the actual Draggable version.

 

Best

Link to comment
Share on other sites

I may have confused myself or both of us;)

 

Setting edgeResistance to 1 does not allow the edge of the dragged element to appear inside the container at all.

 

Here is a little codepen using just Draggable (no ThrowProps)

 

http://codepen.io/GreenSock/pen/be7860bda7150f574fe08ac3daa51e01

 

The Draggable element is bigger than the bounds element.

 

Isn't this the behavior you are after? 

  • Like 2
Link to comment
Share on other sites

;) i have confused for sure

 

In fact,

edgeResistance:1 (full resistance, object can NOT be dragged out of bounds at all)

 

let me think that using bounds and edgedResistance with the element bigger than the container have no sense. There are some subtleties that I do not understand.

 

Based on the codepen example and introducing the ThrowProps it appears that the behavior is exactly what I am looking for.

 

many thanks Carl for your help

  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

Hi,

 

is there any way to apply a rotation to the image and keep the same behavior ?

 

I try to modify the example you provided, adding a button that apply a rotation :

$("#rotate").on("click", function() {TweenLite.to("#drag", 0.95, {directionalRotation:'-=90_short'});});

but white space appears, as if the draggable item do not consider the rotation.

 

Best

Link to comment
Share on other sites

That's a little tricky, but I have attached an updated version of Draggable that should honor the rotated rectangular bounds - does this work for you? 

Draggable.js.zip

  • Like 2
Link to comment
Share on other sites

hi Jack,

 

it works as expected in my case.

again many thanks for your help and reactivity,
 
best
Link to comment
Share on other sites

Is this a similar issue when image is scaled ? (I used ThrowPropsPlugin to change scaleX and sclaeY properties)

Link to comment
Share on other sites

Are you saying it doesn't work with a scaled object? (sorry - I wasn't quite sure what you were asking. A simple codepen or jsfiddle example would be really useful)

Link to comment
Share on other sites

Sorry there is no problem with the scale.

I was confused by the fact that x and left are differents after a scale of the drag element.

 

However, ater an action on the image (rotation in this case), it is not possible to force the refresh of the draggable item to let it respect the bounds defined by xMin, xMax, yMin and YMax.

 

Thus some white space could appears.

I tried to calculate xmin, xmax, ymin and ymax on the complete event of the rotation,

and then use the  ThrowPropsPlugin.to method.

 

But it seems that I was not able to calculate with precision the same values ​​as the Draggable class

 

Is there a method to retrieve the bounds of an element ?

 

(The draggable you provided here is not the deploy on the cdn, thus I did not create a jsfiddle).

 

Link to comment
Share on other sites

I believe most browsers support the getBoundingClientRect() of a DOM element. Is that what you're looking for? 

Link to comment
Share on other sites

Yes I used it.

I try to correctly position the image after rotation.
Perhaps a method Update in Draggable should be interresting?
Because a simple click refreshes the position.
Anyway I do it outside the Draggable file
 
Thanks for the time you spent.
 
Best
Link to comment
Share on other sites

 

Perhaps a method Update in Draggable should be interresting?

 

 

I wasn't quite sure what you meant - what exactly do you want updated, and how would it apply to Draggable?

Link to comment
Share on other sites

If I use the Draggable class you provided in this post, start with the example just above (

See the Pen be7860bda7150f574fe08ac3daa51e01 by GreenSock (@GreenSock) on CodePen

) and modified this example like this :

 

<!DOCTYPE html><html><head>
    <meta charset="utf-8"><meta name="viewport" content="width=1000" />
    <title>GreenSock Draggable and ThrowPropsPlugin Demo</title>
    <style>body {margin: 50px;background-color: #000;font-family:Arial, Helvetica, sans-serif;}h1 {color:white;}#wrapper{position:relative;width:200px;height:200px;background-color:#ccc;overflow:hidden;}</style>
</head>
<body>
<button id="rotate">rotate</button>
<div id="wrapper">
    <img id="drag" src="http://www.snorkl.tv/images/crab.png">
</div>
<script src="js/jquery/jquery-1.10.2.js"></script>
<script src="js/greensock/plugins/ThrowPropsPlugin.js"></script>
<script src="js/greensock/plugins/DirectionalRotationPlugin.js"></script>
<script src="js/greensock/utils/Draggable.js"></script>
<script src="js/greensock/TweenMax.js"></script>
<script>
    $(function() {
        Draggable.create($("#drag"), {
            edgeResistance:0.85,
            throwProps:true,
            bounds:$("#wrapper"),
            type:"x,y",
            resistance:1000,
            snap: {
                x: function(endValue) {return Math.max(this.xMin, Math.min(this.xMax, endValue));},
                y: function(endValue) {return Math.max(this.yMin, Math.min(this.yMax, endValue));}
            }
        });
        $("#rotate").on("click", function() {
            TweenLite.to("#drag", 0.95, {
                directionalRotation:'+=90_short',
                ease:Power3.easeOut
            });
        });
    });
</script>
</body>
</html>

Click on the button to apply the rotation.

You'll see that after the rotation, the image will not fill the container.

Just do a simple click on the image, then the image will fill the container.

 

What I wanted to say was :

a method "update" in Draggable could be called when needed (in this example on the onComplete of the rotation) that allow the image to be in the right place.

 

Otherwise, in the onComplete rotation we need to implement calculations similar to those of the Draggable, to have the image in the right place. I did the calculations to put the image in the right place. So I have no problems with this behavior.

 

Maybe this method is useless because few people will be in this case.

Link to comment
Share on other sites

Ah, I see what you mean now. Thanks for the example file. 

 

I've made several enhancements to the attached update which I think you'll find useful. Specifically, there's an "applyBounds()" method that you can call to have it enforce the bounds. Here's a recap of the changes:

  1. Adds new "endX" and "endY" properties (referring to where the element will land after thrown – these properties are populated the moment the mouse/touch is released)
  2. New "pointerX" and "pointerY" properties that refer to the mouse/touch position associated with that Draggable's last event.
  3. xMax, xMin, yMax, and yMin properties have been renamed maxX, minX, maxY, and minY in order to be consistent with the other new properties like endX, pointerX, etc.
  4. A new applyBounds() method that you can call to have it enforce the bounds immediately. For example, maybe you do a manual tween of the element (outside of dragging) and it lands outside the bounds and you want to have Draggable move it back to within the bounds. 
  5. The ability to have rotated elements work with bounds
  6. New onThrowComplete and onThrowUpdate callbacks
  7. New Draggable.get() method that allows you to find the Draggable instance associated with a particular element. For example: var myDraggable = Draggable.get("#myElementID") or Draggable.get(yourElement) or Draggable.get($("#jQuerySelector"))
  8. New update() method that allows you to force an update of the Draggabe's x and y properties (sync them with the actual element's values). This can be useful if you move the element without going through Draggable, like if you tween it. The applyBounds() method automatically does this too, so you don't need to call them both.
  9. Now the Draggable's x and y properties auto-update over the course of the throwProps tween by default. 
  10. New "tween" property that refers to the actual TweenLite instance that’s generated by ThrowPropsPlugin when the mouse/touch is released. That way, you can find out exactly what the duration is and/or you can drop it into a timeline or alter the timeScale or whatever you want. 
  11. Various bug fixes and performance improvements

Please give this a shot and let me know if it works well for you. 

Draggable_0.8.1_preview2.zip

  • Like 4
Link to comment
Share on other sites

Hi Jack,

 

yes it works well, many thanks again.

The example above could be modified like this now :

$(function() {
        var draggables = Draggable.create($("#drag"), {
            edgeResistance:0.85,
            throwProps:true,
            bounds:$("#wrapper"),
            type:"x,y",
            resistance:1000,
            snap: {
                x: function(endValue) {return Math.max(this.xMin, Math.min(this.xMax, endValue));},
                y: function(endValue) {return Math.max(this.yMin, Math.min(this.yMax, endValue));}
            }
        });


        $("#rotate").on("click", function() {
            TweenLite.to("#drag", 0.95, {
                directionalRotation:'+=90_short',
                ease:Power3.easeOut,
                onUpdate :function() {
                    $.each(draggables, function(index, value) {
                        value.applyBounds();
                    });
                }
            });
        });
    });

According to the problem with IE7 and IE8, it comes from the fact that this is an image that is draggable.

Just put the image in a <div/> and it will work in IE7 and I8.

 

Best

Link to comment
Share on other sites

One point that may be important.

Let's consider the modification of the snap object like this :

            snap: {
                x: function(endValue) {return Math.max(this.xMin - 20, Math.min(this.xMax - 20, endValue));},
                y: function(endValue) {return Math.max(this.yMin - 20, Math.min(this.yMax - 20, endValue));}
            }

After the creation of the draggable object, the image is not at the right place.

just a click on the image and it goes to the right place.

 

Apply a rotation, then the image is not to the right place.

just a click on the image and it goes to the right place.

 

The js code of this example :

$(function() {
        var draggables = Draggable.create($("#drag"), {
            edgeResistance:0.85,
            throwProps:true,
            bounds:$("#wrapper"),
            type:"x,y",
            resistance:1000,
            snap: {
                x: function(endValue) {return Math.max(this.xMin - 20, Math.min(this.xMax - 20, endValue));},
                y: function(endValue) {return Math.max(this.yMin - 20, Math.min(this.yMax - 20, endValue));}
            }
        });
        $("#rotate").on("click", function() {
            TweenLite.to("#drag", 0.95, {
                directionalRotation:'+=90_short',
                ease:Power3.easeOut,
                onUpdate :function() {
                    $.each(draggables, function(index, value) {
                        value.applyBounds();
                    });
                }
            });
        });
    });
Link to comment
Share on other sites

I see what you mean - your example is attempting to treat "snapping" as the same thing as "bounds", but they're very distinct concepts. However, I can see how it would be beneficial to allow throwProps snapping to be incorporated into the applyBounds(). I've attached an updated version that should do that - please let me know if it works well for you. Also note that xMax, xMin, yMax, and yMin properties have been changed to maxX, minX, maxY, and minY. 

Draggable_0.8.1_preview2.zip

Link to comment
Share on other sites

Hi, it works well.

 

I have not had time to test different scenarios, but I will take time next week. I will make some returns if it makes sense.

 

Thank you !!!

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.

×