Сортировка ведет себя неправильно при применении шкалы CSS3

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

jQuery Перетаскивание/изменение размера с помощью шкалы преобразования CSS

Но то, что я не могу решить, - это сортировка позиции позиции при перетаскивании. Он вскакивает и немного поправляет. Я не могу понять, что положить в обработчик события запуска:

        start: function(e, ui)
        {
            // something is needed here to fix the initial offset
        }

Эта сценария показывает проблему: http://jsfiddle.net/adrianrosca/zbvLp/4/

Ответ 1

Одно отличие от draggable заключается в том, что transform не относится к самим элементам, а к родительскому. Таким образом, это немного изменяет логику.

Вот решение для этого конкретного случая, но вы увидите, что в зависимости от ситуации он может измениться. Например, если вы измените transform-origin, или если у вас есть горизонтальная сортировка, ее нужно будет адаптировать. Но логика остается прежней:

var zoomScale = 0.5;

$(".container")
  .sortable({

    sort: function(e, ui) {
    console.log(ui.position.left)
      var changeLeft = ui.position.left - ui.originalPosition.left;
      // For left position, the problem here is not only the scaling,
      // but the transform origin. Since the position is dynamic
      // the left coordinate you get from ui.position is not the one
      // used by transform origin. You need to adjust so that
      // it stays "0", this way the transform will replace it properly
      var newLeft = ui.originalPosition.left + changeLeft / zoomScale - ui.item.parent().offset().left;

      // For top, it simpler. Since origin is top, 
      // no need to adjust the offset. Simply undo the correction
      // on the position that transform is doing so that
      // it stays with the mouse position
      var newTop = ui.position.top / zoomScale;

      ui.helper.css({
        left: newLeft,
        top: newTop
      });
    }
  });

http://jsfiddle.net/aL4ntzsh/5/

EDIT:

Предыдущий ответ будет работать для позиционирования, но, как указано Decent Dabbler, существует ошибка с функцией пересечения, которая проверяет, когда должна произойти сортировка. В принципе, позиции правильно вычисляются, но элементы сохраняют значения ширина и высота, которые не преобразуются, что вызывает проблему. Вы можете отрегулировать эти значения, изменив их в начале события, чтобы учитывать масштабный коэффициент. Например, например:

 start: function(e, ui) {
      var items = $(this).data()['ui-sortable'].items;
      items.forEach(function(item) {
        item.height *= zoomScale;
        item.width *= zoomScale;
      });
    }

http://jsfiddle.net/rgxnup4v/2/

Ответ 2

В вашей проблеме есть две вещи:

  • Свойство position элемента вычисляется на основе ближайшего родителя, который имеет положение абсолютное или относительное. В настоящее время родительский элемент - это тело, которое не очень хорошо, поэтому вам нужно добавить position:relative; для контейнера.
  • Поскольку, как вы уже заметили, JQuery не учитывает масштабы CSS при вычислении как ui.position, так и ui.originalPosition, поэтому вам нужно "применить" zoomScale к обоим.

CSS

.container
{
    position: relative;
    transform: scale(0.5);
    transform-origin: center top;
}

Script

var changeLeft = ui.position.left - ui.originalPosition.left;
var newLeft = (ui.originalPosition.left + changeLeft) / zoomScale;
var changeTop = ui.position.top - ui.originalPosition.top;
var newTop = (ui.originalPosition.top + changeTop) / zoomScale;

Это код обновления: http://jsfiddle.net/zbvLp/9/