Jump to content
Search Community

hitTest() fails for non-rectangular shapes (circles, paths)

kalaschnik test
Moderator Tag

Go to solution Solved by Cassie,

Recommended Posts

Hey GSAP people,

 

My app asks the user to sort things in a stacked circles (or rather rings, as stacked circles are also an issue for the hitTest()). I highlight the corresponding circle whenever hovering the dragged object over it. I noticed, however, that hitTest()  seems to use the bounding box, and thus I could place objects outside the circles or in other rings when coming e.g., from a northwest direction.

 

Is there any way to solve this issue?

 

circle-gsap-hittest.gif.311f74d270fb8f9d70801bd7aa82404a.gif

See the Pen MWXzwGo by Kalaschnik (@Kalaschnik) on CodePen

Link to comment
Share on other sites

  • kalaschnik changed the title to hitTest() fails for non-rectangular shapes (circles, paths)

Update, I added some eventListener for mouseenter and mouseleave, and noticed that those listener don’t use the bounding box rather than the shape itself and the actual mouse entry position (hence the names mouseenter, mouseleave :)). Interesting. Thinking about a way to combine draggable, hitTest and the detection of mouseenter, mouseleave ...?

Link to comment
Share on other sites

Ah ok, so the issue here is that hittest uses bounding boxes - it's correct in that the bounding boxes are overlapping - you can see if we put a border on

See the Pen mdGQvdM?editors=0110 by GreenSock (@GreenSock) on CodePen

 

From the docs -

Quote

IMPORTANT: There is no way to get pixel-perfect hit testing for non-rectangular shapes in the DOM. hitTest() uses the browser's getBoundingClientRect() method to get the rectangular bounding box that surrounds the entire element, thus if you rotate an element or if it's more of a circular shape, the bounding box may extend further than the visual edges. IE8 (and earlier) is not supported because hitTest() requires element.getBoundingClientRect() which is in all modern browsers.


Blake put together a demo for circles here which may be of use to you!

 

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



 

  • Like 3
Link to comment
Share on other sites

Sure this is custom code so you can do anything you like, you just have to work out the logic.

for example - 

 

// these lines are finding out the radius distance to use in the hit test, this is half of the circle
var r1 = circle1.width() / 2;

// so you can change the radius distance to trigger a different distance into the circle
var r1 = circle1.width() / 4;

 

Without jQuery and with a console log for the dragEnd

See the Pen vYzQMMg?editors=1010 by GreenSock (@GreenSock) on CodePen

  • Like 3
Link to comment
Share on other sites

Ok, so this right here was the original value
 

var r1 = circle1.offsetWidth / 2; 
var r2 = circle2.offsetWidth / 2;

 

That's grabbing the radius of both the circles, once we have that we can grab the position of their center points and compare the two numbers.

When the distance between their center points is equal to that number (or less than) then they're intersecting.
 

It usually helps me to break apart demos like this and rewrite it myself with notes and clearer variable names if I'm finding it confusing.

  • Like 1
Link to comment
Share on other sites

offsetWidth is the same as width, that's just vanilla JS instead of jQuery - I updated the r1 variable for you in that latest demo, sorry if that was confusing, I'd just adjusted it to do 50% like you asked in the previous question!

  • Like 1
Link to comment
Share on other sites

  • Solution

Heya!

 

I had to rewrite it a little as my brain struggles to understand other peoples maths, gotta work through it step by step in my own head!

Basically we just need to work out the distance between the centers of the two circles by adding their radii together. Then the next job is to grab the center coordinates of each circle so we know where they're positioned in the SVG.

 

Then when we drag we can calculate the distance between the centers of the two circles using the Pythagorean theorem and check if the distance between the centers of the two circles is less than or equal to the distance between the centers when the circles are intersecting.

Geometry is cool

 

See the Pen dyqwvwY?editors=0111 by GreenSock (@GreenSock) on CodePen

  • Like 3
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...