Jump to content
Search Community

Draggable hitTest()

andyr test
Moderator Tag

Go to solution Solved by OSUblake,

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

Yep, the problem was that you were using the static Draggable.hitTest() method which needs at last TWO parameters (the two things you're comparing/hitTesting). You probably intended to use the instance-based hitTest() method which Diaco is referencing with this.hitTest(). 

  • Like 3
Link to comment
Share on other sites

Yes, any DOM element that has had any css transforms set on it through GSAP will have a .gsTransform object on it which stores all the transform values like: scaleX, scaleY, rotation, x, y, skewX, skewY.

 

Here is a demo that shows how to get the x of an element that you collide with while dragging:

 

EDIT: wrong link previosly, use:

 

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

 

-- nice work, Diaco!

  • Like 2
Link to comment
Share on other sites

Looking at this Codepen: 

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

// Calculate x pos to slide to.  Starting at target items' current x position.
var x_pos =  item.target._gsTransform.x - item.width;
console.log(x_pos);

// Slide the 'hit' item.
TweenMax.to(item.target, 1, {x: x_pos});

I'm dragging a box right.  On 50% threshold, the "hit" box slides left.

 

I'm using the hit box's _gsTransform.x - the width of the dragged box to determine the x_pos to slide to.

 

However, the _gsTransform.x getting applied to TweenMax.to isn't the _gsTransform.x of the first hit, 

but the value when the "hit box" and the dragged box are no longer hitting (the x position where the left edge of the dragged 

box stops hitting the left sliding box).  Which makes sense of course, but...

 

Any way to get that first hit x value?

 

Thanks.

Link to comment
Share on other sites

That's the correct behavior. Your hit test is going to be updating the values while the two boxes are moving past each other. You're going to have to add in some logic to not do a hit a test on a box that is moving, like flagging the element with a certain class name. 

  • Like 1
Link to comment
Share on other sites

Forgot to mention, that it also helps to determine the user's intent before trying to move a box. I had to manually calculate that in the sortable demo, but now Draggable includes getDirection to determine the direction you are dragging. You can use this feature to prevent triggering a move in the wrong direction, which can happen when you're moving elements to a new position.

  • Like 1
Link to comment
Share on other sites

Thanks OSUblake.

 

Yes, I'll need to get ThrowProps plugin to get getDirection('velocity').  For now I'm doing a simple, last_x vs this.x comparison to determine drag direction, like in the demo.

 

I've been trying various methods to do a draggable photo gallery.  The way I was trying to do it above (not touching the DOM and using the transform values to get their positions, then move things around) - won't work responsively.  

 

So I either do it:

 

a. Percentage co-ordinate positions based on the bounding box.

b. Inserting DOM elements - which your grid demo linked above appears to do.  

 

Not sure which is the best method.

 

I was having trouble updating the layout and inserting nodes.  

 

Will have to post a CodePen tomorrow.

Link to comment
Share on other sites

Are you still using Angular for this?

 

The inserting of DOM elements isn't strictly necessary. That demo was converted from Angular, which automatically does that in an ng-repeat. Angular also sets a new $index on each element, which I used to figure out where to move an element.

 

Once everything in the DOM is in the correct order, you can run all the elements through a loop to position them correctly. This assumes that all the elements are positioned absolutely from the same origin.

Link to comment
Share on other sites

  • Solution

If you are using ngRepeat, you don't mess with the node positions. You change your model, and Angular will reorder the elements. The model ngRepeat is using is probably an array, so you can use something like this to update your array...

myArray.splice(toIndex, 0, myArray.splice(fromIndex, 1)[0]);

This will place your elements in the correct order, but because they are positioned absolutely, they will visually be in the same place before you updated your model.

 

Now you have to run some logic to put them in the correct order visually, which can be done a lot of different ways. The main thing is that they are now in the correct order with the correct $index, so you can run them through a loop, setup some $watch expressions, or $broadcast an event to get your directives to animate moving to a new position.

 

For example, if your elements are 100px wide with no gutter space, and an element's $index is 3, you would place it at x = 300.

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