可拖动和保证金:0自动;

时间:2016-03-08 17:29:43

标签: javascript jquery css jquery-ui

这是一个jQuery UI可排序/可拖动的问题,如果被拖动的元素使用margin:0 auto居中,则拖动从容器的左侧开始,而不是元素实际所在的中心。

下载一个演示来展示我的意思:http://codepen.io/anon/pen/YqWRvV。只需拖动红色方块即可。

如果从'.drag'元素中删除margin:0 auto,您会看到拖动正常开始。

如何解决此问题,并在使用margin:0 auto进行居中时,将元素从实际位置拖动?

这似乎发生在谷歌浏览器中。

$("#c").sortable();

`.drag {
   margin: 0 auto;
   width: 200px;
   height: 200px;
   background-color: red;
}`

使用CSS'calc'对元素进行居中修复问题,但我的元素宽度可以动态更改。 'calc'也不像'margin'那样得到支持。

将draggable包装在容器中可以解决问题,但HTML更改不是我正在寻找的解决方案。

更新 所以这不是一个jQuery错误。这是谷歌Chrome的一个错误。显然,chrome会检索错误的位置,因此jQuery会从chrome告诉它元素所在的位置开始拖动。我在控制台中输出元素的左侧位置,当它显然不是时,您可以看到它是13px。 http://codepen.io/anon/pen/YqWRvV。我想知道这个bug是否已被报道。

http://codepen.io/anon/pen/MyjeJP感谢JulienGrégoire 注意:此解决方案可能需要一种方法来刷新帮助程序位置。

6 个答案:

答案 0 :(得分:2)

Chrome以不同于Firefox的方式返回位置,但您可以使用偏移获得正确的坐标,这是可排序使用的。问题是在 mouseStart 上,边距会从计算中移除,这可能在您设置边距时有意义。但是有了自动余量,就会产生这个问题。

您可以添加一个选项来忽略边距并修改 _mouseStart 。像这样:

$("#c").sortable({
  ignoreMargins: true
});

$.ui.sortable.prototype._mouseStart = function(event, overrideHandle, noActivation) {
    ...
    if (!this.options.ignoreMargins) {

      this.offset = {
        top: this.offset.top - this.margins.top,
        left: this.offset.left - this.margins.left
      };
    }
    ...
}

http://codepen.io/anon/pen/BKzeMp

编辑:

如果您不想修改插件,可以使用开始停止事件。一个问题是很难检查边距是否已设置为自动,因此您可以在可排序的调用中定义它们,这不像它应该的那样灵活,或者您找到一种方法来检查哪些边距是自动动态的。

$("#c").sortable({
  start: function(e, ui) {
    var marginsToSet = ui.item.data().sortableItem.margins;
    // You set the margins here, so they don't go back to 0 
    // once the item is put in absolute position
      ui.item.css('margin-left', marginsToSet.left);
      ui.item.css('margin-top', marginsToSet.top);

  },
  stop: function(e, ui) {
    // Then you need to set the margins back once you stop dragging.
    // Ideally this should be dynamic, but you have to be able
    // to check which margins are set to auto, which as you'll
    // see if you look for some answers on this site, 
    // doesn't look that simple.
    ui.item.css('margin', '20px auto');
  }
});

http://codepen.io/anon/pen/mPrdYp

答案 1 :(得分:1)

嘿我正在测试您的Codepen并在两个不同的浏览器(Mozilla和Chrome)中进行检查。

我得到的东西就是你所说的Chrome。但在Mozilla,它的工作正常。

在铬位置左侧属性值不同。在Mozilla中它意味着左:560px在拖动时在Chrome中它从左边开始:0;

这就是从左侧显着显示拖动元素的原因。

我希望它会对你有所帮助。

答案 2 :(得分:1)

更新你的jQuery以添加克隆助手:

$("#c").sortable({
 helper: "clone"
});

更新你的CSS以添加位置和溢出:

#c {
  width: 100%;
  padding: 50px 0px;
  border: solid 5px;
  box-sizing: border-box;
  overflow: hidden;
  position: relative;
}

<强> Updated Codepen

答案 3 :(得分:1)

我出现的解决方法是 http://codepen.io/anon/pen/VaaaaZ

在CSS中使用calc而不是自动

答案 4 :(得分:0)

如果您不能使用CSS设置中心,则使用JQuery设置中心选项。 请查看我在您的代码库中根据您在本文中解释的反馈和要求以及其他答案更新的演示。 Demo

Cabinet error code 1

答案 5 :(得分:0)

当您使用.sortable()并将margin: 0 auto位置设为left时,Chrome 0似乎无法正确计算元素的位置。所以我想你应该找到其他方法来横向居中你。

一种选择是在父元素上使用text-align: center,在子元素

上使用display: inline-block

$("#c").sortable();
#c {
  width: 100%;
  padding: 50px 0px;
  border: solid 5px;
  box-sizing: border-box;
  text-align: center;
}

.drag {
  width: 200px;
  height: 200px;
  background-color: red;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<div id="c">
  <div class="drag"></div>
</div>

另一个是使用Flexbox并将子元素与justify-content: center

居中

$("#c").sortable();
#c {
  width: 100%;
  padding: 50px 0px;
  border: solid 5px;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
}

.drag {
  width: 200px;
  height: 200px;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<div id="c">
  <div class="drag"></div>
</div>