Jquery Draggable - 垂直居中光标

Posted

技术标签:

【中文标题】Jquery Draggable - 垂直居中光标【英文标题】:Jquery Draggable - center cursorAt Vertically 【发布时间】: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 函数下为我提供了一个不错的解决方法。 【参考方案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.

以上是关于Jquery Draggable - 垂直居中光标的主要内容,如果未能解决你的问题,请参考以下文章

jQuery UI 拖动(Draggable) - Handles和Cancel

jquery-ui,如何将光标恢复为默认值

使用 jQuery 将 div 垂直和水平居中

UWP TextBox中的垂直中心文本和光标

使用jQuery垂直居中

在 jQuery Mobile 中垂直居中 DIV 的内容