Jump to content
Search Community

Draggable bounds affected by body margin: 0

jamiejefferson test
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

I'm spending a bit of time seeing what can be done with Draggable at the moment (trying to find some way to remove jQueryUI) and I've come across the following issue:

See the Pen pjszJ by jamiejefferson (@jamiejefferson) on CodePen

With this Draggable setup, setting body { margin: 0; } makes the first drag on an element apply incorrect bounds. It seems more like the bounding rectangle is being used as a min/max x/y on the first drag. On subsequent drags the bounds seem to correct themselves and everything works as expected. body { margin != 0; }, or adding a positive margin to the bounds, causes the bounds to work correctly from the first attempt. Calling applyBounds() on drag start also seems to fix this, but still, I'm not sure why the first click would be different. Any ideas?
Also, I've noticed an odd behaviour with edgeResistance:1, where dragging outside of the bounds seems to have difficulty updating the position (expected behaviour comes with a value close to 1 e.g. edgeResistance:0.99999).
Aaaaand one more: I was just doing some quick IE testing, and don't have IE8 right now to see if it happens there, but I changed the infamous document mode to IE8 and found that line 261 of Draggable.js was causing IE to throw an error, with _transformProp being set to "" in _checkPrefix. I modified the line to
if (_transformProp) parent.style[_transformProp] = "rotate(1deg)";
and it seems to be working ok now.

Link to comment
Share on other sites

First off, thanks for doing the codepen - you know how helpful those are :)


I noticed a few problems....

  1. Since you're setting display:none on the target of your Draggable, most browsers report its offsetWidth and offsetHeight as zero (even though that isn't really intuitive or true). Draggable has to know the width/height in order to correctly calculate the bounds, so the initial calculation of width/height was zero, thus the funky behavior. The solution is to force an update of the bounds after you set the element to actually display (in your onDragStart). You were already calling update() but you forgot to tell that method to update the bounds too, so you should do update(true) instead of just update(). Or you could add that applyBounds() call afterward, but that's kinda redundant since the update() can do that too. 
  2. I couldn't replicate any strange behavior with edgeResistance:1. I tried in several browsers. Could you describe in more detail what you mean by "difficulty updating the position"? Is it in all browsers for you? 
  3. The IE8 thing was fixed in version 0.9.9, released with GSAP 1.11.4 - thanks for pointing that out. 

There are a few other things that were fixed in the latest version of Draggable, so please give that a shot. It doesn't change the whole "browser reports offsetWidth/offsetHeight as zero when display:none is applied", though. 


Thanks again for all the detailed descriptions, examples, and for hammering away at Draggable to see how far you can push it :) I love that. 

  • Like 2
Link to comment
Share on other sites

Yea I figured that display:none wouldn't have been helping, but I just found it odd that it was only happening with zero margin on the body, or positive margin on the bounds. Without those it seemed to pick up ok. Anyway, I realised in what I'm doing I need to update the bounds before most drags anyway, so it's all good now.


Sorry, should have been more clear with the edgeResistance thing (and I'm always forgetting to try things in multiple browsers). I'm seeing it in Firefox 26 and IE9, Win7 at the moment. When dragging outside of the bounds in the 4 corners (and occassionally on the sides too):

I see the drag target getting 'stuck' without sliding completely into the bounds corner. It's much more obvious when moving the mouse at higher speed. It's kind of like the mouse events just stop when the mouse is in the red zones. This only happens when edgeResistance is 1 though. 0.9999 gives the same effect of locking the element inside the bounds, except it doesn't seem to be subject to the 'sticking'.

[edit] (Draggable.js 0.9.9) it looks like reversing the "dirty" logic in onMove (commenting out lines 1083 & 1152, and inserting dirty = true after line 1150) corrects this behaviour for me, and I haven't seen any side effects... yet. Letting render() decide when things are "clean" again seems sound to me anyway, but you might be aware of something else going on there.


Chrome appears to have as many render() ticks as mouseevents, so all "dirty" moves get an opportunity to render. Firefox/IE are firing many more mouseevents than render() calls though, and dirty was being set back to false before it had a chance to render. The 0.9999 value was working because it still allowed micro variances in the tolerance-applied x/y values so the mouseevents in the corners were always dirty.


The funny thing is, I have no intention of using edgeResistance:1 for what I'm doing since I adore the resistance effect, but it's a puzzle I absolutely have to solve :lol:


The IE8 fix seems to be working well now, thanks (Jonathan - I was indeed using IE9 for this one - don't shoot me! ;))


Here's another puzzle for you - I liked the idea of just having one Draggable instance for potentially hundreds of draggable things on a page, so my original thought was to have a reusable proxy object which looked like this:

See the Pen rcbqK by jamiejefferson (@jamiejefferson) on CodePen

but I had to abandon it due to an odd issue with touch events on iOS7:
- First touch calls onDragStart - element made visible but not dragging with the finger.
- Second touch does nothing - element still not dragging
- Third touch starts dragging - onDragEnd called on release
Absolutely no idea what happened with this one, but things work a bit better with the other solution anyway (woohoo multiple finger dragging!!) so I'm not really after any 'fix' for this - just thought it was interesting to share.

Link to comment
Share on other sites

Great catch on the whole "dirty" variable thing. I've tweaked it a bit differently than you described and attached it here - can you see if this works well for you? I haven't had a chance to look at the last scenario you described (iOS7 weirdness with your proxy), but it kinda sounds like maybe an issue caused by the new proxy getting in the way of the mouse/touch events (again, just a guess at this point). 


Thanks again for all the detailed insight, Jamie. 


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.
  • Create New...