HTML5拖放事件和setDragImage的浏览器支持

11
我正在开发一个小型jQuery插件,使用本地HTML5拖放事件来模仿jQuery UI可拖动/可放置行为。
我想要添加的功能是指定节点作为拖动代理。
经过一些研究,根据MDN的说法,这需要使用setDragImage(),传递图像或元素。
不同浏览器对于setDragImage的支持如何?
我注意到有一个名为jquery.event.drag的插件,它对此问题采取了与我预期不同的方法。
这个功能是否需要我像上面的插件一样做一些解决方案,还是应该可以在大多数或所有浏览器中直接使用setDragImage实现? 编辑

在尝试了一下这个功能后,似乎发现这个函数非常有限。

除了在许多浏览器中没有支持外,将任意DOM元素用作助手需要它在DOM树中可见,因此您需要在body上拥有该元素本身和其副本作为处理程序。对于这种插件,这大多是不需要的。

此外,即使符合正确的条件,渲染也存在问题。当尝试从<span>TEST</span>创建助手时,助手本身只显示了一个具有标签尺寸的白色矩形。

这些问题是按照规格预期的吗?它们可以在代码中修复还是需要解决方法?

1个回答

20

对于任何非平凡的拖放用例,我认为setDragImage是至关重要的功能。例如,考虑多选列表,其中拖动需要包括所有选定的项目,而不仅仅是进行拖动手势的行。很奇怪你想设置的内容需要在DOM中可见,但更糟糕的是,自版本11起,IE根本没有实现此方法。

然而,经过一点努力,我能够使它相当令人满意地工作。可以在timeout 0函数中从DOM中删除自定义拖动图像节点。因此,在dragstart中将其添加到DOM中,然后在setDragImage中使用它,最后再将其删除。这在Firefox中完美运行,但在Chrome中,拖动图像节点会在超时触发之前闪烁。防止这种情况的一种方法是将其定位,使实际由浏览器生成的拖动图像出现在完全相同的位置上。这并不像听起来那么糟糕,因为您可以控制自定义拖动图像相对于光标的位置。

最近我正在玩这个,并成功让它在IE上工作。其中的诀窍是让IE拖动自定义拖动图像节点而不是dragstart触发的节点。您可以使用特定于IE的dragDrop()方法来实现此目的。

最后要注意的是,在Windows上,自定义拖动图像节点的宽度有300px的限制,这适用于所有可拖动的对象,而不仅仅是自定义节点。因此,如果拖动图像太大,浏览器会应用重型径向渐变。

http://jsfiddle.net/stevendwood/akScu/21/

$(function() {

(function($) {
    var isIE =  (typeof document.createElement("span").dragDrop === "function");
    $.fn.customDragImage = function(options) {

        var offsetX = options.offsetX || 0,
            offsetY = options.offsetY || 0;

        var createDragImage = function($node, x, y) {
            var $img = $(options.createDragImage($node));
            $img.css({
                "top": Math.max(0, y-offsetY)+"px",
                "left": Math.max(0, x-offsetX)+"px",
                "position": "absolute",
                "pointerEvents": "none"
            }).appendTo(document.body);

            setTimeout(function() {
                $img.remove();
            });

            return $img[0];
        };

        if (isIE) {
            $(this).on("mousedown", function(e) {
                var originalEvent = e.originalEvent,
                    node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY);

                node.dragDrop();
            });
        }

        $(this).on("dragstart", function(e) {

           var originalEvent = e.originalEvent,
               dt = originalEvent.dataTransfer;

            if (typeof dt.setDragImage === "function") {
                node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY);
                dt.setDragImage(node, offsetX, offsetY);  
            }
        });

        return this;
    };
}) (jQuery);



$("[draggable='true']").customDragImage({
    offsetX: 50,
    offsetY: 50,
    createDragImage: function($node) {
        return $node.clone().html("I'm a custom  DOM node/drag image").css("backgroundColor", "orange");
    }
}).on("dragstart", function(e) {
    e.originalEvent.dataTransfer.setData("Text", "Foo");
});

});

1
了不起的概念验证和巧妙的解决方法! - GeReV
1
这个解决方法对于IE Edge仍然有效,因为它也没有实现setDragImage。 - Adam B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接