【问题标题】:Jquery Draggable - center cursorAt VerticallyJquery Draggable - 垂直居中光标
【发布时间】:2011-08-10 15:42:28
【问题描述】:

我正在开发我的第一个 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() 会在 firebug 中出现错误“elem.style is undefined”

我知道outerHeight元素存在于jquery中,并且基于API doc它似乎可以自动计算,即使CSS未定义,所以我认为这是正确的方法,也许 $(this) 只是寻找它的错误位置。

【问题讨论】:

  • tolerance:"pointer" 在 droppable 函数下为我提供了一个不错的解决方法。

标签: javascript jquery html draggable


【解决方案1】:

我还想在拾起可拖动对象后将它们居中。我的解决方案:

$(".dragme").draggable({ 
    start: function(event, ui) { 
        $(this).draggable("option", "cursorAt", {
            left: Math.floor(this.clientWidth / 2),
            top: Math.floor(this.clientHeight / 2)
        }); 
    }
});

【讨论】:

  • 由于某种原因,这对我来说在放入启动处理程序时工作不一致(可能这会导致较新版本的 jQuery UI 中的竞争条件?)但在创建处理程序中效果很好。
  • 是的。这是不可靠的 - cursorAt 必须正常设置(在 start() 之前)。
【解决方案2】:

解决了最初的问题,请参阅我最初帖子的评论。

编辑:

Tolerance option“pointer”:鼠标指针与其他项目重叠。

$(".sortable").sortable({
    containment: "parent",
    tolerance: "pointer"
});

【讨论】:

    【解决方案3】:

    如果可拖动对象具有辅助对象,则此方法可以正常工作。只需将它放在可拖动的启动方法中,如下代码。

    start: function(event, ui) { 
      $(this).draggable("option", "cursorAt", {
        left: Math.floor(ui.helper.width() / 2),
        top: Math.floor(ui.helper.height() / 2)
      }); 
    }
    

    【讨论】:

    • 我认为这是迄今为止最具可读性和优雅的答案。
    【解决方案4】:

    我只是花了几个小时把头撞在墙上试图可靠地完成这项工作,所以我想我会发布解决方案:)

    问题: Draggable 无法在实例化动态值(即可变大小的可拖动代理的中心)期间为“克隆”拖动设置 cursorAt,因为尚未创建 ui.helper!您可以在启动处理程序中设置它,但它不适用于第一次拖动。

    解决方案: 在 start 内设置 cursorAt,但也手动覆盖连续发生的拖动事件的 ui.position。使用 firstRun 布尔值,您可以防止它不必要地运行。您必须将默认 cursorAt 设置为左​​上角才能重新定位。

    享受吧!

    $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;
                };
            }
        });
    

    【讨论】:

    • 如果您花一些时间阅读它并将其应用于您的代码,这个答案真的非常好。
    • 删除firstRun如果您的可拖动元素是可变宽度,则在拖动开始处签入。
    • 如果 droppable 比 draggable 小,这个 firstRun 的东西不会像预期的那样工作!因为当可放置中心悬停可拖动但您希望它与光标悬停时,可拖动获得悬停焦点。我找到的完美解决方案in this thread
    【解决方案5】:

    如果是多个可拖动对象,Goz 的回答对我不起作用,所以这是我不使用 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>

    【讨论】:

      【解决方案6】:

      @yuri 戈尔:

      你的回答对我有用,但你可以从一开始就开始偏移:

          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 );   
           }
          });
      

      【讨论】:

      • 是的,你是对的,我不记得我在想什么做这么复杂的初始化,也许是因为我的应用程序中的一些其他代码,这超出了本文的范围- p.
      猜你喜欢
      • 2018-05-31
      • 2011-04-20
      • 2011-02-03
      • 2012-04-26
      • 2011-03-09
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多