Firefox не отображает изображение в предварительном просмотре призрака

Я пытаюсь отобразить элемент-призрак вместо предварительного просмотра браузера по умолчанию для перетаскивания. Проблема заключается в том, что в файле firefox внутри элемента ghost не отображается при перетаскивании. Но если я его сброшу и снова перетаскиваю, изображение будет отображаться.

Итак, я думаю, что это может быть какая-то проблема с кешем. Но я не вижу, как я могу предварительно кэшировать изображение в этом случае.

Здесь код:

//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) открыть скрипт/запустить фрагмент

2) попробуйте перетащить образец изображения

Фактически: вы увидите пустой квадрат с красной рамкой

Ожидается: квадрат с изображением внутри.

Чтобы воспроизвести его снова, вам необходимо принудительно перезагрузить страницу (ctrl + f5). Вот почему я думаю, что это проблема с кешем.

Примечание. Я знаю, что я должен удалить элемент-призрак из DOM в обработчике dragend, но здесь это не важно.

Обновление:

1) фактический прецедент включает в себя просмотр с большим количеством изображений (~ 500), поэтому он не может предварительно кэшировать изображения через js.

2) Для тех, кто не смог воспроизвести проблему, вот скриншот: сначала вы видите предварительный просмотр после жесткой перезагрузки (ctrl + f5), а затем вторую попытку перетаскивания. Обратите внимание, что никакие HTTP-запросы не отображаются на вкладке сети в веб-инспекторе в обоих случаях. screenshot

Ответы

Ответ 1

Я не вижу проблемы, когда я запускаю ваш jsfiddle в Firefox 53 (в Windows 7). Призрачное изображение и перетаскиваемое изображение имеют одинаковый 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)

У меня также не было большого успеха с предварительная выборка ссылок. Однако 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 изображения для перетаскивания призрачного изображения. В этом случае вы можете проверить эту страницу, чтобы узнать, предотвращает ли какой-либо параметр перезагрузку изображения.

Вы также можете принудительно перекрасить макет после добавления элемента div в body в обработчик события dragstart. Этого можно достичь, позвонив div.offsetHeight:

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

Ответ 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>