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: 0px
或 height: 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
background
到url("/path/to/image")
以获取:hover
的<img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />
父元素的图像。在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 在拖放幽灵预览中不显示图像的主要内容,如果未能解决你的问题,请参考以下文章
UITableView - 如何在拖放期间更改单元格的背景颜色?