4

我有一个带有可拖动/可放置元素的页面,一旦放置,就需要计算它们可能接触到的其他可拖动元素的左侧位置和宽度。

这本身并不太难,但我真正遇到麻烦的地方是让他们填补空白。如何让可拖动对象填充空白空间而不会相互叠加?

// $t is the element being added/dropped. 
// nd refers to New Dimensions, IE, the new dimensions for $t
// existingDivs gets any DIV's that have already been added to the dom
var $t = $(this), nd = {t:$t.position().top, h:$t.height(), l: 0, w: 95},
  existingDivs = $('#container .subContainer .draggable'), intersectArr = [],
  nonIntersectArr = [], finalArr = [];

// If there are no DIV's in the DOM you dont need to check if they intersect.
if (existingDivs.length > 0) {
// Find the DIV's that Intersect with the one being added
  intersectArr = $.grep(existingDivs, function(val,num){
    // xd is Existing Dimensions, for the current item being checked
    // verse the one being added.
    var $t2 = $(val), xd = {h:$t2.height(), w:parseFloat($t2.css('width')),
    l:parseFloat($t2.css('left')), t:$t2.position().top};
    // If they intersect add it to this array
    return ((xd.t <= nd.t && xd.t+xd.h > nd.t) ||
    (nd.t <= xd.t && nd.t+nd.h > xd.t));
  });
// Find the DIV's that DO NOT Intersect with the one being added
  nonIntersectArr = $.grep(existingDivs, function(val,num){
    // xd is Existing Dimensions, for the current item being checked
    // verse the one being added.
    var $t2 = $(val), xd = {h:$t2.height(), w:parseFloat($t2.css('width')),
    l:parseFloat($t2.css('left')), t:$t2.position().top};
    // If they DO NOT intersect add it to this array
    return ((xd.t > nd.t && xd.t > nd.t+nd.h) ||
    (nd.t > xd.t && nd.t > xd.t+xd.h));
  });
// For every element that does not intersect, check it verse the ones that do
  $(nonIntersectArr).each(function(){
    // nid is Non Intersecting Dimensions
    var $t2 = $(this), c = 0, nid = {h:$t2.height(),
    w:parseFloat($t2.css('width')),
    l:parseFloat($t2.css('left')), t:$t2.position().top};
    $(intersectArr).each(function(){
    // id is Intersecting Dimensions
      var $t3 = $(this), id = {h:$t3.height(), w:parseFloat($t3.css('width')),
      l:parseFloat($t3.css('left')), t:$t3.position().top};
    // if the non intersecting hits one that is intersecting, then there is no space
    // beneath/near it, so we add it to the final intersecting array then increment c
      if((id.t <= nid.t && id.t+id.h > nid.t) ||
      (nid.t <= id.t && nid.t+nid.h > id.t)){ finalArr.push(this); c++; }
      else { finalArr.push(this); }
    });
    // if c has been incremented, we cant use this nonIntersect, so add it to the final
    if(c > 0) { finalArr.push(this); }
  });
  // make sure all items in the final Array are unique
  finalArr = $.unique(finalArr);
  // iterate over the final array, processing the dimensions of each element in the
  // array layering them so you can see each one
  $(finalArr).each(function(num){
    // xd is Existing Dimensions, for the current item being checked
    // verse the one being added.
    var $t2 = $(this), xd = {h:$t2.height(), w:parseFloat($t2.css('width')),
    l:parseFloat($t2.css('left')), t:$t2.position().top};
    if(((xd.t <= nd.t && xd.t+xd.h > nd.t) ||
    (nd.t <= xd.t && nd.t+nd.h > xd.t))) {
      if(nd.l == xd.l){
        nd.w = ((95/(finalArr.length+1))*1.5);
        xd.l = ((nd.w)*(num));
        $(finalArr).each(function(ci){
          $(this).css({left:((nd.w*ci)*0.58)+'%',
          width:((95/(finalArr.length+1))*1.5)+'%'});
          nd.l = ((nd.w*ci)*0.58);
        });
      }
    }
  });
}
// Add the New Element to the container and position accordingly.
nd.l = ((nd.l/finalArr.length)*(finalArr.length+1))+'%';
nd.w = nd.w+'%';
$('#container .subContainer').append('<div style="top:'+nd.t+'px;left:'+nd.l+
';width:'+nd.w+';height:'+nd.h+'px;" class="dragId_'+$t.attr('id')+
' draggable"><div class="title">'+$t.attr('title')+'</div></div>');

任何建议/帮助将不胜感激。谢谢。

4

1 回答 1

3

这是您需要做的算法:

  1. 虽然有形状接触,但找出最右边的形状(具有最大右侧 x 坐标的那个)正在接触另一个形状。移动它,使其左边缘恰好位于它刚刚接触的最右侧形状的右侧。
  2. 虽然有些形状不在它们左边的东西旁边,但要找出左边 x 坐标最小的形状,它不在它左边的东西旁边。移动它,使其左边缘恰好位于对象 y 范围内具有最大右 x 坐标的形状的右侧。

够简单吗?好吧,这是简化版:

  1. 当有形状相互接触时,移动最右边的形状,使其不接触任何其他形状。
  2. 虽然有些形状没有相互依偎,但移动最左边的形状,使其依偎到最接近的形状。

编辑:例如...

假设我拿了正方形 3 并将其放在正方形 1 和正方形 2 的顶部:

1111 44
1111 44
1133333
1133333
  33333
  3333322
  3333322
     2222
     2222

第 1 步。找到与某物相交的最右边的形状。在这种情况下,这就是形状 2。将它移动到相交处的右侧。

1111 44
1111 44
1133333
1133333
  33333
  333332222
  333332222
       2222
       2222

现在有形状接触吗?是的,最右边的是形状 3。将它移动到它所接触的形状的右边,形状 1:

1111 44
1111 44
111133333
111133333
    33333
    3333322
    3333322
       2222
       2222

现在有形状接触吗?是的,最右边的是形状 2。将它移动到它所接触的形状的右边,形状 3:

1111 44
1111 44
111133333
111133333
    33333
    333332222
    333332222
         2222
         2222

现在有形状接触吗?不,所以我们完成了第 1 步。

第 2 步:找到最左边的形状,它没有依偎在任何东西上。在这种情况下,最左边的没有依偎在任何东西上的是形状 4。将它向左移动,使其位于与它存在相同 y 坐标的最右边形状的右侧:

111144
111144
111133333
111133333
    33333
    333332222
    333332222
         2222
         2222

有什么不依附于任何东西的吗?没有!所以你完成了!

如您所见,基本上有一个扩张阶段和一个收缩阶段。您从右到左进行扩展阶段,这样就没有任何东西可以通过其他东西进行扩展。您从左到右进行收缩阶段,因此没有任何东西通过其他方式收缩。

于 2009-10-08T19:37:11.717 回答