Jump to content
GreenSock

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

Draggable.hitTest in a scrolled window

Recommended Posts

While doing hit test while the window is scrolled, I don't seem to get the correct results.  This occurs if I am trying to compare the pointer event of the mouse.  The code pen example demonstrates it: the top 2 boxes will work correctly, but if you scroll the demo window down and try with the bottom 2 boxes the hittest will still return false.

 

My initial thought is that this has something to do with some confusion or misuse somewhere between clientx/pagex, but I'm just beginning to investigate.  Any ideas or pointers?

See the Pen zGbLBp by acamp (@acamp) on CodePen

Link to comment
Share on other sites

Hi Andy,
 
What jumps right out is the fact that you're passing an event object as the second parameter of the hitTest() method. The second parameter is normally the overlapping amount (in pixels or percentage) between the two elements and that's either a value or a string. In this case you're passing either a mouse or touch event object. Second you're trying to use the static version of the hitTest(), why not use the regular one:

hitTest = this.hitTest("#drop1", e);

That actually works with the setup you have in place.

 

It seems that Draggable is not updating the new position of the hitTest target after a scroll when using the static hitTest method, perhaps Carl or Jack could explain this. Meanwhile hopefully the code above helps.

  • Like 1
Link to comment
Share on other sites

Draggable uses pageX/Y for events, but you can create your own point like this.

var x = e.clientX;
var y = e.clientY;
var point = {      
  left: x,
  right: x + 1,
  top: y,
  bottom: y + 1
};
var hit = Draggable.hitTest(element, point);

So here's your example with that...

See the Pen zGbLja by osublake (@osublake) on CodePen

 

And here's a demo I made that demonstrates why hit testing a event might not be what you expect.

See the Pen JoQbya by osublake (@osublake) on CodePen

  • Like 3
Link to comment
Share on other sites

Thanks Rodrigo - thanks for the reply.  My example is a bit contrived.  I agree that if I compare the 2 boxes with the non static version, things work well, but for my actual application I'm looking to do a hittest with the pointer event - the dragging example was a convenient way to show this.  But the hitTest docs (http://greensock.com/docs/#/HTML5/Drag/Draggable/hitTest/) state that a pointer event is a supported object...

Link to comment
Share on other sites

Thanks Blake.  I was just finding my way to this, that's a sweet codepen Demo :).  Thanks for the tip on using clientX/Y, that does seem to solve my problem... (although getting clientX/Y on touch events is my next complication).

 

I'm curious why hitTest uses PageX/Y for pointer events... it appears that for DOM elements it uses getBoundingClientRect(), which is a clientX/Y based result.  So it would make sense to use clientX/Y for everything when doing hit tests...

Link to comment
Share on other sites

Thanks! I thought it was a pretty cool demo, but you're the only person who has acknowledged it.

 

I don't know why it uses pageX/Y, but I ran into the same problem and I saw in the source code that it just creates a 1x1 rectangle to test.

 

What touch problems are you having? I would just look at how Draggable handles them because they are spot on. 

  • Like 1
Link to comment
Share on other sites

Thanks! I thought it was a pretty cool demo, but you're the only person who has acknowledged it.

 

I had never seen it before, but I'll acknowledge it now - that's cool!   8-)

  • Like 1
Link to comment
Share on other sites

Thanks Greensock, that version doesn't seem to solve the problem, although I did a diff and there were no differences in the parseRect() or hitTest() functions between the version 1.14.1 you linked and version 1.14.0 (of my current draggable file) that I am using.  There were some changes from self to this, and some changes in the _cache function.

 

Edit: I updated my codepen at 

See the Pen zGbLBp by acamp (@acamp) on CodePen

to point the latest-beta link above.

Edited by andycamp00
Link to comment
Share on other sites

For blake:

 

What touch problems are you having? I would just look at how Draggable handles them because they are spot on.

 
No problems, but for touch events, the events store data differently - and I can see several examples of this in the Draggable code with comments like:

 

if (e.changedTouches) { //touch events store the data slightly differently

 

The event object from a touch doesn't have a clientX or clientY prop, but they have a changedTouches property that is an array of points with clientX (and, on iOS at least, also a touches property that is an array of points..)

 

Anyway, I'll look through Draggable and see how it works, it seems to be using changedTouches all the time.  Not too bad; I wasn't looking forward to figuring out all the compatibility issues for different touch platforms... but it doesn't look too bad.

Link to comment
Share on other sites

so my current workaround code modifies blakes slightly:  

var x, y;

if (e.changedTouches) {
  x = e.changedTouches[0].clientX;
  y = e.changedTouches[0].clientY;
} else {
  x = e.clientX;
  y = e.clientY;
}

var point = {      
  left: x,
  right: x + 1,
  top: y,
  bottom: y + 1
};
var hit = Draggable.hitTest(element, point);

This works on iOS at least, for a normal touch-drag scenario.  I need to learn more about changedTouches prop to find out if it is universal and if using the first element in the array is always OK...

Link to comment
Share on other sites

Hi andycamp00  :)

 

Pls add something like ' ?20 ' at the end of js address to prevent browser using old/cashed one .

 

pls check this out : 

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

Link to comment
Share on other sites

Ah, of course... that works.  Thanks!  I'll mark the original link from to the fix as solved.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Hi Jack,

Thank you for the fix in the Draggable-latest-beta.js. It works great.
However there is a an exception being thrown in IE8 when I call this line:
 

if( Draggable.hitTest(this, e) ){
}

 
 
File: Draggable-latest-beta.js
Line: 2127 
 
Unable to get property 'getBoundingClientRect' of undefined or null reference
 
This is the faulty line:

var r = (e.pageX !== undefined) ? {left:e.pageX - _getDocScrollLeft(), top:e.pageY - _getDocScrollTop(), right:e.pageX - _getDocScrollLeft() + 1, bottom:e.pageY - _getDocScrollTop() + 1} : (!e.nodeType && e.left !== undefined && e.top !== undefined) ? e : _unwrapElement(e).getBoundingClientRect();

 
Do you have an idea what is causing the error?
 
Thanks!
 
Simon

Link to comment
Share on other sites

Technically hitTest() isn't supported in IE8 and earlier (those browser have zero support for getBoundingClientRect() as you discovered which is rather important. However, I did update the preview so that at least it shouldn't throw errors now: https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/Draggable-latest-beta.js (you may need to clear your cache). Does that work better for you? 

  • Like 2
Link to comment
Share on other sites

Oh I see. Yeah, the new latest-beta doesn't throw the error anymore.

Thanks for clarifying this so quickly. 

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