Jquery Draggable Circle Containment

时间:2013-01-30 19:57:50

标签: jquery containment

我已经为此寻找答案而找不到......所以希望有人可以帮助我。我正在尝试创建一个可拖动的div(使用jquery ui),它包含在一个圆圈中(而不是一个正方形)。现在,我已经将遏制设置链接到它的父div,但无论我尝试什么......它仍然允许可拖动元素进入父方形div的角落。我已经尝试设置父div的border-radius,这样它就是圆形而不是正方形(但这可能只是一个css的东西,并没有影响实际的div形状)。有谁知道如何将可拖动的div限制为圆圈? 谢谢, 安迪

var containment_radius = 50;

$(this.dragobject).draggable({ 
    drag: function() {
        var position = $(this.dragobject).position();
        var result = limit(position.left, position.top, containment_radius, containment_radius);
        if (!result.limit) {
            $(this.dragobject).x = result.x + "px";
            $(this.dragobject).y = result.y + "px";
        }
        console.log(result);
    } 
});

function limit(x, y, x1, y1) {
    var dist = distance([x, y], [x1, y1]);
    if (dist <= containment_radius) {
        return {x: x, y: y};
    } else {
        return {limit: true};
    }
}

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));
}

3 个答案:

答案 0 :(得分:0)

请参阅this answer,其中显示了如何使用drag事件进行约束。这是通过更新ui.position事件处理程序中的drag变量来完成的。

答案 1 :(得分:0)

Duopixel回复了这个确切的问题,其中一个示例包含在一个圆圈中,而不是正如andyopayne所建议的波浪。

How to constrain movement within the area of a circle

这是一个例子 http://jsfiddle.net/7Asn6/

诀窍是计算与初始和当前阻力位置坐标的距离,

Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));

然后用

计算新的x和y坐标

x: Math.cos(radians) * canvas.radius + canvas.center[0], y: Math.sin(radians) * canvas.radius + canvas.center[1]

在拖回回调中:

答案 2 :(得分:0)

此解决方案遵循Luke H关于更新ui.position的建议。它实现起来很简单(不需要扩展可拖动库存的小部件),但我不喜欢它,因为必须从可拖动的外部访问半径而不是从包含本身中取出。

var radius = 128;
$('.color-picker-map-selector').draggable({
    containment: '.map',
    drag: function( event, ui ) {
        var x = ui.position.left - radius,
            y = radius - ui.position.top,
            h = Math.sqrt(x*x + y*y);
        if (Math.floor(h) > radius) {
            ui.position.top = radius - Math.round(radius * y / h);
            ui.position.left = Math.round(radius * x / h) + radius;
        }
    }
});

不需要像许多例子那样使用正弦和余弦等精细的数学函数。

我首选的解决方案是通过添加形状选项(&#39;矩形,圆形&#39;)来扩展小部件,并覆盖内部_generatePosition函数。它使用容器的宽度和高度来查找中心,如果容器不是正方形,它会将可拖动的约束为椭圆。

// add shape option to stock draggable
$.widget( "ui.draggable", $.ui.draggable, {
    options: {
        shape: 'rectangular'
    },
    _generatePosition( event, constrainPosition ) {
        var position = this._super( event, constrainPosition );
        if (this.options.shape != 'circular') return position;
        if ( constrainPosition ) {
            if ( this.containment ) {
                if ( this.relativeContainer ) {
                    co = this.relativeContainer.offset();
                    containment = [
                        this.containment[ 0 ] + co.left,
                        this.containment[ 1 ] + co.top,
                        this.containment[ 2 ] + co.left,
                        this.containment[ 3 ] + co.top
                    ];
                } else {
                    containment = this.containment;
                }
                var xRadius = Math.floor((containment[ 2 ] - containment[ 0 ]) / 2),
                    yRadius = Math.floor((containment[ 3 ] - containment[ 1 ]) / 2),
                    x = position.left - xRadius,
                    y = yRadius - position.top,
                    h = Math.sqrt(x*x + y*y);
                if (Math.floor(h) > Math.min(xRadius, yRadius)) {
                    var ye = Math.round(yRadius * y / h),
                    xe = Math.round(xRadius * x / h);
                    if ((Math.abs(y) > Math.abs(ye)) || (Math.abs(x) > Math.abs(xe))) {
                        position.left = xe + xRadius;
                        position.top = yRadius - ye;
                    }
                }
            }
        }
        return position;
    }
});

如果jQuery UI人员更改了_generatePosition的名称和用法,那么会有一些小问题,但是如果他们要更改函数的内部因此它会调用一些辅助函数,比如_constrain()会简化它会很好这段代码非常重要。

另请注意,此解决方案不适用于网格对齐,但可以通过一些额外的代码来完成。

干杯!