setDragImage is IMO a vital feature for any non trivial drag and drop use case. e.g consider a multi select list where a drag needs to include all the selected items and not just the row that the drag gesture was made on. it's odd that the thing you want to set needs to be visible in the DOM but even worse is that this method is not implemented at all in IE as of version 11.
However, with a bit of effort I was able to get it working reasonably satisfactorily. The custom drag image node can be removed from the DOM in a timeout 0 function. so add it to the DOM in dragstart then use it in set drag image and then remove it. This works perfectly in FF but in chrome the drag image node will flicker before the timeout fires. One way to prevent this is to position it such that the actual browser generated drag image will appear in exactly the same place, this is not as bad as it sounds since you can control the position of the custom drag image relative to the cursor.
I was playing with this recently and was able to get it working on IE as well. the trick there is to get IE to drag the custom drag image node and not the node that dragstart fired on. you can do this with the IE specific dragDrop() method.
The final thing to be aware of is that on windows there is a 300px limit on the width of the custom drag image node this applies to all draggables not just the custom node actually. so the browser applies a heavy radial gradient if the drag image is too big.
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");
});
});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…