html拖放setDragImage在第一次拖动时没有设置重影图像

Car*_*ler 8 html jquery jquery-ui-draggable

我正在尝试创建一个拖放菜单,用户可以将图像缩略图从div拖动到画布.

问题是源div使用精灵来显示它的背景缩略图,所以我必须使用setDragImage来允许在拖动div时显示图像.

我可以成功地将div拖动到画布并将图像拖放得很好,但是我的问题是拖动鬼图像直到我第二次拖动div时才会显示.

我使用上一个答案的代码:[ HTML5拖放事件和setDragImage浏览器支持

这是我对此代码的略微修改版本:

var isIE =  (typeof document.createElement("span").dragDrop === "function");


$.fn.customDragImage = function(options) {
    var offsetX = 0,
        offsetY = 0;

    var createDragImage = function($node, x, y) {
        var $img = $(options.createDragImage($node));
        icon = "icon" + window.draggedimgsrc;
        offsetX = window[icon][2] / 2;
        offsetY = window[icon][3] / 2;
        $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);
            console.log("node="+node);
            dt.setDragImage(node, offsetX, offsetY);  
        }
    });

    return this;

};

$("[draggable='true']").customDragImage({
    createDragImage: function($node) {
        //init icon [0] = icon filename | [1] = icon set | [2] = icon width | [3] = icon height
        icon = "icon" + window.draggedimgsrc;
        window.draggedimgset = window[icon][1];
        image="/boards/markers/soccerm/set" + window[icon][1] + "/" + window[icon][0] + ".png";
        return $node.clone().css("width", window[icon][2]).css("height", window[icon][3]).css("background", "transparent url(" + image + ") no-repeat center");        }
}).on("dragstart", function(e) {
    e.originalEvent.dataTransfer.setData("Text", "Foo");
});
Run Code Online (Sandbox Code Playgroud)

奇怪的是,当我在$ node.clone()上弹出一个边框时,它会在我第一次拖动时被设置,它似乎似乎没有将图像放在那里.

我还设置了手动宽度和高度,所以我知道它不是图像的大小.

我会在菜单出现之前预先加载图像.

有任何想法吗?

小智 15

所以这已经过时了,但我也一直在努力解决这个问题.我发现问题是我在dragstart事件中创建了鬼图像,我看到你也在做.

因此,在您创建自定义重影图像时,拖动已经开始,这意味着在您开始新的拖动之前它将不可见.

所以只需尝试在dragstart之外调用createDragImage.为我工作.

  • 我遇到了同样的问题,但就我而言,我只是想将拖动图像设置为页面上_已经_的元素,如下所示: `e.dataTransfer.setDragImage(document.getElementById('myElement', 0, 0);`.我不明白为什么它不起作用,因为该元素已经存在了。 (2认同)

ben*_*nvc 6

将拖动反馈图像预加载到事件侦听器外部似乎可以避免拖动图像不会出现在第一次拖动中的问题。有多种方法可以做到这一点,最好的方法高度依赖于您要尝试执行的操作。以下是一种方法,其中将拖动图像的url存储在可拖动元素上的数据属性中,并预先创建每个元素的拖动反馈图像并将其存储在对象中。

以下是jQuery和Vanilla JS的示例:

const draggable = $('div');
let images = {};

draggable.each((i, elem) => {
  let src = $(elem).data('src');
  let img = new Image();
  img.src = src;
  images[src] = img;
});

draggable.on('dragstart', (event) => {
  let src = $(event.currentTarget).data('src');
  let img = images[src];
  let drag = event.originalEvent.dataTransfer;
  drag.setDragImage(img, 0, 0);
  drag.setData('text/uri-list', src);
});
Run Code Online (Sandbox Code Playgroud)
div {
  border: 1px solid #000000;
  height: 100px;
  width: 100px;
  line-height: 100px;
  text-align: center;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div draggable="true" data-src="https://via.placeholder.com/50/0000FF">drag me</div>
<div draggable="true" data-src="https://via.placeholder.com/50/FF0000">drag me</div>
Run Code Online (Sandbox Code Playgroud)

const elems = document.querySelectorAll('div');
let images = {};
for (let elem of elems) {
  let src = elem.dataset.src;
  let img = new Image();
  img.src = src;
  images[src] = img;
  
  elem.addEventListener('dragstart', (event) => {
    let src = event.currentTarget.dataset.src;
    let img = images[src];
    event.dataTransfer.setDragImage(img, 0, 0);
    event.dataTransfer.setData('text/uri-list', src);
  });

}
Run Code Online (Sandbox Code Playgroud)
div {
  border: 1px solid #000000;
  height: 100px;
  width: 100px;
  line-height: 100px;
  text-align: center;
}
Run Code Online (Sandbox Code Playgroud)
<div draggable="true" data-src="https://via.placeholder.com/50/0000FF">drag me</div>
<div draggable="true" data-src="https://via.placeholder.com/50/FF0000">drag me</div>
Run Code Online (Sandbox Code Playgroud)