jQuery的可拖动网格

6

看起来,在Draggable的构造函数中,'grid'选项相对于被拖动元素的原始坐标是有限制的。简单地说,如果您有三个可拖动的

,它们分别相对于其父元素设置了top为100、200、254像素:

<div class="parent-div" style="position: relative;">
    <div id="div1" class="draggable" style="top: 100px; position: absolute;"></div>
    <div id="div2" class="draggable" style="top: 200px; position: absolute;"></div>
    <div id="div3" class="draggable" style="top: 254px; position: absolute;"></div>
</div>

所有这些元素都启用了拖拽功能,并将“grid”设置为[1, 100]:

draggables = $('.draggable');
$.each(draggables, function(index, elem) {
    $(elem).draggable({
                       containment: $('#parent-div'),
                       opacity: 0.7,
                       revert: 'invalid',
                       revertDuration: 300,
                       grid: [1, 100],
                       refreshPositions: true
    });
});

问题在于,一旦你拖动了,例如向下,它的顶部就会增加100,移动到354px而不是增加仅仅46px(254 + 46 = 300),这将使它到达网格中的下一个停止点——300px,如果我们将父级div视为参考点和“网格容器”。
我查看了可拖动源代码,似乎存在内置缺陷——它们只是相对于可拖动元素的原始位置进行所有计算。
我希望避免猴子补丁可拖动库的代码,我真正寻找的是让可拖动元素相对于包含父级计算网格位置的方法。然而,如果无法避免猴子补丁,我想我只能接受它。
4个回答

12

由于 @Pez 的答案已经无法访问(404),这里是我的做法:

$('#elem').draggable({
    ....,
    drag: function(e, ui) {
        ui.position.left = Math.floor(ui.position.left / 10) * 10;
        ui.position.top = Math.floor(ui.position.top / 10) * 10;
    }
});

演示: http://jsfiddle.net/ThiefMaster/yGsSE/


我正在尝试实现你上面展示的代码,但我很难确定需要哪些资源。如果我也有1.8.9 UI,1.5.2似乎就足够了,但是需要哪些UI文件呢?我喜欢你的解决方案,因为它非常简洁和优雅,这正是我一直在寻找的。 - C_K
通常情况下,没有使用旧版jQuery的好理由。因此,请选择1.6.1版本和最新的UI版本。除此之外,请使用UI包构建器并包含“Draggable” - 它应该会选择所有必要的内容。 - ThiefMaster
当网格大小大于10像素时,人们可能希望元素可以向两个方向捕捉,而不仅仅是向左(这是使用“floor”发生的):ui.position.left = Math.round((ui.position.left - offset) / 100) * 100 + offset(其中offset是网格左边框的位置)。 - Milanka

2
我通过在可拖拽元素的 drag 属性下添加自己的脚本并将其设置为“drag: true”来解决了这个问题。
divide math.Floor(x/100)*100 

对于 Y,同样如此。


0

Jquery 桌面:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"></script>
<link rel="stylesheet/less" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/themes/base/jquery-ui.css">

<div class="parent-div" style="position: relative;">
    <div id="div1" class="draggable" style="top: 100px; position: absolute;">1</div>
    <div id="div2" class="draggable" style="top: 200px; position: absolute;">2</div>
    <div id="div3" class="draggable" style="top: 254px; position: absolute;">3</div>
</div>

<script>
var Z_INDEX_APP = 0;
var Z_INDEX_WINDOW_COUNTER = 1;
var Z_INDEX_NOTE_COUNTER = 999;
var Z_INDEX_FOR_DRAGGED = 99999;
var Z_INDEX_FOR_NOTIF = 999999; 
var ICONS_GRID_CELL_SIZE = 75;
var ICONS_GRID_PADDING_LEFT = 20;
var ICONS_GRID_PADDING_TOP = 50; 
draggables = $('.draggable');
$.each(draggables, function(index, elem) {
    $(elem).draggable({
        containment: $('#parent-div'),
        start: function(event) {
        icon = $(this);
        icon.css('z-Index', Z_INDEX_FOR_DRAGGED);
        dragStartLeft = icon.css('left');
        dragStartTop = icon.css('top');
        icon.addClass('desktop-app-dragging');
        icon.removeClass('desktop-app-pressed');
    },
    stop: function(event) {         
        icon.css('z-Index', Z_INDEX_APP);
        var appId = icon.attr('id').split('_')[1];
        icon.removeClass('desktop-app-dragging');
        var alignedX = ICONS_GRID_PADDING_LEFT + Math.floor(parseInt(icon.css('left'))/ICONS_GRID_CELL_SIZE) * ICONS_GRID_CELL_SIZE;
        var alignedY = ICONS_GRID_PADDING_TOP + Math.floor(parseInt(icon.css('top'))/ICONS_GRID_CELL_SIZE)  * ICONS_GRID_CELL_SIZE;
        if ( alignedX < ICONS_GRID_PADDING_LEFT ) alignedX = ICONS_GRID_PADDING_LEFT;
        if ( alignedY < ICONS_GRID_PADDING_TOP ) alignedY = ICONS_GRID_PADDING_TOP;         
        var iconToSwitch = null;
        $(".desktop-app").each(function(index, app) {           
            if ( app.style.top == ( alignedY + 'px' ) && app.style.left == ( alignedX + 'px' ) ) {
                iconToSwitch = app;
            }
        });
        if ( iconToSwitch != null ) {
            var appToSwitchId = iconToSwitch.id.split('_')[1];
            var updateUrl = 'api/desktop?cmd=update&id=' + appToSwitchId + '&x=' + parseInt(dragStartLeft) + '&y=' + parseInt(dragStartTop);
            //$.getJSON(updateUrl);
            iconToSwitch.style.left = dragStartLeft;
            iconToSwitch.style.top = dragStartTop;
        }       
        icon.css('left', alignedX + 'px');
        icon.css('top', alignedY + 'px');
        var updateUrl = 'api/desktop?cmd=update&id=' + appId + '&x=' + alignedX + '&y=' + alignedY;
        //$.getJSON(updateUrl);
    }

    });
});
</script>

0

我最近几天开始使用JQuery可拖动功能,并找到了一个简单的解决方法。

将位置属性设置为绝对,并使用top和left将小部件添加到与网格对齐的值。

由于top/left的值是绝对的,因此在离开并将它们存储在数据库中时,它们也更有意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接