问题 应用CSS3比例时,Sortable行为错误


我正在使用CSS转换扩展JQuery可排序元素。两个可排序的项目开始位置和偏移,而拖动是错误的,因为JQuery不考虑CSS标度。我用这里的代码部分解决了它:

jQuery使用CSS转换比例拖动/调整大小

但我无法解决的问题是拖动开始时的可排序项目位置。它向上跳了一下。我无法弄清楚要放入启动事件处理程序的内容:

        start: function(e, ui)
        {
            // something is needed here to fix the initial offset
        }

这个小提琴显示了问题: http://jsfiddle.net/adrianrosca/zbvLp/4/


8348
2017-07-26 12:00


起源

我为这个问题开始了赏金。虽然我不一定认为这个问题广泛适用于大量观众,但我 做 喜欢看一个规范的答案,它解决了可排序的事件处理程序中究竟需要调整的内容以及为什么可以在OP中建议的jquery可拖动解决方案 参考SO问题,不适用于jquery sortables。 - Decent Dabbler


答案:


与...有一点不同 拖动 是那个 转变 不是元素本身,而是父母。所以它改变了一点逻辑。

这是针对这种特定情况的解决方案,但您会看到根据情况可能会发生变化。例如,如果您更改 变换原点,或者如果你有一个水平排序,它将不得不进行调整。但逻辑保持不变:

var zoomScale = 0.5;

$(".container")
  .sortable({

    sort: function(e, ui) {
    console.log(ui.position.left)
      var changeLeft = ui.position.left - ui.originalPosition.left;
      // For left position, the problem here is not only the scaling,
      // but the transform origin. Since the position is dynamic
      // the left coordinate you get from ui.position is not the one
      // used by transform origin. You need to adjust so that
      // it stays "0", this way the transform will replace it properly
      var newLeft = ui.originalPosition.left + changeLeft / zoomScale - ui.item.parent().offset().left;

      // For top, it's simpler. Since origin is top, 
      // no need to adjust the offset. Simply undo the correction
      // on the position that transform is doing so that
      // it stays with the mouse position
      var newTop = ui.position.top / zoomScale;

      ui.helper.css({
        left: newLeft,
        top: newTop
      });
    }
  });

http://jsfiddle.net/aL4ntzsh/5/

编辑:

之前的答案将适用于定位,但正如Decent Dabbler所指出的,交叉函数存在一个缺陷,可以在进行排序时进行验证。基本上,位置是正确计算的,但项目保持不变 宽度 和 高度 未转换的值,这会导致问题。 您可以通过在启动事件上修改这些值来调整这些值,以考虑比例因子。像这样举例如:

 start: function(e, ui) {
      var items = $(this).data()['ui-sortable'].items;
      items.forEach(function(item) {
        item.height *= zoomScale;
        item.width *= zoomScale;
      });
    }

http://jsfiddle.net/rgxnup4v/2/


8
2018-04-18 03:04



你和你的 user3765122的回答 似乎在很大程度上解决了OP的问题。然而,一个微妙的问题,我怀疑是我自己问题的罪魁祸首,似乎仍然存在于两者中:排序检测向右移动。如果你抓住水平中心的一个元素并将其拖过其他元素,同时小心地左右移动,你会看到这个。因为我使用连接的sortables,它更广泛 和 水平的兄弟姐妹,这个微妙的问题是非常放大的。你知道怎么补偿吗? - Decent Dabbler
也许我只需要为我的具体情况开始一个新问题,因为它比OP复杂得多,但如果你知道如何解决这个微妙的问题,我的问题可能会消失。在任何情况下:既然你的答案到目前为止看起来都是平等的,我还不完全确定奖励赏金的答案。我可能会决定给两者奖励。但也许你可以解释为什么两个答案似乎都有相同的结果? PS:到目前为止,非常感谢您的解决方案! - Decent Dabbler
好的,非常感谢你的加入!这个 不 解决OP的问题。不幸的是,它没有解决我连接的可排序的情况(连接的项目都显示为具有 {width: 0, height: 0, left: 0, top: 0}),但就像我说的,我的情况要复杂得多。所以,或者我要用更长的时间来摆弄它,以便真正尝试理解定位/偏移/等等的复杂性,或者如果我无法解决它,我会开始一个关于它的新问题。但赏金是当之无愧的,你给了我很多关于在哪里看的线索。再次感谢! - Decent Dabbler


你的问题有两件事:

  1. 元素的位置属性是基于最近的父级计算的,该父级的位置是绝对的或相对的。现在基于父母的身体是不好的,所以你必须添加 position:relative; 用于容器。
  2. 因为,正如您已经注意到的那样,JQuery在计算两者时都不会考虑CSS比例 ui.position 和 ui.originalPosition 所以你必须“申请” zoomScale 对他们两个。

CSS

.container
{
    position: relative;
    transform: scale(0.5);
    transform-origin: center top;
}

脚本

var changeLeft = ui.position.left - ui.originalPosition.left;
var newLeft = (ui.originalPosition.left + changeLeft) / zoomScale;
var changeTop = ui.position.top - ui.originalPosition.top;
var newTop = (ui.originalPosition.top + changeTop) / zoomScale;

这是更新代码: http://jsfiddle.net/zbvLp/9/


1
2018-04-19 10:07



你和你的 JulienGrégoire的回答 似乎在很大程度上解决了OP的问题。然而,一个微妙的问题,我怀疑是我自己问题的罪魁祸首,似乎仍然存在于两者中:排序检测向右移动。如果你抓住水平中心的一个元素并将其拖过其他元素,同时小心地左右移动,你会看到这个。因为我使用连接的sortables,它更广泛 和 水平的兄弟姐妹,这个微妙的问题是非常放大的。你知道怎么补偿吗? - Decent Dabbler
也许我只需要为我的具体情况开始一个新问题,因为它比OP复杂得多,但如果你知道如何解决这个微妙的问题,我的问题可能会消失。在任何情况下:既然你的答案到目前为止看起来都是平等的,我还不完全确定奖励赏金的答案。我可能会决定给两者奖励。但也许你可以解释为什么两个答案似乎都有相同的结果? PS:到目前为止,非常感谢您的解决方案! - Decent Dabbler