Получение jQuery перетаскивания для привязки к определенной сетке

( ПРИМЕЧАНИЕ: Некоторые задавали похожие вопросы, но были слишком конкретными и не давали никаких полезных ответов)

jQuery UI draggable widget имеет опции для привязки к сетке, но не имеет способа установить, что сетка относительно.

Например, у нас есть четко определенная сетка 20x20 в нашей целевой точке. Элемент перетаскивания, начинающийся с 0,0 в пределах целевой цели, будет привязан в соответствии с сеткой. Но элемент перетаскивания, который начинается в другом месте или за пределами целевой цели, не будет соответствовать этой сетке.

enter image description here

http://jsfiddle.net/FNhFX/5/

HTML:

<div class="drop-target">
    <div class="drag-item">Drag me</div>
    <div class="drag-item" style="left:87px;top:87px;">Drag me</div>
</div>
<div class="outside-drag-item">Drag me</div>

JS:

$(function() {
    $(".drag-item").draggable({
        grid: [20, 20]
    });
    $(".outside-drag-item").draggable({
        grid: [20, 20],
        helper:"clone"
    });
    $(".drop-target").droppable({
        accept: ".drag-item"
    });
});

Есть ли способ привязки к определенной сетке с помощью jQuery draggable?

Ответ 1

Я собираюсь пойти и ответить на этот вопрос здесь, хотя я пришел сюда через следующий вопрос, который вы задали.

Вы можете легко создать свою собственную функцию привязки к сетке внутри события drag в jQuery UI draggable.

В принципе, вы хотите проверить, насколько близко текущая позиция ui находится в любой точке, в которую перетаскивается перетаскиваемая в сетку. Эта близость всегда может быть представлена ​​как остальная часть позиции, деленная на сетку. Если этот остаток меньше или равен snapTolerance, просто установите положение в том, что было бы без этого остатка.

Это было странно говорить в прозе. В коде должно быть более ясно:

Live Demo

// Custom grid
$('#box-3').draggable({
    drag: function( event, ui ) {
        var snapTolerance = $(this).draggable('option', 'snapTolerance');
        var topRemainder = ui.position.top % 20;
        var leftRemainder = ui.position.left % 20;

        if (topRemainder <= snapTolerance) {
            ui.position.top = ui.position.top - topRemainder;
        }

        if (leftRemainder <= snapTolerance) {
            ui.position.left = ui.position.left - leftRemainder;
        }
    }  
});

Ответ 2

В качестве альтернативы попытке использовать параметр сетка в пользовательском интерфейсе jQuery, я создал свою собственную сетку (которую вы можете сделать видимой или невидимой с помощью css), а затем используйте привязку и укажите класс каждой из моих линий сетки.

В ваш оригинальный jsfiddle я добавил следующий css:

.gridlines {
display: none;
position:absolute;
background-color:#ccc;
}

и следующий javascript:

function createGrid(size) {
  var i,
  sel = $('.drop-target'),
      height = sel.height(),
      width = sel.width(),
      ratioW = Math.floor(width / size),
      ratioH = Math.floor(height / size);

  for (i = 0; i <= ratioW; i++) { // vertical grid lines
    $('<div />').css({
        'top': 0,
        'left': i * size,
        'width': 1,
        'height': height
    })
      .addClass('gridlines')
      .appendTo(sel);
  }

  for (i = 0; i <= ratioH; i++) { // horizontal grid lines
    $('<div />').css({
        'top': i * size,
        'left': 0,
        'width': width,
        'height': 1
    })
      .addClass('gridlines')
      .appendTo(sel);
    }

  $('.gridlines').show();
}

createGrid(20);

Вот jsFiddle (http://jsfiddle.net/madstop/46sqd/2/)