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

时间:2012-07-09 03:09:36

标签: javascript jquery css jquery-ui jquery-ui-draggable

我想要一些方形的可拖动对象(在这种情况下只有<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>

这是一个粗略的基于文本的插图,说明正在发生的事情

-----+---------+
XXXXXXXXXXX   X|
     |         |
     |    Y   x|
     |        X|
-----+-------+X|
     |        X|
  • 如果上面的框是最顶行tr行右角的td单元格
  • 然后X是元素当前粘的地方(显然不是那个 很大,我只是展示它坚持的地方......实际上我已经删除了 一些X展示了它到达角落后如何捕捉到角落 某种接近......)
  • 基本上这个模型演示了只有表的外边缘 对可拖动元素有“重力”。我真正想要的是什么 要做的是使用排斥对所有边缘进入td单元,而不是 对外部的吸引力。
  • Y是拖动元素的所需捕捉位置。
  • 最后由于演示原因,我希望元素快照到位 有某种过渡而不是突然跳跃......

6 个答案:

答案 0 :(得分:11)

我相信这就是你想要的。

如果您愿意,您可以明显改变定位,并且它可以更好地满足您的需求。

演示在这里: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'});
}

答案 1 :(得分:5)

关于snapToMiddle函数的一点说明:

为了让它适合我,我必须将其更改为&gt;

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

答案 2 :(得分:1)

http://jsfiddle.net/vtdhV/

我创造了一个解决你的问题的小提琴......有点(如果我理解的话)。

红色div位于td s的中心位置,您可以使用它们。只需删除边框,它就会显示为捕捉到td的中心。 .draggable的性质将导致可拖动对齐任何边缘而不是所有边缘。

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

答案 3 :(得分:1)

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

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

但是如果可拖动的大小可能会有所不同,那么每次开始拖动元素时,您都需要调整大小并重新定位放置目标。在可拖动的mousedown上执行此操作(使用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/

答案 4 :(得分:0)

在这些tds中添加一个div,并通过为tds和新添加的div提供固定的宽度和高度来居中。然后跨越可拖动到这些div。

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

tds和div的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/

答案 5 :(得分:-1)

如果我遇到问题,请用以下内容替换当前脚本:

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

}); 

如果我不只是说,我会解决它。