如何使用jQuery UI Sortable正确相交?

How to use jQuery UI Sortable to intersect properly?

这是我尝试制作动画 jQuery UI 可排序:
https://codepen.io/anon/pen/YdMOXE

var startIndex, changeIndex, uiHeight;

$('ul').sortable({
    'placeholder': 'marker',
    start: function(e, ui) {

        startIndex = ui.placeholder.index();
        uiHeight = ui.item.outerHeight(true);//get offset incl margin

        ui.item.nextAll('li:not(.marker)').css({
            transform: 'translateY(' +uiHeight+ 'px)'
        });

        ui.placeholder.css({
            height: 0,
            padding: 0
        });
    },
    change: function(e, ui) {

        changeIndex = ui.placeholder.index();


        if (startIndex > changeIndex) {

            var slice = $('ul li').slice(changeIndex, $('ul li').length);

            slice.not('.ui-sortable-helper').each(function() {
                var item = $(this);
                item.css({
                    background:'lightcoral',
                    transform: 'translateY(' +uiHeight+ 'px)'
                });
            });

        } else if (startIndex < changeIndex) {

            var slice = $('ul li').slice(startIndex, changeIndex);

            slice.not('.ui-sortable-helper').each(function() {
                var item = $(this);
                item.css({
                    background: 'lightgreen',
                    transform: 'translateY(0px)'
                });
            });
        }

        startIndex = changeIndex
    },
    stop: function(e, ui) {
        $('.ui-sortable-handle').css({
            background: 'lightblue',
            transform: 'translateY(0)'
        })
    }
});

不幸的是,它不能与 tolerance: intersect 一起可靠地工作。 (当元素的 50% 重叠时排序改变)。它似乎只想通过指针位置进行排序。附件是一个视频来展示这一点。 https://gfycat.com/WatchfulPresentHedgehog

如何使它与 intersect 一起正常工作?

可以看到the bug #8342

Sortable: Incorrect behaviour (or incorrect documentation) of sortable option tolerance: 'intersect'

我现在已经测试了解决方法(来自 this answer (I have corrected it for vertical using) and from this answer),这些方法在 Munim Munna 评论中 linked 并且两种解决方法都无法正常工作(非常非常越野车)。

tolerance: 'pointer'

的解决方法

您必须设置 tolerance: 'pointer'cursorAt: {top: height/2, left: width/2}(可拖动元素的宽度和高度的一半大小)。

tolerance : 'pointer'选项允许元素在光标进入目标元素时立即替换目标元素。默认情况下,它被设置为 tolerance : 'intersect',这意味着该项目与其他项目至少重叠 50%。但不幸的是,此选项存在错误(请参阅我的回答顶部)。

也尝试在有或没有 cursorAt 选项的情况下使用它或更改值。此选项移动排序元素或助手,使光标始终显示为从同一位置拖动。坐标可以使用一个或两个键的组合作为散列给出:{top, left, right, bottom}.

这是 tolerance option and for cursorAt option.

的文档

2019 年 1 月 29 日更新

我修复了 jQuery UI 中的一些错误 可排序:从最后一个项目拖动时如果它没有足够的 space 用于移动。我通过添加此代码修复了此错误:

<div style="clear: both; line-height: 500px">&nbsp;</div>

直接在可排序元素之后。

var startIndex, changeIndex, uiHeight,
    bRect = $("ul li")[0].getBoundingClientRect(),
    width = bRect.right - bRect.left,
    height = bRect.bottom - bRect.top;

$('ul').sortable(
{
    tolerance: 'pointer',
    cursorAt: {top: height/2, left: width/2}, //try to use it with and without this option
    'placeholder': 'marker',
    start: function(e, ui)
    {
        startIndex = ui.placeholder.index();
        uiHeight = ui.item.outerHeight(true); //get offset incl margin

        ui.item.nextAll('li:not(.marker)').css({
            transform: 'translateY(' + uiHeight + 'px)'
        });
        ui.placeholder.css({height:0, padding:0});
    },

    change: function(e, ui)
    {
        changeIndex = ui.placeholder.index();

        if(startIndex > changeIndex)
        {
            var slice = $('ul li').slice(changeIndex, $('ul li').length);

            slice.not('.ui-sortable-helper').each(function()
            {
                var item = $(this);
                item.css({
                    background:'lightcoral',
                    transform: 'translateY(' +uiHeight+ 'px)'
                });
            });
        }
        else if(startIndex < changeIndex)
        {
            var slice = $('ul li').slice(startIndex, changeIndex);
            slice.not('.ui-sortable-helper').each(function()
            {
                var item = $(this);
                item.css({
                    background: 'lightgreen',
                    transform: 'translateY(0px)'
                });
            });
        }

        startIndex = changeIndex
    },

    stop: function(e, ui)
    {
        $('.ui-sortable-handle').css({
            background: 'lightblue',
            transform: 'translateY(0)'
        })
    }
});
body{color:white; font-family:Helveticasans-serif; padding:10px}
ul{float:left; width:300px; border-radius:6px}
ul:after{clear:both; content:''; display:table}
li
{
    background: lightblue;
    display: block;
    position: relative;
    padding: 80px 6px;
    z-index: 1;
    margin: 5px 20px;
    overflow: hidden;
    transition: transform .2s
}
.marker{opacity:0.0; transition:.2s height}
.ui-sortable-helper{transform:scale(.9)}
<br><br>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>
<!--
Fixing some bugs from jQuery UI Sortable:
on dragging from last item if after it
it has not enough space for moving
-->
<div style="clear: both; line-height: 500px">&nbsp;</div>
<!--END of Fixing bugs-->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>

在整页中查看此代码片段更有用(使用代码片段右上方的 link)。