Set Position During Drag using Jquery Draggable Div

11,298

Solution 1

Yes, I did finally figure it out. I had thought that .position was a read only property... but it turns out you can also use it to set the position as well. So, in the code above, I'm creating a variable called result and storing the return value from the limit function (which returns the x and y values of the mouse capped within the containment circle). So, after that you just have to call this:

ui.position={'top': result.y-10, 'left': result.x-10};

You'll need to remove the line:

$(that.light).css({'top': result.y, 'left': result.x});

This should be all you need. Hope this helps.

Solution 2

Since i'm pretty sure that the algorithms are not completely correct and the information you provided was very helpful to me, i want to be grateful and created a jsfiddle demo for everybody to see the algorithms in action. i additionally provided a default interface to play with.

http://jsfiddle.net/s7Uy2

Thanks again.

The code:

CSS:

.ui-controlpad {
width:150px;
height:150px;
border:1px solid black;
-moz-border-radius:75px;
border-radius:75px;
z-index:1000;
}
.ui-controlpad-pad {
position:relative;
width:75px;
height:75px;
top:37.5px;
left:37.5px;
border:1px solid black;
-moz-border-radius:37.5px;
border-radius:37.5px;
z-index:1001;
background-color:grey;
}

Html:

<div id="Controlpad"></div>

Javascript:

jQuery.fn.extend({
    controlpad: function (options) {
        $(this[0]).append('<div class="ui-controlpad"></div>');
        $(".ui-controlpad").append('<div class="ui-controlpad-pad"></div>');
        $(".ui-controlpad-pad").draggable({
           drag: options.ondrag,
           revert: true
        });
    }
});
function limit(x, y, cenx, ceny, r) {
    var dist = distance([x, y], [cenx, ceny]);
    if (dist <= r) {
        return { x: x, y: y };
    }
    else {
        x = x - cenx;
        y = y - ceny;
        var radians = Math.atan2(y, x);
        return {
            x: Math.cos(radians) * r + cenx,
            y: Math.sin(radians) * r + ceny
        }
    }
}

function distance(dot1, dot2) {
    var x1 = dot1[0],
        y1 = dot1[1],
        x2 = dot2[0],
        y2 = dot2[1];
    return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
$(document).ready(function(){
    var circle_cenx = 37.5;
    var circle_ceny = 37.5;
    var circle_radius = 37.5;
    $("#Controlpad").controlpad({
        ondrag: function(event, ui){
            var result = limit(ui.position.left, ui.position.top, circle_cenx, circle_ceny, circle_radius);
            ui.position = { 'top': result.y, 'left': result.x };
        }
    });
});
Share:
11,298
andyopayne
Author by

andyopayne

Updated on June 15, 2022

Comments

  • andyopayne
    andyopayne almost 2 years

    I've been working on a script that would limit the containment of a draggable div to a circle (instead of a rectangular parent div). I found this thread: How to constrain movement within the area of a circle which seemed to solve some of my questions. I've got the proper functions in place and when I call those functions inside the drag function it will return the proper x & y position of the div. I know this because I can check the console log during the drag function and check the position of the div. However, my problem is that I can't seem to set the actual position during the drag event. The console reports the proper position values, but the div never actually gets constrained to the circular boundary. For example, if I drag the div to the center of the circle and then move it up vertically past the circle boundary... the div doesn't stop at the circle, however the console clamps the position to [0,50]//50 is the the center of the circle in both the X & Y axis. I read on some other threads that I might have to use a helper object, but I didn't seem to get anywhere with this method. I'm posting a simplified example in hopes that someone can help. Thank you.

    this.light = document.createElement("div");
    this.light.style.position='absolute';
    this.light.style.left="20px";
    this.light.style.top="40px";
    this.light.style.width="20px";
    this.light.style.height="20px";
    
    $(parentdiv).append(this.light);
    
    var circle_cenx = 50.0;
    var circle_ceny = 50.0;
    var circle_radius = 50.0;
    
    $(this.light).draggable({ 
        drag: function( event, ui ){
            var position = $(that.light).position();
            var result = limit(position.left+10, position.top+10, circle_cenx, circle_ceny);
            $(that.light).css({'top': result.y, 'left': result.x});
            position = $(that.light).position();
            console.log(position);
        }
    });
    
    function limit(x, y, cenx, ceny) {
        var dist = distance([x, y], [cenx, ceny]);
        if (dist <= circle_radius) {
            return {x: x, y: y};
        } 
        else {
            x = x - circle_cenx;
            y = y - circle_ceny;
            var radians = Math.atan2(y, x);
            return {
               x: Math.cos(radians) * circle_cenx + circle_radius,
               y: Math.sin(radians) * circle_ceny + circle_radius
            }
        } 
    }
    
    function distance(dot1, dot2) {
        var x1 = dot1[0],
            y1 = dot1[1],
            x2 = dot2[0],
            y2 = dot2[1];
        return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
    }