2017-05-04 21 views
16

Tôi đang cố gắng hiển thị phần tử ma thay vì xem trước trình duyệt mặc định để kéo và thả. Vấn đề là trong hình ảnh firefox bên trong phần tử ma không được hiển thị trong khi kéo. Nhưng nếu tôi thả nó và kéo lại hình ảnh được hiển thị.Firefox không hiển thị hình ảnh trong chế độ xem kéo và thả ma

Vì vậy, tôi nghĩ rằng đây có thể là một số vấn đề liên quan đến bộ nhớ cache. Nhưng tôi không thể thấy cách tôi có thể lưu trước hình ảnh trong trường hợp này.

Dưới đây là các mã:

// 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); 

Fiddle: https://jsfiddle.net/etseq5cg/5/

bước để tái sản xuất:

1) mở fiddle/chạy đoạn

2) cố gắng kéo hình ảnh mẫu

thực tế: bạn sẽ thấy một hình vuông rỗng với đường viền màu đỏ

dự kiến: hình vuông với hình ảnh bên trong.

Để tái tạo lại, bạn cần buộc tải lại trang (ctrl + f5). Đó là lý do tại sao tôi nghĩ rằng đây là vấn đề về bộ nhớ cache.

Lưu ý: Tôi biết rằng tôi nên xóa phần tử ma khỏi DOM trong trình xử lý kéo, nhưng điều này không quan trọng ở đây.

Cập nhật:

1) việc sử dụng hợp cụ thể thực tế bao gồm quan điểm với số lượng lớn các hình ảnh (~ 500), vì vậy nó không phải là một tùy chọn để pre-cache hình ảnh qua js.

2) Đối với những người không thể tạo lại vấn đề, dưới đây là ảnh chụp màn hình: lúc đầu bạn thấy bản xem trước sau khi tải lại cứng (ctrl + f5) và sau đó là lần thử kéo thứ hai. Xin lưu ý rằng không có yêu cầu http nào được nhìn thấy trong tab mạng trong thanh tra web trong cả hai trường hợp. screenshot

+0

Vấn đề bạn gặp phải là hình ảnh của bạn đã được nạp sau khi div được gắn vào cơ thể của bạn. Bạn có thể sử dụng hình ảnh 'onload' để chờ tải hình ảnh, hãy xem câu trả lời này: http://stackoverflow.com/questions/12354865/image-onload-event-and-browser-cache. Thay vào đó, bạn có thể tạo phần tử trước khi người dùng kéo phần tử (trên tải trang), do đó bạn không cần phải xử lý việc chờ tải hình ảnh. –

+0

@ toggy-tog-togs Tôi không thể đợi sự kiện tải hình ảnh vì đây là hoạt động không đồng bộ và gọi 'setDragImage' là đồng bộ hóa. Vì vậy, nếu tôi gọi 'setDragImage' bên trong 'onload' gọi lại nó sẽ không làm bất cứ điều gì. Và như bạn có thể thấy chính hình ảnh đã được thêm vào DOM (tôi sử dụng cùng một hình ảnh để xem trước và dnd ghost). – Rasalom

+0

Tôi đã thử jsfiddle trong Firefox.Khi tôi kéo hình ảnh "Mẫu", tôi thấy hình ảnh ma "Mẫu". – ConnorsFan

Trả lời

7

Tôi không thể thấy sự cố khi chạy your jsfiddle trong Firefox 53 (trên Windows 7). Hình ảnh ma và hình ảnh được kéo có cùng URL và hình ảnh ma luôn được hiển thị khi kéo. Tuy nhiên, tôi có thể tái tạo sự cố với hình ảnh ma có URL khác.

Bạn có thể thêm một điều khiển img ẩn để tải trước hình ảnh ma.Một cái gì đó như thế này:

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

Theo thử nghiệm của tôi, các thiết lập này ngăn ngừa sự tải trước hình ảnh trong Firefox:

  • Ẩn phần tử với display: none
  • Thiết lập một kích thước null (width: 0px hoặc height: 0px)
  • Di chuyển nó ra ngoài chế độ xem (ví dụ: left: -10000px)

Tôi cũng không có nhiều thành công với link prefetching. Tuy nhiên, visibility: hidden dường như hoạt động. Kiểu của phần tử hình ảnh ẩn có thể được định nghĩa là:

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

Phương pháp này có thể được thử nghiệm cho hai hình ảnh có thể kéo trong this jsfiddle. Trong trình xử lý sự kiện dragstart, URL hình ảnh được truy lục từ phần tử bị ẩn:

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

nhưng có thể mã hóa cứng. Nếu bạn thích, bạn có thể đặt thuộc tính src của hình ảnh ẩn động khi trang được tải. Khi thử nghiệm trong jsfiddle, bạn có thể thay đổi tên hình ảnh ma (ví dụ: 225x225) trước khi chạy lại, để đảm bảo rằng hình ảnh không được lưu trong bộ nhớ cache.


Theo nhận xét của bạn, tải trước hình ảnh không phải là một tùy chọn. Và bạn đang sử dụng cùng một URL hình ảnh cho hình ảnh ma đang kéo. Trong trường hợp đó, bạn có thể kiểm tra this page để xem có tùy chọn nào ngăn cản tải lại hình ảnh hay không.

Bạn cũng có thể bắt buộc vẽ lại bố cục sau khi thêm điều khiển div vào body trong trình xử lý sự kiện dragstart. Điều này có thể đạt được bằng cách gọi div.offsetHeight:

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

Đã có thể tái tạo sự cố được mô tả tại OP tại firefox 53 tại * nix. – guest271314

+0

Xin chào và cảm ơn câu trả lời. Tôi đã thêm phần 'Cập nhật' cho câu hỏi với ví dụ về những gì tôi đang nhận được. Thật không may trước khi bộ nhớ đệm hình ảnh không phải là một lựa chọn cho tôi. – Rasalom

+0

Nếu ảnh chụp màn hình thu được bằng [jsfiddle] (https://jsfiddle.net/etseq5cg/5/), chúng tôi phải có các cấu hình khác nhau. Bạn đang sử dụng hệ điều hành nào? Và phiên bản nào của Firefox? Kể từ khi hình ảnh đã được hiển thị, nó sẽ có sẵn. Bạn có plugin RealPlayer không (dường như có thể gây ra sự cố khi tải lại hình ảnh) (https://support.mozilla.org/en-US/kb/fix-problems-images-not-show#w_images-load-the -lần đầu-nhưng-không-sau))? – ConnorsFan

1

Tại css thiết .parent giả lớp :hover.elementbackground-url("/path/to/image") để lấy hình ảnh ở :hover của phần tử cha <img class="element" src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/Sample.jpg" draggable="true" />. Tại dragstart bộ sự kiện div.className đến "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/

Các vấn đề liên quan