当将元素拖动到另一个容器并捕捉到另一个容器时,如何强制 jquery 将其居中?

Posted

技术标签:

【中文标题】当将元素拖动到另一个容器并捕捉到另一个容器时,如何强制 jquery 将其居中?【英文标题】:How do I force jquery to center an element when it is dragged to and snapped to another container? 【发布时间】:2012-07-08 11:24:31 【问题描述】:

我想要一些方形的可拖动对象(在这种情况下只是 <td> 带有数字的框)能够捕捉到一些空的表格单元格并捕捉到这些单元格的中心(空的 td 框),而不是那些单元格的(外)边缘,这似乎是默认情况下所做的。

这是我的脚本:

<script type="text/javascript">
 $(document).ready(function () 
     $(".inputs div").draggable( 
       snap: ".spaces"
     );    
 );    
</script>

编辑:这是整个文件

 <!DOCTYPE html>
  <head>
   <title>Draggable</title>
   <script type="text/javascript" src="jquery-1.7.2.min.js"></script>
   <script type="text/javascript" src="jquery-ui-1.8.21.custom.min.js"></script>
   <script type="text/javascript" src="jquery.ui.touch-punch.min.js"></script>
   <style>
    .block 
        z-index:9999;
        cursor:move;
    
    li 
        list-style:none;
    
    tr 
        border: 2px solid black;
    
    table 
        border: 2px solid black;
    
    .inputs div 
        float:left;
        background-color:#FFFFFF;
        color:#004E66;
        font-size:x-large;
        margin:2px;
        padding:20px;
        border:1px solid black;
    
    .spaces td 
        background-color:#666666;
        margin:2px;
        padding:36px;
        border:2px solid black;
    
 </style>
</head>

<body>
<form id="form1">
  <div class="inputs">
    <div>1</div>
    <div>2</div>
    <div>3</div>    
    <div>4</div>
    <div>5</div>
    <div>6</div>
  </div>
  <br/>
  <table class="spaces">
    <tr>
        <td></td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td></td>
    </tr>
  </table>
</form>
<!-- here we are telling jquery to make each element inside of class 'inputs' draggable -->
<script type="text/javascript">
   $(document).ready(function () 
      $(".inputs div").draggable( 
         snap: ".spaces"
      ).center();  
  );   
</script>

这是一个粗略的基于文本的说明

-----+----------+ XXXXXXXXXXXX X| | | |是 x| | X| -----+-------+X| | X| 如果上面的框是最上面tr行右上角的td单元格 那么 X 是元素当前所在的位置(显然不是 大,我只是显示它粘的地方......实际上我删除了 一些 X 显示它在到达某个位置后如何捕捉到角落 与它有一定的接近性...) 基本上这个模型展示了只有桌子的外部边缘 关于可拖动元素具有“重力”。我真正想要的 要做的是用 repelling 将所有边缘卡入 td 单元格,而不是 对外部的吸引力。 Y 是拖动元素所需的对齐位置。 最后,出于演示的原因,我希望元素卡入到位 有某种过渡而不是突然的跳跃......

【问题讨论】:

您希望可拖动元素在 tds 中垂直和水平居中吗?因为它们不太适合。 4000 次观看。 9 票赞成正确答案。 4关于问题。唧唧喳喳。签到你们这些懒汉!!! 【参考方案1】:

我相信这就是你想要的。

如果你愿意,你显然可以改变定位,它更适合你的需要。

演示在这里:DEMO

$(document).ready(function () 


$(".inputs div").draggable( 
        opacity: .4,
        create: function()$(this).data('position',$(this).position()),
        cursorAt:left:15,
        cursor:'move',
        start:function()$(this).stop(true,true)
   );

     $('.spaces').find('td').droppable(
         drop:function(event, ui)
             snapToMiddle(ui.draggable,$(this));
         
     );

 ); 


function snapToMiddle(dragger, target)
    var topMove = target.position().top - dragger.data('position').top + (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
    var leftMove= target.position().left - dragger.data('position').left + (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
    dragger.animate(top:topMove,left:leftMove,duration:600,easing:'easeOutBack');

【讨论】:

好的,所以这不在我的电脑上运行。我以前从未使用过 fiddle,我的代码在此页面 (gist.github.com/3095046) 上,如下所示。我错过了什么吗? 唯一看起来不同的是您的 jQuery UI 版本。 jsfiddle 使用jQuery UI 1.8.18 在你的 jquery ui 中,我注意到它有“自定义”,这意味着你可能选择了一些不同的东西,然后下载了你需要的东西。我猜想,也许你的自定义一个没有包含 droppable 或类似的东西? 另外,在您的示例中,将最后一个 部分放在 html 的头部...如果您没有它,它将无法工作。 【参考方案2】:

关于 snapToMiddle 函数的一点说明:

为了让它对我正常工作,我不得不将其更改为 >

function snapToMiddle(dragger, target)
    var offset = target.offset();
    var topMove = (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
    var leftMove= (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
    dragger.offset( top: topMove + offset.top, left: leftMove + offset.left )

另外,我创建了一个将拖动器与滴管相关联的数组,并且在调整窗口大小时,我确保我的所有滴管都不会偏离:

$( window ).resize(function() 
    for( i = 0 ; i < assc.length - 1 ; i++ )
    
        var drp = assc[i].drop;
        var drg = assc[i].drag;
        snapToMiddle(drg,drp);
    
);

【讨论】:

乔恩·特灵顿你是我的男人!!关于如何使它像jeschafe的答案一样动画的任何想法? dragger.animate(top:topMove,left:leftMove,duration:600,easing:'easeOutBack');【参考方案3】:

http://jsfiddle.net/vtdhV/

我创建了一个可以解决您的问题的小提琴 .. 有点(如果我理解正确的话)。

红色的 div 位于 tds 的中心,而您可以捕捉到它们。只需删除边框,它似乎会捕捉到 td 的中心。 .draggable 的性质将导致可拖动对象捕捉到任何边缘,而不是同时捕捉到所有边缘。

如果这还不够,您可能必须为.stop 实现一个调用处理程序,该处理程序根据您的期望调整元素的位置。

【讨论】:

也许我做得不对,但是当小提琴网站显示工作代码时,当我在计算机的网络服务器上尝试该代码时,元素不可拖动。 @David 你有任何错误吗?我从你那里复制了大部分内容。【参考方案4】:

您需要指定与拖动元素大小相同的捕捉目标。如果您的可拖动对象始终大小相同,这没什么大不了的。只需在您的单元格中添加一个空的、绝对定位的 div,并设置您的 CSS,使其大小和居中正确。然后,将您的 snap 选择器设置为该 div。要仅捕捉到捕捉目标的内部,请将 snapMode 设置为 "inner"

$(".inputs div").draggable(
    snap: ".spaces td div",
    snapMode: "inner"
);

但如果您的可拖动元素的大小可能不同,则每次开始拖动元素时都需要调整放置目标的大小并使其居中。在可拖动的鼠标按下时执行此操作(使用mousedown,因为dragstart 为时已晚且不起作用):

$(".inputs div").draggable(
    snap: ".spaces td div",
    snapMode: "inner",
).mousedown(function()
    var targets = $(".spaces td div");
    targets.height(this.offsetHeight);
    targets.width(this.offsetWidth);
    targets.each(function()
        $(this).position( of: this.parentNode );
    );
);

http://jsfiddle.net/gilly3/mPr3A/

【讨论】:

【参考方案5】:

在这些 tds 中添加一个 div 并通过为 tds 和新添加的 divs 提供固定的宽度和高度将其居中。然后将可拖动对象扩展到这些 div。

$(document).ready(function () 
    $('<div></div>').appendTo('.spaces td');
    $(".inputs div").draggable(
        snap: ".spaces td div",
        snapMode:'inner'
    );  
); 

tds 和 divs 的 css 也将如下所示。

.block 
    z-index:9999;
    cursor:move;


.productCode 



li 
    list-style:none;

tr 
    border: 2px solid black;

table 
    border: 2px solid black;


.inputs div 
    float:left;
    background-color:#FFFFFF;
    color:#004E66;
    font-size:x-large;
    margin:2px;
    padding:20px;
    border:1px solid black;


.spaces td 
    background-color:#666666;
    width:80px;
    height:80px;            
    border:2px solid black;


.spaces td div 
    margin:0 auto;
    width:50px;
    height:70px;

小提琴演示 - http://jsfiddle.net/nsjithin/u25Bs/1/

【讨论】:

【参考方案6】:

如果我的问题正确,请将您当前的脚本替换为:

$(document).ready(function () 

    // create a bunch of invisible divs
    var divs = $('<div></div><div></div><div></div><div></div>');

    // make them 2/2 and add them to the existing tds
    divs.css( width:'50%', float:'left' ).appendTo('.spaces td');

    // snap to everything
    $(".inputs div").draggable(snap: ".spaces td, .spaces td div" ).center(); 

); 

如果我不只是说,我会修复它。

【讨论】:

更好!它现在对桌子的内壁具有“吸引力”。但它不会粘在给定单元格的中心。 @David Cell 您的意思是 TD 还是编号框?还有你用的是什么浏览器? 在 jquery 或 jquery ui.. 中有方法.center() 吗?

以上是关于当将元素拖动到另一个容器并捕捉到另一个容器时,如何强制 jquery 将其居中?的主要内容,如果未能解决你的问题,请参考以下文章

可拖动元素的遏制

我在可拖动节点内更改了一些文本,然后我将此节点拖动到另一个容器中,旧值又回来了

C++中如何把list容器的元素复制到另一个list容器中

带细节的有界可拖动元素

可拖动 | jQuery 用户界面。如何在拖动事件上添加类

Java。如何将一个LinkedList里的元素全部复制到另一LinkedList容器里?