Jump to content
GreenSock

Ratchet

Nested draggables

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

Hi there,

I consider using Draggable in my mobile game (either with or without throwprops), in a similar fashion to games like WordFeud: a draggable stage with draggable tiles on it. For this it seems most logical to have draggable objects inside a div that is itself draggable. This seems to work somewhat, though when I drag the tile, the draggable stage also moves (hence the tile itself moves twice the dragged distance). it seems easiest to cancel propagation of the event using the onDragStart callback, however it seems that no event object is passed into this callback so I cannot call e.stopPropagation(). Who has an elegant solution for nested draggables? By the way, I also tried temporarily .disable() on the top draggable but that gave serious javascript/dom errors.

 

Here is my code so far. HTML:

<div id="scrollContainer">
  <div id="scroller" style="overflow: visible; padding: 0px; position: relative; height: 300px; width: 300px;">
    <div id="tile0">
      <img src="img/tile_0.png" style="position: absolute;top:0">    
    </div>
  </div>
</div>

And js:

Draggable.create("#scroller", {type:"scroll", edgeResistance:0.5, throwProps:true});
Draggable.create("#tile0", {type:"x,y", edgeResistance:0.65, onDragStart: 
function(event){
  //event not available here?
}});

 

Link to comment
Share on other sites

Hi and welcome to the forums.

 

Please check the update preview from this particular reply:

 

http://forums.greensock.com/topic/8189-problem-with-new-draggable-plugin/?view=findpost&p=32055

 

And let us know if it solves the problem.

 

Also it'll be very helpful if you could set up a simple codepen or fiddle with the isolated issue in order to get a better look.

 

Best,

Rodrigo.

Link to comment
Share on other sites

Hi,

 

Try the following code please:

var child = $("#child"),
    parent = $("#parent");

var parentDrag = Draggable.create(parent,
{
    type:'x'
});

Draggable.create(child,
{
    type:'x',
    onDragStart:function()
    {
        parentDrag[0].disable();
    },
    onDragEnd:function()
    {
        parentDrag[0].enable();
    }
});

I believe the problem might be on the disable and enable calling.

 

You can see it working here:

See the Pen Ehjbd by rhernando (@rhernando) on CodePen

 

Best,

Rodrigo.

  • Like 2
Link to comment
Share on other sites

Thanks a million, rhernando, your fiddle was really helpful!!!

I am getting close to what I want in this fiddle:

See the Pen spiqK by anon (@anon) on CodePen

However, here I also implemented a zoom on the contents upon doubleclicking BUT after zooming 2x, the dragged distances are (again) multiplied by two. Do you or anyone else know of some way to avoid that? Also, I would like to implement pinch zooming (with two fingers) on the parent draggable, is this a viable option? 

Link to comment
Share on other sites

You're welcome.

 

Sorry that you're still having problems, but I'm afraid that this issue has nothing to do with GSAP or a browser quirk. This is basically the nature of amplifying stuff.

 

For example if you look at an ant through a magnifying glass (please beware of the sun!!! the poor little ant hasn't done anything to you :D) that doubles the size of what you're looking, you'd see that the ant goes a specific distance in two seconds, but the fact is that the ant moved half that distance, it just seems like it moved more. The same happens in your sample, if you check with a console.log call for the draggable element's position you'll see that it moves one pixel, but since you scaled everything in a factor 2.2 it seems that it went 2.2 pixels, so if you translate the element 50 pixels it seems that it moved 110 pixels.

 

One option could be to create a mechanism to check the element's position on every drag update, store it in a variable, then check for the next update calculate the difference between those values divided by the scale factor, in this case 2.2, and finally tween the element in that direction by that amount.

 

Perhaps there's a way to constrain the drag displacement in the draggable element created but I'm not aware of that, Carl or Jack could enlighten us in this subject.

 

Best,

Rodrigo

Link to comment
Share on other sites

Looking at the Draggable source code, I think it would be very simple for the developers to implement it in Draggable directly. Look at it as a kind of dragResistance property, similar to the edgeResistance. Then basically the GreenSock developers need to change these lines in their internal onMove callaback (line 712)

yChange = (e.pageY - startMouseY)*dragResistance;
xChange = (e.pageX - startMouseX)*dragResistance;

 

I would then simply need to feed a new dragResistance (=1/zoomFactor) to the child draggables each time the zoom level changes. A dragResistance property could also be desirable in some situations when you dont want the object to follow the mouse.

Link to comment
Share on other sites

It isn't quite as simple as adding that dragResistance factor, mostly because of some complications with handling rotation and the way Math.atan2() works, but I hacked away at it and I believe the attached files should give you what you're after. This is a preview of the upcoming 1.11.0 release. Note that rotational data is not degree-based instead of radian-based in order to be consistent with the way CSSPlugin interprets things (plus it seems more intuitive). This change affects more than just Draggable, so please make sure you're using the attached versions of TweenLite and CSSPlugin too. 

 

You can set the dragResistance to a value between 0 and 1. Please give it a shot and let me know if it works well for you. When I dropped it into your test codepen, it seemed to work well. 

GSAP_1.11.0_rc1.zip

  • Like 3
Link to comment
Share on other sites

Wow, I didn't anticipate this level of service, thanks Jack!

I will check it out as soon as I have the time....

  • Like 1
Link to comment
Share on other sites

Hi Jack,

I checked it out and it does the job, awesome work!

2 remarks:

- I update the dragResistance of each node at runtime by directly setting the .dragResistance property, is this the recommended way or is this 'hacky' (i.e. should there be a setter function)?

- I actually needed a negative dragResistance because I decided to scale the contents down rather than up. I found out that setting it to -1 works to speed up the dragging by a factor 2. So it's fine by me, I'm happy it's supported in the first place, though it feels a bit unintuitive to put a negative number.

 

A bit unrelated: What is the recommended way to scale the contents of a "scroll" without increasing the scroller itself? there are some unexpected things happening when I scale the contents of a "scroll" draggable using css transforms (i.e. the scale property). Because I don't want the draggable container itself to scale, I put everything in a wrapper div which I scale with TweenLite. However, zooming in and out (by multiple doubleclicks), the width of 'your' injected wrapper does not revert back, not even after disable and re-enable, hence the scrollable area is way too big. Also, this behavior is browser specific (on iPad it does resize itself back, on Chrome it doesn't). 

You can see this behavior if you doubleclick twice in the following example, and then pan to the right (there is a black area). Additionally, the edgeResistance at the bottom and right edge seem to reset to 1 in the process.

 

See the Pen Ihmgz by ratchet (@ratchet) on CodePen

 

(dragResistance obviously does not work in this example since the library is loaded from the cdn)

Link to comment
Share on other sites

Glad to hear things are working much better with that update.

 

Unfortunately, we just don't have the time to tackle the complexities involved in the zooming stuff you're attempting right now - that's not really something that Draggable was made to do. I suspect that handling bounds could also get awkward with the zooming (especially if rotation gets involved). If you have a particular project that you need this for and would like to hire us on a consulting basis to help iron out some specific challenges, let us know. I really wish we had the time to tackle every challenge that comes our way for free, as I find it quite fun to dig deep and create innovative solutions. But alas, there are limited hours in the day and we've got lots of neat stuff we're working on right now for the rest of the platform. 

 

Oh, and yes, it's fine to be altering the dragResistance property directly.

Link to comment
Share on other sites

Hi Jack,

I totally understand... I will hack my own way around it ;)

It would be a nice (and quite logical) feature though to have pinch zooming out of the box, then it could completely replace popular (but flawed) hacks like iScroll. Just an idea for the future.

Thanks again!

Link to comment
Share on other sites

FYI, I posted an updated preview of the upcoming GSAP 1.11.0 release at http://forums.greensock.com/topic/8339-draggable-on-windows-8-touch/#entry32419 in case you want to take a peek. A lot of work has been done on the guts. Please kick the tires if you've got time and let us know how things work for you. 

Link to comment
Share on other sites

  • 2 weeks later...

I believe I found a bug with nested draggable.

 

If you look at this fiddle http://jsfiddle.net/9Z92w/3/, it's working fine.

 

But when you add throwProps into the mix, you get an error the second time you try to drag, "TypeError: ce.tween.isActive is not a function".

 

Check out this fiddle.

http://jsfiddle.net/9Z92w/4/

 

PS: in the second example, I'm using the upcoming GSAP 1.11.0 release

Link to comment
Share on other sites

That just means you're not using the updated 1.11.0 version of GSAP (isActive() is a new method). So please make sure you update ALL of your GSAP/Draggable files ;)

Link to comment
Share on other sites

Does this mean I need to upadte the ThrowPropsPlugin also? It wasn't in the zip you provided which is normal because it's a paid plugin! :)

Link to comment
Share on other sites

Yep, there were a few minor changes to ThrowPropsPlugin (mostly to go with the change in CSSPlugin/Draggable to use degrees instead of radians for rotational data). If a "Shockingly Green" or "Business Green" member wants to get early access to that, just shoot me a PM or e-mail request. Steven, it looks like your membership expired last year :(

Link to comment
Share on other sites

Just renewed it! I'll PM you for the file.
I can't congratulate you guys enough for all the outstanding work you guys do.

Link to comment
Share on other sites

Excellent! Thanks for joining again. I just sent you the files via e-mail. 

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.
×