How to fix wrongly positioned draggable helpers for connected sortables (partially caused by floated/relative positioned parent elements)?

前端 未结 3 1676
春和景丽
春和景丽 2021-02-05 08:34

Preface

I\'m experiencing a problem where the draggable helper is being offset incorrectly, when using draggables + sortables that are placed in floating, relative pos

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-02-05 08:57

    A simple JavaScript only workaround is to store the offset to the mouse when the dragging starts and then force the ui.helper to have the same offset to the mouse - always:

    [...]
    var offset_start = {};
    
    $('.draggable').draggable({
      connectToSortable: '.sortable',
      helper: 'clone',
      revert: true,
      start: function(e, ui) {
          offset_start = {
              x: ui.position.left - e.pageX,
              y: ui.position.top - e.pageY
          }
      },
      drag: function(e, ui) {
          ui.position.top = e.pageY + offset_start.y
          ui.position.left = e.pageX + offset_start.x
      }
    }).disableSelection();
    

    See the updated jsfiddle.

    For the simple case this is an easy workaround, but requires more work if you introduce borders (where the helper cannot leave) etc.


    Edit: For your snippet I came up with another solution (because the other one does not work as expected - harder to get the initial offsets than I thought ...): Simply force the item to stay at the mouse pointer regardless of the initial offset after appending the helper to the body. It is not 100% nice, because when starting to drag it might "jump" to the mouse - but then it stays there at least ...

    $('.draggable').draggable({
      connectToSortable: '.sortable',
      helper: 'clone',
      revert: 'invalid',
      appendTo: 'body',
      drag: function(e, ui) {
        if (!ui.helper.parent().is('body')) {
          ui.helper.appendTo($('body'));
        }
        ui.position.top = e.pageY - 10;
        ui.position.left = e.pageX - 25;
      }
    }).disableSelection();
    

    $('.sortable').sortable({
      connectWith: '.sortable',
      revert: 600,
      forcePlaceholderSize: true,
      placeholder: 'ui-sortable-placeholder',
      tolerance: 'pointer'
    }).disableSelection();
    
    
    $('.draggable').draggable({
      connectToSortable: '.sortable',
      helper: 'clone',
      revert: 'invalid',
      appendTo: 'body',
      scroll: false,
      drag: function(e, ui) {
        if (!ui.helper.parent().is('body')) {
          ui.helper.appendTo($('body'));
        }
        ui.position.top = e.pageY - 15;
        ui.position.left = e.pageX - 25;
      }
    }).disableSelection()
    .sortable-container {
      display: inline-block;
      width: 100px;
      vertical-align: top;
    }
    .sortable {
      cursor: move;
      margin: 0;
      padding: 0;
      list-style-type: none;
      vertical-align: top;
      border: 1px solid #000;
    }
    .ui-sortable-placeholder {
      background: #ff0000;
    }
    #draggables {
      margin: 0;
      padding: 0;
      list-style-type: none;
    }
    .draggable {
      margin: 4px;
      cursor: move;
      color: #fff;
      background: #5dd1ff;
    }
    
    
    
    
    

    foo

    bar

    foo

    bar

    foo

    bar

    • sortable 1
    • sortable 2
    • sortable 3
    • sortable 4
    • sortable 5
    • sortable 6
    • sortable 1
    • sortable 2
    • sortable 3
    • sortable 4
    • sortable 5
    • sortable 6
    • sortable 1
    • sortable 2
    • sortable 3
    • sortable 4
    • sortable 5
    • sortable 6
    • draggable 1
    • draggable 2
    • draggable 3

提交回复
热议问题