javascript Jquery Draggable - 垂直居中光标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5750302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 18:12:18  来源:igfitidea点击:

Jquery Draggable - center cursorAt Vertically

javascriptjqueryhtmldraggable

提问by Sam

I'm working on my first JQuery project, and i've hit a bit of a roadblock. I'm trying to allow drag & drop reordering of a set of nested lists (ul). Everything is working with the exception of the positioning. The goal is to vertically center the draggable relative to the cursor (horizontal movement is restricted), so that an li with elements nested inside it can be easily dropped. Here's the relevant JS:

我正在开展我的第一个 JQuery 项目,但遇到了一些障碍。我正在尝试允许对一组嵌套列表 (ul) 进行拖放重新排序。除了定位之外,一切都在工作。目标是将可拖动对象相对于光标垂直居中(水平移动受到限制),以便可以轻松删除包含嵌套在其中的元素的 li。这是相关的JS:

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

and HTML:

和 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>

Some stuff I've already tried:

我已经尝试过的一些东西:

  • setting cursorAt to $(this).height() - didn't work, i'm guessing height() pulls the css heights in, but they aren't defined explicitly so it jumps to 0
  • setting it to outerHeight() gives me an error "elem.style is undefined" in firebug
  • 将 cursorAt 设置为 $(this).height() - 没有用,我猜 height() 将 css 高度拉进来,但它们没有明确定义,所以它跳到 0
  • 将它设置为 outerHeight() 会给我一个错误“elem.style is undefined”在萤火虫中

I know the outerHeight element exists in jquery, and based on the API docit would appear that it can be calculated automatically, even if the CSS is undefined, so I'm thinking that is the right way to be going, and perhaps $(this) is just the wrong spot to be looking for it.

我知道 jquery 中存在 externalHeight 元素,并且根据API 文档,它似乎可以自动计算,即使 CSS 未定义,所以我认为这是正确的方法,也许 $(这)只是寻找它的错误地点。

采纳答案by Sam

Worked around the initial problem, see the comment to my initial post.

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

EDIT:

编辑:

Tolerance option"pointer": The mouse pointer overlaps the other item.

容差选项“指针”:鼠标指针与其他项目重叠。

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

回答by Paul

I also wanted to center my draggable objects after I pick them up. My solution:

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

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

回答by Lalit Kumar Maurya

This works fine if draggable have helper object. Just put it in start method of draggable as below code.

如果可拖动对象具有辅助对象,则这可以正常工作。只需将其放入可拖动的 start 方法中,如下代码所示。

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

回答by Goz

I just spent a couple of hours smashing my head against the wall to try to reliably make this work, so I thought I'd post the solution :)

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

Issue:Draggable cannot set cursorAt for 'clone' drags during instantiation for dynamic values (i.e. the center of a draggable proxy of variable size) because ui.helper hasn't been created yet! You can set it inside the start handler but it will not work for the first drag.

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

Solution:Set the cursorAt inside start, but ALSO manually override the ui.position for the drag event, which occurs continuously. Using a firstRun boolean, you can prevent it from running needlessly. You must set the default cursorAt to the top left for repositioning.

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

Enjoy!

享受!

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

回答by Yuri Gor

In case of multiply draggable objects Goz's answer didn't work for me, so here is my solution without using cursorAt option

如果有多个可拖动对象,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>

回答by Johan Velthuis

@yuri gor:

@yuri戈尔:

Your answer worked for me, but you could have just inited the offset from start:

您的回答对我有用,但您可以从一开始就初始化偏移量:

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