Jump to content
Search Community

How to stick the element to the border

hellboy 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

Hello!

I'm currently building a room planner, but I got stuck with a problem.

I want (some) elements to always stick to the wall. So my current onDrag function is:

function () {
    var $el = $(this.target);
    // You get the height, width, startX, endX (start + width), startY & endY (start + height) of that element
    var elData = getElementData($el, this);

    // Once the element is insde the planner, don't let it out anymore!
    if (this.hitTest($roomPlanner, '100%')) {
        this.applyBounds($roomPlanner);
        $el.addClass('is-in-container');
    }

    var isStickingToWand = (
        elData.startX <= 0 ||
        elData.startY <= 0 ||
        elData.endX >= roomPlannerWidth ||
        elData.endY >= roomPlannerHeight
    );
    var finalX = elData.startX;
    var finalY = elData.startY;

    if (!isStickingToWand) {
        //finalX = 0;
        //finalY = 0;
    }

    // just a helper for TweenLite.set & Draggable.update
    moveElementTo($el, finalX, finalY);
}

So, I've figured out how to detect if that element is sticking to the wall, but can't figure out how to calculate the correct final x & y. It technically works of I uncomment either of them, but not as I want, because the element doesn't stick to the border on nearest point to pointer coordinates.

post-50587-0-70322700-1486852741_thumb.png

Link to comment
Share on other sites

Sorry, forgot to add a CodePen example:

See the Pen EZGNzN by hellboy124 (@hellboy124) on CodePen

 

So for now, the element does need to be dropped first, before the detection starts working.
If you now comment in the "finalX = 0" or "finalY = 0", it will work, but not really as you would expect.

It only works, if you exactly follow along with the border with your pointer, else it just jumps and sticks to the wall (to the left one, if finalX = 0; otherwise to the top one).

Link to comment
Share on other sites

Hello hellboy,

 

Welcome to the forums!

 

When you say, always stick to the walls, do you mean, for example: it cannot be dragged into the center of the room. Or do you mean, once it is placed next to a wall, it will stick to it when you scale the room up or down?

 

If it is the first idea, it will be a matter of you having a special drag function that checks the bounds you are looking to work with and it locks the X/Y axis of your draggable depending  on where your mouse is.

 

For the second idea, I am guessing you can just clear all inline styling and to absolutely position the element onDragEnd.

Link to comment
Share on other sites

Hey,

Thanks!

The room will (for now) probably have fixed height / width, so it won't scale.

I was thinking of probably snapping on dragEnd yes.

So something similar like the liveSnap function, but the grid would need to be only along the borders (so it would always stick to the nearest border when released).

Not really sure how to do that.

Link to comment
Share on other sites

  • Solution

I can think of several ways to do this, but it's all going to depend on the behavior you want and the shape of the room. A room with more than 4 corners is going to add a little complexity.

 

I didn't see your latest posts about how you were thinking you wanted to snap on drag end, but here's how you can make it snap while dragging. I'm using a new snap point feature, which isn't the docs, but it's discussed here.

https://greensock.com/forums/topic/15705-draggable-improvements-snapping-and-position-properties/?p=68640

 

I couldn't get the axis lock to change while dragging, so I'm manually doing that. It detects if it's inside a corner, and if so, it clears the lockedAxis value, allowing it to adjust to a change in axis movement.

See the Pen 6d3b6653862f81c2cf7e9891bedc35e7?editors=0010 by osublake (@osublake) on CodePen

 

That demo allows for a little wiggle room in the corners, but if you wanted it to be a little stricter, you could skip the liveSnap and just change the bounds whenever you're inside a corner. Basically create a bounds object that will only allow movement along a certain edge.

  • Like 4
Link to comment
Share on other sites

  • 1 month later...

Hey Guys, me again. Thank you very much for the help last time!
Now, I have again one more question and it is regarding the rotation of the element, meaning, when I'm at the bottom border it is without rotation, at the top border 180, left 90 & right 270. I did make a helper function, which is triggered inside the onDrag callback, but it's not really reliable & quite jittery when it comes to borders.

function calculateRotation( self ) {
    $el = $( self.target );

    if ( self.y >= self.maxY ) {
        self.rotation = 0;
    } else if ( self.y <= self.minY ) {
        self.rotation = 180;
    } else if ( self.x >= self.maxX ) {
        self.rotation = 270;
    } else if ( self.x <= self.minX ) {
        self.rotation = 90;
    }

    TweenLite.set( $el, {
        rotation: self.rotation
    } );
    Draggable.get( $el ).update( true );
}

Now, my question is, how do I do this correctly? Thanks!

 

Edit: I currently use a variation of Blake's script (

See the Pen 6d3b6653862f81c2cf7e9891bedc35e7?editors=0010 by osublake (@osublake) on CodePen

) as the base (except I can't drag the element out of the container once it's in, but I'm sure that initially, it was also like that in this example).

Link to comment
Share on other sites

I just looked at my demos, and it looks like Draggable isn't working like it originally did. I was using the snap to point feature, but it appears broken. Here's the original demo I made to show off this feature. As you can see, it's not snapping... at least not on my machine.

See the Pen QdbQjN?editors=1010 by osublake (@osublake) on CodePen

 

I think @GreenSock will have to look into this before proceeding any further.

.

Link to comment
Share on other sites

Oh yeah, I have noticed that too. For m it still works locally, because I copied the beta JS file back then. Also for this script: 

See the Pen 6d3b6653862f81c2cf7e9891bedc35e7?editors=0010 by osublake (@osublake) on CodePen

, it doesn't work anymore like it used to. I'm sure that it initially didn't let the box out of the container. Even just yesterday, the box was kinda jumping between the container and the outside position on the mouse when I tested it -- today you can drag it outside without any problem.

So technically, it should work with that snap feature? Because for me now, the main problem is, that the element doesn't correctly stick to the wall, once it rotates.

 

When now thinking about it... I guess I probably need to apply the offset after the rotation?

For now it looks like this:

https://ibb.co/mo5wRF (before the corner)

https://ibb.co/frk7Yv (when it initially sticks to the "next" wall)

https://ibb.co/i4V7Yv (when I move it a little further, it sticks back to the first wall -- that's the "jumping" I was talking about; it does the 2. and 3. step quite a lot of times, until it's not fully sticked to the next wall -- after it does stick to the next wall, everything it fine)

 

Also, it this formula correct -- I'm currently using it, to recalculate the offset when dropping the item into the container... it kinda works, but I'm not 100% sure if that is the right way.

if (
    self.target._gsTransform.rotation === 90 ||
    self.target._gsTransform.rotation === 270
) {
    var elHeight = self.target.clientHeight;
    var elWidth = self.target.clientWidth;
    var rotationValue = elWidth > elHeight
        ? (elWidth - elHeight) / 2
        : (elHeight - elWidth) / 2;
            elementRotationOffsetX = rotationValue;
            elementRotationOffsetY = -rotationValue;
}
Link to comment
Share on other sites

I just looked at my demos, and it looks like Draggable isn't working like it originally did. I was using the snap to point feature, but it appears broken. Here's the original demo I made to show off this feature. As you can see, it's not snapping... at least not on my machine.

http://codepen.io/osublake/pen/QdbQjN?editors=1010

 

I think @GreenSock will have to look into this before proceeding any further.

.

 

Sorry about that Blake - for some reason I thought I mentioned to you that we changed "point" to "points" in the API because no matter how many times Carl and I typed it, we just kept wanting to put an "s" on there intuitively :)

 

So just change "point" to "points" and it should work great. 

  • Like 2
Link to comment
Share on other sites

  • 3 years later...

Hello @OSUblake,

I am looking for an example/suggestion where I can drag various elements into one drop area. But while dropping, if it overlaps the existing element, i want it to move to nearest available place so that it won't overlap.

 

The simple drag drop example given by you in the second post (#2) above is perfect but I am looking for additional requirement where the dropped element doesn't overlap.

 

Could you please guide me in this regard.

 

Thanks.

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