Firefox 在拖放幽灵预览中不显示图像

Posted

技术标签:

【中文标题】Firefox 在拖放幽灵预览中不显示图像【英文标题】:Firefox is not displaying image in drag and drop ghost preview 【发布时间】:2017-10-02 19:04:35 【问题描述】:

我正在尝试显示幽灵元素而不是默认浏览器预览以进行拖放。问题是在拖动时不显示幽灵元素内的Firefox图像。但是,如果我放下它,然后再次拖动图像 就会显示出来。

所以我认为这可能是某种与缓存相关的问题。但是在这种情况下我看不到如何预先缓存图像。

代码如下:

//html:

<div class="parent container">
<img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />
</div>

//js:

document.querySelector(".element").addEventListener("dragstart", function(e) 
    var img = document.createElement("img");
    var div = document.createElement('div');
    div.style.width = '100px';
    div.style.height = '100px';
    div.style.position = 'fixed';
    div.style.top = '-1000000px';
    div.style.left = '-1000000px';
    div.style.border = '2px solid red';

    img.src = "http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg";
    img.style.width = '100px';
    img.style.height = '100px';
    div.appendChild(img);
    document.body.appendChild(div);
    e.dataTransfer.setData('text/plain', 'test');
    e.dataTransfer.setDragImage(div, 0, 0);
, false);

小提琴: https://jsfiddle.net/etseq5cg/5/

重现步骤:

1) 打开 fiddle/运行 sn-p

2) 尝试拖动示例图片

实际:你会看到一个带有红色边框的空方块

预期:正方形,里面有图片。

要再次重现它,您需要强制重新加载页面(ctrl+f5)。这就是为什么我认为这是与缓存相关的问题。

注意:我知道我应该在 dragend 处理程序中从 DOM 中删除 ghost 元素,但这在这里并不重要。

更新:

1) 实际用例包括包含大量图像(~500)的视图,因此不能通过 js 预缓存图像。

2) 对于那些无法重现问题的人,这里是截图:首先你看到硬重载(ctrl+f5) 后的预览,然后是第二次拖动尝试。请注意,在这两种情况下,网络检查器的网络选项卡中都没有看到 http 请求。

【问题讨论】:

您遇到的问题是在将 div 附加到您的身体后正在加载您的图像。您可以使用图像onload 等待图像加载,看看这个答案:***.com/questions/12354865/…。您可以在用户拖动元素之前(在页面加载时)创建元素,这样您就不必等待图像加载。 @toggy-tog-togs 我等不及图像加载事件,因为这是异步操作,调用“setDragImage”是同步的。因此,如果我在“onload”回调中调用“setDragImage”,它不会做任何事情。如您所见,图像本身已添加到 DOM(我使用相同的图像进行预览和 dnd ghost)。 我在 Firefox 中尝试了 jsfiddle。当我拖动“Sample”图像时,我看到了“Sample”重影图像。 @ConnorsFan 我添加了“更新”部分,其中包含我所得到的截图。 【参考方案1】:

当我在 Firefox 53(在 Windows 7 上)中运行 your jsfiddle 时,我看不到问题。重影图像和被拖动的图像具有相同的 URL,并且在拖动时始终显示重影图像。但是,我可以使用具有不同 URL 的幻影图像重现该问题。

您可以添加一个隐藏的img 控件来预加载重影图像。像这样的:

<div class="parent container">
    <img class="element" draggable="true" src="http://the.element.image" />
    <img class="imgGhost" src="http://the.ghost.image" />
</div>

根据我的测试,这些设置阻止了 Firefox 中的图像预加载:

display: none隐藏元素 设置空大小(width: 0pxheight: 0px) 将其移出视口(例如left: -10000px

link prefetching 我也没有取得太大的成功。但是,visibility: hidden 似乎有效。隐藏图像元素的样式可以定义为:

.imgGhost 
    position: absolute;
    left: 0px;
    top: 0px;
    visibility: hidden;

该方法可以测试this jsfiddle中的两个可拖动图像。在dragstart 事件处理程序中,从隐藏元素中检索图像 URL:

img.src = this.parentNode.querySelector(".imgGhost").src;

但它可能是硬编码的。如果您愿意,您可以在页面加载时动态设置隐藏图像的src 属性。在 jsfiddle 中进行测试时,您可以在再次运行之前更改幻影图像名称(例如 225x225),以确保图像未被缓存。


根据您的评论,预加载图像不是一种选择。并且您对拖动的幻影图像使用相同的图像 URL。在这种情况下,您可以检查 this page 以查看是否有任何选项阻止重新加载图像。

dragstart 事件处理程序中将div 控件添加到body 后,您还可以强制重新绘制布局。这可以通过调用div.offsetHeight来实现:

div.appendChild(img);
document.body.appendChild(div);
div.offsetHeight; // Force repaint

【讨论】:

能够在 *nix 的 firefox 53 上重现 OP 中描述的问题。 您好,感谢您的回答。我已经为这个问题添加了“更新”部分,并举例说明了我得到了什么。不幸的是,预缓存图像不是我的选择。 如果截图是用your jsfiddle获取的,那我们肯定有不同的配置。您使用的是什么操作系统?哪个版本的 Firefox?由于图像已经显示,它应该是可用的。你有RealPlayer插件吗(貌似可以cause trouble when reloading images)? @Rasalom - 我在回答中添加了另一个建议:在布局中添加 div 元素后强制重新绘制。 感谢您的帮助,但没有一个选项对我有用。我想我得写好旧的 js 拖动预览。【参考方案2】:

css 设置.parent 伪类:hover.element backgroundurl("/path/to/image") 以获取:hover&lt;img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" /&gt; 父元素的图像。在dragstart 事件集div .className"element"

.element 
  width: 100px;
  height: 100px;
  background: url("http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg");
  background-size: 100px 100px;
  


.parent:hover 
  background: url("http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg");
  background-size: 0px 0px;
<div class="parent container">

  <img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />

</div>
    <script>
    function handleImage(e) 
      var div = document.createElement('div');
      div.style.width = '100px';
      div.style.height = '100px';
      div.style.position = 'fixed';
      div.style.top = '-1000000px';
      div.style.left = '-1000000px';
      div.style.border = '2px solid red';
      div.className = "element";
      document.body.appendChild(div);
      e.dataTransfer.setData('text/plain', 'test');
      e.dataTransfer.setDragImage(div, 0, 0);
    
 document.querySelector(".element")
 .addEventListener("dragstart", handleImage, false);
  </script>

jsfiddle https://jsfiddle.net/etseq5cg/7/

【讨论】:

以上是关于Firefox 在拖放幽灵预览中不显示图像的主要内容,如果未能解决你的问题,请参考以下文章

C# 具有叠加/不透明图像的拖放效果

UITableView - 如何在拖放期间更改单元格的背景颜色?

拖放在Firefox中不起作用[重复]

背景图像在 Firefox 中不显示

以 chrome 显示但在 Firefox 中不显示的视图的图像

在 IE/Chrome/Firefox 中打印预览(或打印)时不显示图像