Wie kann ich überprüfen, ob ein Hintergrundbild geladen ist?

154

Ich möchte ein Hintergrundbild für das Body-Tag festlegen und dann einen Code ausführen - wie folgt:

$('body').css('background-image','http://picture.de/image.png').load(function() {
    alert('Background image done loading');
    // This doesn't work
});

Wie kann ich sicherstellen, dass das Hintergrundbild vollständig geladen ist?

Peter
quelle
4
Weisen Sie dem Image()Objekt, das ein onloadEreignis hat, einfach dieselbe URL zu .
Schatten-Assistent ist Ohr für Sie
2
url()
Stellen Sie

Antworten:

274

Versuche dies:

$('<img/>').attr('src', 'http://picture.de/image.png').on('load', function() {
   $(this).remove(); // prevent memory leaks as @benweet suggested
   $('body').css('background-image', 'url(http://picture.de/image.png)');
});

Dadurch wird ein neues Image im Speicher erstellt und mithilfe des Ladeereignisses erkannt, wann der Quellcode geladen wird.

jcubic
quelle
10
Scheint, als würde das Bild ohne Grund zweimal geladen.
HyderA
49
@gAMBOOKa Sie werden einmal geladen, weil sie im Browserspeicher bleiben. Dies ist auch dann der Fall, wenn Sie versteckte Bilder oben auf Ihrer Seite platzieren und dann in CSS festlegen. Die Bilder werden also vor der CSS-Datei heruntergeladen. Dies wird als Vorladen bezeichnet.
Jcubic
4
Ich bin mir nicht sicher, aber ich denke, Sie beziehen sich auf den Cache. Ich glaube nicht, dass es so etwas wie einen Browserspeicher gibt, in dem Assets gespeichert sind. Wenn Sie sich auf den Cache beziehen, denken Sie daran, dass Sie eine zusätzliche HTTP-Anforderung hinzufügen und möglicherweise nicht für alle Clients der Cache aktiviert ist.
HyderA
7
Geben Sie dies auf jeder Seite mit jquery: ein javascript:void($('<img/>').attr('src', 'http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg').load(function() { $('html').css('background-image', 'url(http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg)'); }))und überprüfen Sie die HTTP-Anforderungen in Firebug. Wenn ich eine Flimmern-Seite mit diesem Bild geöffnet habe, das in einem anderen Tab geöffnet wurde, werden keine HTTP-Anforderungen ausgeführt. Dieses Bild wird nur sofort angezeigt. und als ich den Cache löschte und ausführte, gab es eine Anfrage.
Jcubic
26
Ein Vergleich zwischen diesem Test und diese hier zeigt , dass Sie anrufen müssen .remove()auf $('<img/>')Objekt einen Speicherverlust zu vermeiden. Sie sollten beim ersten Test einen stabilen Speicherverbrauch und beim zweiten einen Speicheranstieg feststellen. Nach einigen Stunden auf Chrome 28 dauert der erste Test 80 MB und der zweite 270 MB.
Benweet
23

Ich habe ein jQuery-Plugin namens waitForImages, das erkennen kann, wann Hintergrundbilder heruntergeladen wurden.

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);
Alex
quelle
Dieses Plugin eignet sich auch hervorragend, um den Ladevorgang mithilfe des eachRückrufs anzuzeigen.
Soviut
1
@alex, Wie soll ich jedes Hintergrundbild für jedes Element in einer Klasse überprüfen? Ich habe es versucht, aber es scheint nicht richtig zu sein. $ ('. user_main_photo_thumb'). waitForImages (function () {$ (this) .parents ('. photoThumbFrame'). delay (1000) .slideDown ();}, function (geladen, count, success) {});
Relm
@Relm Du benutzt es nicht richtig. Der zweite Rückruf erfolgt pro Bild. Funktioniert auch delay()nicht so.
Alex
16

Etwas wie das:

var $div = $('div'),
  bg = $div.css('background-image');
  if (bg) {
    var src = bg.replace(/(^url\()|(\)$|[\"\'])/g, ''),
      $img = $('<img>').attr('src', src).on('load', function() {
        // do something, maybe:
        $div.fadeIn();
      });
  }
});
Colin
quelle
hallo ... das scheint zu funktionieren, obwohl ich den bg.replace auf gesetzt habe bg.replace( ... , my_src ). Aber meine Frage ist: Sobald das $ ('<img>') geladen ist, was genau passiert damit <img>... Ich meine, es ist nicht wirklich real - es ist nur ein Dummy-Platzhalter, oder?
dsdsdsdsd
Richtig. Das <img>wird niemals in das DOM eingefügt. Es wird nur verwendet, um den Browser zum Laden der Bilddatei in den Cache zu "täuschen".
Colin
hilfreich, wenn Sie jQuery nicht aufrufen möchten
vwvan
15

Es gibt keine JS-Rückrufe für CSS-Assets.

Adrian Pacala
quelle
3
Danke für die schnelle Antwort. Irgendwelche Ideen für eine Problemumgehungslösung?
Peter
aber es gibt JS-Lösung für diejenigen, die stackoverflow.com/questions/5057990/…
godblessstrawberry
8

reine JS-Lösung, die Preloader hinzufügt, das Hintergrundbild festlegt und es dann zusammen mit dem Ereignis-Listener für die Garbage Collection einrichtet :

Kurzfassung:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector("body");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
    bgElement.style.backgroundImage = `url(${imageUrl})`;
    preloaderImg = null;
});

Ein bisschen länger mit schönem Deckkraftübergang:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector(".bg-lazy");
bgElement.classList.add("bg-loading");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
  bgElement.classList.remove("bg-loading");
  bgElement.style.backgroundImage = `url(${imageUrl})`;
  preloaderImg = null;
});
.bg-lazy {
  height: 100vh;
  width: 100vw;
  transition: opacity 1s ease-out;
}

.bg-loading {
  opacity: 0;
}
<div class="bg-lazy"></div>

Godblessstrawberry
quelle
3
Unterschätzte Lösung.
Tom Thomson
1
@ TomThomson danke Tom, ich fand, dass der Bildübergang nicht richtig funktionierte, behoben
godblessstrawberry
6

Hier ist ein kleines Plugin, das ich erstellt habe, damit Sie genau dies tun können. Es funktioniert auch mit mehreren Hintergrundbildern und mehreren Elementen:

Lesen Sie den Artikel:

http://catmull.uk/code-lab/background-image-loaded/

oder gehen Sie direkt zum Plugin-Code:

http://catmull.uk/downloads/bg-loaded/bg-loaded.js

Fügen Sie einfach das Plugin hinzu und rufen Sie es dann für das Element auf:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded();
</script>

Laden Sie das Plugin herunter und speichern Sie es auf Ihrem eigenen Hosting.

Standardmäßig wird jedem übereinstimmenden Element eine zusätzliche "bg-geladene" Klasse hinzugefügt, sobald der Hintergrund geladen ist. Sie können dies jedoch leicht ändern, indem Sie ihm eine andere Funktion wie die folgende übergeben:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded({
      afterLoaded : function() {
         alert('Background image done loading');
      }
   });
</script>

Hier ist ein Codepen, der die Funktionsweise demonstriert.

http://codepen.io/catmull/pen/Lfcpb

Jon Catmull
quelle
3

Ich habe eine Lösung gefunden, die für mich besser funktioniert und die den Vorteil hat, dass sie mit mehreren Bildern verwendet werden kann (Fall in diesem Beispiel nicht dargestellt).

Aus der Antwort von @ adeneo auf diese Frage :

Wenn Sie ein Element mit einem Hintergrundbild haben, wie dieses

<div id="test" style="background-image: url(link/to/image.png)"><div>

Sie können warten, bis der Hintergrund geladen ist, indem Sie die Bild-URL abrufen und sie mit einem Onload-Handler für ein Bildobjekt in Javascript verwenden

var src = $('#test').css('background-image');
var url = src.match(/\((.*?)\)/)[1].replace(/('|")/g,'');

var img = new Image();
img.onload = function() {
    alert('image loaded');
}
img.src = url;
if (img.complete) img.onload();
Papiersaft
quelle
2

Ich habe einen reinen Javascript-Hack durchgeführt, um dies zu ermöglichen.

<div class="my_background_image" style="background-image: url(broken-image.jpg)">
<img class="image_error" src="broken-image.jpg" onerror="this.parentElement.style.display='none';">
</div>

Oder

onerror="this.parentElement.backgroundImage = "url('image_placeHolder.png')";

CSS:

.image_error {
    display: none;
}
Gino
quelle