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

Posted

技术标签:

【中文标题】HTML5 拖放事件和 setDragImage 浏览器支持【英文标题】:HTML5 Drag and Drop events and setDragImage browser support 【发布时间】:2012-09-27 18:45:33 【问题描述】:

我正在开发一个small jQuery plugin,它通过原生 html5 拖放事件模拟 jQuery UI 可拖放/可拖放行为。

我想要添加的一个功能是能够指定将用作拖动代理的节点。

我做了一些研究,according to MDN,为此需要使用setDragImage(),传递图像或元素。 不同浏览器对setDragImage的支持是什么?

我注意到有一个名为 jquery.event.drag 的插件与我对这个问题的预期不同。 这个功能是否需要我像上面的插件一样做某种解决方法,还是应该在大多数或所有使用 setDragImage 的浏览器中开箱即用?

编辑

在玩了一会儿这个功能之后,似乎这个功能非常有限。

除了在相当多的浏览器中不支持之外,使用任意 DOM 元素作为 helper 要求它在 DOM 树中并且可见,因此您将元素本身放在主体上,并将其副本作为处理程序。这对于这类插件来说是最不需要的。

此外,即使满足正确的条件,渲染也存在问题。在尝试从<span>TEST</span> 创建助手时,助手本身只显示一个白色矩形,其尺寸与span 相同。

这些问题是否符合规范?它们可以在代码中修复还是需要解决方法?

【问题讨论】:

【参考方案1】:

setDragImage 是 IMO 任何重要的拖放用例的重要功能。例如,考虑一个多选列表,其中拖动需要包括所有选定的项目,而不仅仅是做出拖动手势的行。奇怪的是,您要设置的东西需要在 DOM 中可见,但更糟糕的是,从 IE 版本 11 开始,此方法根本没有实现。

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

我最近在玩这个,并且能够让它在 IE 上运行。诀窍是让 IE 拖动自定义拖动图像节点,而不是 dragstart 触发的节点。您可以使用 IE 特定的 dragDrop() 方法来做到这一点。

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

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");
);

);

【讨论】:

出色的概念证明和出色的解决方法! 这个变通方法对 IE Edge 仍然有效,它也没有实现 setDragImage。

以上是关于HTML5 拖放事件和 setDragImage 浏览器支持的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 Draggable setDragImage 不适用于 Chrome 上的画布

为啥HTML5拖放dragImage隐藏时不显示?

HTML5 拖放 getData() 仅适用于 Chrome 中的拖放事件?

HTML5 拖放 getData() 仅适用于 Chrome 中的拖放事件?

HTML5拖放的dragover vs dragenter事件

HTML5-原声拖放