Jquery Draggable - центральный курсор по вертикали - PullRequest
6 голосов
/ 22 апреля 2011

Я работаю над своим первым проектом JQuery, и я наткнулся на некоторый контрольно-пропускной пункт. Я пытаюсь разрешить перетаскивание из списка вложенных списков (ul). Все работает, кроме позиционирования. Цель состоит в том, чтобы вертикально перетаскивать перетаскиваемый объект относительно курсора (горизонтальное перемещение ограничено), чтобы можно было легко опустить li с вложенными в него элементами. Вот соответствующий JS:

$(function() {
$( ".organizerlink" ).draggable({ axis: "y",
    containment:"#organizer",
    scroll: false ,
    helper: "original",
    revert: "invalid",
    cursorAt: { top: Math.round($(this).outerHeight() / 2)}
});

и HTML:

<ul id="organizer">
<li class="organizerTarget">&nbsp</li>
<li class="organizerlink" id="dbid-1">Page
    <ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul>
</li>
<li class="organizerTarget">&nbsp</li>
<li class="organizerlink" id="dbid-2">About
    <ul>
        <li class='organizerTarget'>&nbsp;</li>
        <li class='organizerlink' id="dbid-3">Another Page<ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul></li>
        <li class='organizerTarget'>&nbsp;</li>
        <li class='organizerlink' id="dbid-4">Example<ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul></li>
    </ul>
</li>
<li class="organizerTarget">&nbsp</li>
<li class="organizerlink" id="dbid-27">Stuff
    <ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul>
</li>

Некоторые вещи, которые я уже пробовал:

  • установка cursorAt в $ (this) .height () - не сработало, я предполагаю, что height () вытягивает высоты css, но они не определены явно, поэтому он переходит к 0
  • установка его в outerHeight () выдает ошибку "elem.style is undefined" в firebug

Я знаю, что элемент externalHeight существует в jquery, и на основании API doc может показаться, что он может быть рассчитан автоматически, даже если CSS не определен, поэтому я считаю, что это правильно путь, и, возможно, $ (this) - это не то место, где его нужно искать.

Ответы [ 6 ]

8 голосов
/ 04 января 2012

Я также хотел центрировать мои перетаскиваемые объекты после того, как я их поднял. Мое решение:

$(".dragme").draggable({ 
    start: function(event, ui) { 
        $(this).draggable("option", "cursorAt", {
            left: Math.floor(this.clientWidth / 2),
            top: Math.floor(this.clientHeight / 2)
        }); 
    }
});
6 голосов
/ 22 апреля 2011

Обошли начальную проблему, см. Комментарий к моему первоначальному сообщению.

EDIT:

Параметр допуска «указатель»: указатель мыши перекрывает другой элемент.

$(".sortable").sortable({
    containment: "parent",
    tolerance: "pointer"
});
5 голосов
/ 22 января 2016

Я просто потратил пару часов, разбивая голову о стену, чтобы попытаться надежно сделать эту работу, поэтому я решил опубликовать решение :)

Проблема: Draggable не может установить cursorAt для перетаскивания «клон» во время создания экземпляра для динамических значений (то есть центра перетаскиваемого прокси переменного размера), потому что ui.helper еще не был создан! Вы можете установить его внутри обработчика запуска, но он не будет работать для первого перетаскивания.

Решение: Установите cursorAt внутри start, но ТАКЖЕ вручную переопределите ui.position для события перетаскивания, которое происходит непрерывно. Используя логическое значение firstRun, вы можете запретить его запуск без необходимости. Вы должны установить курсор по умолчанию в верхнем левом углу для изменения положения.

Наслаждайтесь!

$jobs.each( function( index, element ) {
    var $el = $(element),
        firstRun = true;

    /*
     * jQuery UI Draggable
     * See @link: http://api.jqueryui.com/draggable/
     *
     * Note that for clone drags, the first drag cannot center the proxy because ui.helper hasn't been created yet
     * so need to set it manually for first drag. Subsequent drags can use the cursorAt property.
     * See my @link: 
     */
    $el.draggable({
        cursorAt : [0, 0],          // Set origin then update dynamically
        drag : function( evt, ui ) { // Fires after start event, and continuously during drag
            if ( firstRun ) {
                // Reset proxy position here since cursorAt cannot be set for 
                ui.position.left -= Math.floor( ui.helper.width()/ 2 );
                ui.position.top -= Math.floor( ui.helper.height()/ 2 );
            };
        },
        helper : 'clone',
        start : function( evt, ui ) { // Fires once
            if ( firstRun ) {
                // Center proxy relative to cursor for future drags
                $(this).draggable( 'option', 'cursorAt', {
                    left : Math.floor( ui.helper.width()/ 2 ),
                    top : Math.floor( ui.helper.height()/ 2 )
                });
            };

            // Set cursor ( 'cursor' option just applies style to <body> )
            ui.helper.css( 'cursor', 'move' );
        },
        stop : function( evt, ui ) { // Fires once
            if ( firstRun ) {
                firstRun = false;
            };
        }
    });
5 голосов
/ 08 мая 2013

Это прекрасно работает, если у перетаскиваемого объекта есть вспомогательный объект.Просто поместите его в метод запуска draggable, как показано ниже.

start: function(event, ui) { 
  $(this).draggable("option", "cursorAt", {
    left: Math.floor(ui.helper.width() / 2),
    top: Math.floor(ui.helper.height() / 2)
  }); 
}
1 голос
/ 17 апреля 2019

@ yuri gor:

Ваш ответ сработал для меня, но вы могли только что начать смещение от начала:

    var offsetX = null;
    var offsetY = null;
    $(".item").draggable({
      helper:"clone",
      start:function(e,ui){
        offsetX = e.clientX-ui.offset.left;
        offsetY = e.clientY-ui.offset.top;
      },
      drag:function(e,ui){
        ui.position.left += offsetX - Math.floor( ui.helper.outerWidth()/ 2 );
        ui.position.top += offsetY - Math.floor( ui.helper.outerHeight()/ 2 );   
     }
    });
1 голос
/ 16 мая 2017

В случае многократно перетаскиваемых объектов ответ Гоза у меня не сработал, так что вот мое решение без использования cursorAt опция

var offsetX = null;
var offsetY = null;
$(".item").draggable({
  helper:"clone",
  start:function(e,ui){
    offsetX=null;
    offsetY=null;
  },
  drag:function(e,ui){
    if(offsetX===null){
      offsetX = e.clientX-ui.offset.left;
      offsetY = e.clientY-ui.offset.top;
    }
    ui.position.left += offsetX - Math.floor( ui.helper.outerWidth()/ 2 );
    ui.position.top += offsetY - Math.floor( ui.helper.outerHeight()/ 2 );
            
  }
});
.desk{
  width:300px;
  height:300px;
  border:2px dashed gray;
}

.item {
  padding:8px;
  margin:2px;
  border:1px solid blue;
  background: rgba(0,0,80,.3);
  display:inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="desk">
  <div class="item">Item 1</div>
  <div class="item" style="width:100px;">Item 2</div>
  <div class="item" style="height:50px;">Item 3</div>
</div>
...