Javascript / jQuery kullanarak bir görüntünün yüklenip yüklenmediğini nasıl belirleyebilirim?


84

Büyük resmi, kullanıcının tarayıcı penceresine sığacak şekilde yeniden boyutlandırmak için bazı Javascript yazıyorum. (Maalesef kaynak görüntülerin boyutunu kontrol etmiyorum.)

Yani HTML'de böyle bir şey olacaktır:

<img id="photo"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

srcBir imgetiketteki görselin indirilip indirilmediğini belirlememin bir yolu var mı ?

Buna ihtiyacım var çünkü $(document).ready()tarayıcı resmi yüklemeden önce çalıştırılırsa bir sorunla karşılaşıyorum . $("#photo").width()ve $("#photo").height()yer tutucunun boyutunu (alternatif metin) döndürür. Benim durumumda bu 134 x 20 gibi bir şey.

Şu anda sadece fotoğrafın yüksekliğinin 150'den az olup olmadığını kontrol ediyorum ve eğer öyleyse sadece alternatif metin olduğunu varsayıyorum. Ancak bu oldukça zor ve bir fotoğraf 150 pikselden daha azsa (benim özel durumumda büyük olasılıkla değil) veya alternatif metin 150 pikselden daha yüksekse (muhtemelen küçük bir tarayıcı penceresinde olabilir) .


Düzenle: Kodu görmek isteyen herkes için:

$(function()
{
  var REAL_WIDTH = $("#photo").width();
  var REAL_HEIGHT = $("#photo").height();

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(REAL_HEIGHT < 150)
    {
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
      if(REAL_HEIGHT < 150)
      {
        //image not loaded.. try again in a quarter-second
        setTimeout(adjust_photo_size, 250);
        return;
      }
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});

Güncelleme : Öneriler için teşekkürler. Etkinlik için bir geri arama ayarlarsam etkinliğin tetiklenmemesi riski vardır $("#photo").load, bu nedenle doğrudan resim etiketi üzerinde bir onLoad etkinliği tanımladım. Kayıt için, işte son bulduğum kod:

<img id="photo"
     onload="photoLoaded();"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

Sonra Javascript'te:

//This must be outside $() because it may get called first
var isPhotoLoaded = false;
function photoLoaded()
{
  isPhotoLoaded = true;
}

$(function()
{
  //Hides scrollbars, so we can resize properly.  Set with JS instead of
  //  CSS so that page doesn't break with JS disabled.
  $("body").css("overflow", "hidden");

  var REAL_WIDTH = -1;
  var REAL_HEIGHT = -1;

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(!isPhotoLoaded)
    {
      //image not loaded.. try again in a quarter-second
      setTimeout(adjust_photo_size, 250);
      return;
    }
    else if(REAL_WIDTH < 0)
    {
      //first time in this function since photo loaded
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});

1
Bu çok eski ve sen zaten bir cevabı kabul ettin, bu yüzden burada yorum yapacağım. Neden jQuery eklentisini 'onImagesLoad' kullanamıyorsunuz? Ve ayrıca, jQuery ya da değil, ayarlamada max-widthve max-heightJavascript ile resim stilinde sorun nedir? Ardından, maksimum genişlik / yüksekliği görüntü alanı genişliğinin / yüksekliğinin boyutuna ayarlayarak yazmanız gereken TÜM koddan kaçınırsınız.

@ jon.wd7: Bu eklentiye aşina değilim ve 2008'de pek de geri dönmemiş olabilir. max-width ve max-height iki şey: 1) IE'de desteklenmiyorlar (IE 8 konusunda emin değilim); 2) görüntü alanı boyut değiştirirse (pencere yeniden boyutlandırılırsa, vb.), Maksimum genişlik / maksimum yüksekliği değiştirmek için yine de javascript'e ihtiyacım olur (ancak piksel ölçümü yerine "% 100" kullansaydım olmayabilirim)
Kip

Quirksmode.org'a göre kesinlikle IE7 ve IE8'de destekleniyor. Bu yüzden sorununuzdan emin değilim. Ben şahsen bunun gibi küçük şeyler için IE6'yı desteklemiyorum, bu yüzden görecekleri şey JS etkin olmayan bir kullanıcının göreceği şeyle aynı. Ve elbette sıfırlamanız max-widthve max-heightyeniden boyutlandırmanız gerekir. Ama bu oldukça kolay bir iş, .resize()aslında tek satırlık bir kullanım .

3
Tam mülkiyet görüntü yüklenmiş olup olmadığını bilmenin şart yol verir.
BorisOkunskiy

1
@Adrien, Mozilla artık Andoid dışında (bilinmiyor) tüm büyük tarayıcılar tarafından desteklenen tam olarak gösteriyor .
Oliver Bock

Yanıtlar:


33

Ya bir olay dinleyicisi ekleyin ya da görüntünün onload ile kendisini duyurmasını sağlayın. Sonra oradan boyutları bulun.

<img id="photo"
     onload='loaded(this.id)'
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

Spesifikasyona göre, yükleme yalnızca gövde ve çerçeve kümesi öğeleri için bir olaydır; bunun IE'de çalıştığını düşünüyorum, ancak başka tarayıcılarda çalıştığını veya varsayabileceğiniz bir şey olduğunu bilmiyorum ... Bunu birkaç hafta önce araştırıyordum ...
Jason Bunting

IE6, IE7, FF3, Opera9, Safair (Windows Beta) ve Chrome'da (Windows Beta) test ettim.
Kip

9
Mesaj davranışı ve içeriği tavsiye edilmez. Etkinlikler HTML değil Javascript kullanılarak uygulanmalıdır.
dionyziz

10
Onun yorumu, 2008'de takılıp kalmadığımız için alakalı. İnsanlar bunu hala okuyor ve 08'de kötü bir uygulama olarak görülmese bile, insanların şimdi onun iyi bir uygulama olduğunu düşünmelerini istemiyorsunuz.
Spoeken

3
document.querySelector ("img"). addEventListener ("load", function () {alert ('onload!');});
Frank Schwieterman

14

Jquery veri deposunu kullanarak bir 'yüklü' durum tanımlayabilirsiniz.

<img id="myimage" onload="$(this).data('loaded', 'loaded');" src="lolcats.jpg" />

Sonra yapabileceğiniz başka bir yerde:

if ($('#myimage').data('loaded')) {
    // loaded, so do stuff
}

2
Diğer kitaplıklarla daha iyi uyumluluk için jQuery(this)bunun yerine kullanın $(this)(jquery $ değerine sahip değildir), özellikle html'de JavaScript'iniz olduğunda.
John Magnolia

11

Doğru cevap, event.special.load kullanmaktır

Görüntü tarayıcı önbelleğinden yüklenirse yükleme olayının tetiklenmemesi mümkündür. Bu olasılığı hesaba katmak için, görüntü hazır olduğunda hemen tetiklenen özel bir yükleme olayı kullanabiliriz. event.special.load şu anda bir eklenti olarak mevcuttur.

.Load () üzerindeki dokümanlar için


2
Böyle bir öneriyle cevap ekleyecektim, kodlamadan önce bu cevabı gördüğüme sevindim. Temel olarak, işleyiciyi ayarlamadan önce işleyicilerinizin görüntünün yüklenip yüklenmediğini kontrol etmesi gerekir. Zaten yüklenmişse, geri aramayı hemen başlatın. Ne $.readyyapar. Sadece genişliği kontrol etmeyi önerecektim, ama bunun da sorunları var, bu çözümü gerçekten beğendim.
Juan Mendes

5

Allain'in dediğini yapmak istiyorsunuz, ancak bazen görüntünün dom hazır olmadan önce yüklendiğini unutmayın, bu da yükleme işleyicinizin ateşlemeyeceği anlamına gelir. En iyi yol, Allain'in dediği gibi yapmaktır, ancak yükleme işleyiciyi taktıktan sonra görüntünün src değerini javascript ile ayarlayın. Bu şekilde ateşleneceğini garanti edebilirsiniz.

Erişilebilirlik açısından, siteniz javascript olmayan kişiler için hala çalışacak mı? İmg etiketini doğru src'yi vermek, js'nizi çalıştırmak için dom ready işleyicinizi eklemek isteyebilirsiniz: image src'yi temizleyin (sayfanın titremesini önlemek için ona bir sabit ve css yüksekliği verin), sonra img yükleme işleyicinizi ayarlayın, sonra src'yi doğru dosyaya sıfırlayın. Bu şekilde tüm üsleri kapsarsınız :)


Site hala Javascript kullanmayan kişiler için çalışıyor, sadece tüm görseli görmek için kaydırmaları gerekiyor.
Kip

4

Orijinal sorunuza yapılan son yorumlardan birine göre

$(function() {

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()  {
    if (!$("#photo").get(0).complete) {
       $("#photo").load(function() {
          adjust_photo_size();
       });
    } else {
      ... 
    }
});

Uyarı Bu yanıt ie8 ve daha düşük sürümlerde ciddi bir döngüye neden olabilir, çünkü img.complete tarayıcı tarafından her zaman doğru şekilde ayarlanmamaktadır. İe8'i desteklemeniz gerekiyorsa, görüntünün yüklendiğini hatırlamak için bir bayrak kullanın.


Tut şunu. Bu yanıt ie8 ve daha düşük sürümlerde ciddi bir döngüye neden olabilir, çünkü img.complete tarayıcı tarafından her zaman doğru şekilde ayarlanmamaktadır. İe8'i desteklemeniz gerekiyorsa, görüntünün yüklendiğini hatırlamak için bir bayrak kullanın.
commonpike

2

Şöyle bir şey dene:

$("#photo").load(function() {
    alert("Hello from Image");
});

6
Teşekkürler. Bununla birlikte, görüntünün bu gerçekleşmeden önce zaten yüklenmiş olma ihtimali vardır, bu durumda yükleme olayı tetiklenmeyecektir.
Kip

Bu etkinliği resim etiketinden hemen sonra ayarlayan bir komut dosyası etiketi nasıl olur? Hazır kullanmanın nedeni, tüm belgenin yüklendiğinden emin olmaktır, bu durumda bu gereksiz, değil mi?
Jason Goemaat

2

Bir öğenin görüntülerinin yüklenip yüklenmediğini kontrol etmek için tarayıcılar arası uyumlu bir yöntem sağlayan "imagesLoaded" adlı bir jQuery eklentisi var.

Web sitesi: https://github.com/desandro/imagesloaded/

İçinde çok sayıda görüntü bulunan bir kap için kullanım:

$('container').imagesLoaded(function(){
 console.log("I loaded!");
})

Eklenti harika:

  1. içinde birçok resim bulunan bir kabı kontrol etmek için çalışır
  2. bir img'nin yüklenip yüklenmediğini kontrol etmek için çalışır

sadece yüklü img'yi kontrol etmek için küçültülmüş 5KB ağır görünüyor. Daha kolay bir yöntem mevcut olmalı ...
cdalxndr

1

Bununla ilgili herhangi bir yorumunuz var mı?

...

doShow = function(){
  if($('#img_id').attr('complete')){
    alert('Image is loaded!');
  } else {
    window.setTimeout('doShow()',100);
  }
};

$('#img_id').attr('src','image.jpg');

doShow();

...

Her yerde çalışıyor gibi görünüyor ...


kullanmak kötü bir uygulamasetTimeout
cdalxndr

1

JQuerys Ertelenmiş Nesne kullanarak bir görüntü yüklemek için bir jQuery işlevi oluşturdum , bu da yükleme / hata olayına tepki vermeyi çok kolaylaştırıyor:

$.fn.extend({
    loadImg: function(url, timeout) {
        // init deferred object
        var defer = $.Deferred(),
            $img = this,
            img = $img.get(0),
            timer = null;

        // define load and error events BEFORE setting the src
        // otherwise IE might fire the event before listening to it
        $img.load(function(e) {
            var that = this;
            // defer this check in order to let IE catch the right image size
            window.setTimeout(function() {
                // make sure the width and height are > 0
                ((that.width > 0 && that.height > 0) ? 
                    defer.resolveWith : 
                    defer.rejectWith)($img);
            }, 1);
        }).error(function(e) {
            defer.rejectWith($img);
        });

        // start loading the image
        img.src = url;

        // check if it's already in the cache
        if (img.complete) {
            defer.resolveWith($img);
        } else if (0 !== timeout) {
            // add a timeout, by default 15 seconds
            timer = window.setTimeout(function() {
                defer.rejectWith($img);
            }, timeout || 15000);
        }

        // return the promise of the deferred object
        return defer.promise().always(function() {
            // stop the timeout timer
            window.clearTimeout(timer);
            timer = null;
            // unbind the load and error event
            this.off("load error");
        });
    }
});

Kullanım:

var image = $('<img />').loadImg('http://www.google.com/intl/en_com/images/srpr/logo3w.png')
.done(function() {
    alert('image loaded');
    $('body').append(this);
}).fail(function(){
    alert('image failed');
});

Çalışırken görün: http://jsfiddle.net/roberkules/AdWZj/


Harika gibi. Kodunuzun img.onload ve img.onerror yerine ne zaman tercih edildiğine dair kesin bir örnek verebilir misiniz? Kodunuz yalnızca, henüz haberdar olduğum jQuery hata işlemenin görünen eksikliklerini ele almak mı? Dosya uzantısı yoksa bu hata IE'de tetiklenmiyor mu?
mplungjan

ilginç fikir. görüntünün ne zaman yapıldığını bilmek çok kolay. Ama ya görüntü yüklenemezse. Görüntünün yüklenmesinin başarısız olup olmadığını öğrenmenin bir yolunu arıyordum. ve bana yüklerken zaman aşımı fikrini verdin. Bunun için +1
meşe

1
@oak zaman aşımı yalnızca bir geri dönüş olmalıdır. çoğu tarayıcı, errortarafından işlenen bir olayı tetiklemelidir .error(function(e) { defer.rejectWith($img); }). JsFiddle'a bakarsanız, http://www.google.com/abc.png not foundmetnin hemen sonuçlar bölmesinde gösterildiğini göreceksiniz (hata olayı başladığı için zaman aşımını beklemiyorsunuz)
roberkules

jquery'nin .error'u yükseltmesi için iki şeyin olması gerektiğini unutmayın 1. tutamaç, ancak hatadan önce ayarlanmalıdır. 2. .error sadece http protokolünü işler ve file: // ile ilgilenmez, böylece orada hata almazsınız ..
oak

benim kod örneğimde, başarı / hata işleyicisi, src özniteliğini tam olarak bu nedenle atamadan önce ayarlanır. hakkında file://kısıtlama - Ben dosya protokolünü kullanarak bağlantı görüntülere ihtiyacım olmadı ve ben çok ihtiyaç olduğunu sanmıyorum.
roberkules

1

Bu işlev, ölçülebilir boyutlara dayalı olarak bir görüntünün yüklenip yüklenmediğini kontrol eder. Bu teknik, betiğiniz bazı görüntüler yüklendikten sonra çalıştırılıyorsa yararlıdır.

imageLoaded = function(node) {
    var w = 'undefined' != typeof node.clientWidth ? node.clientWidth : node.offsetWidth;
    var h = 'undefined' != typeof node.clientHeight ? node.clientHeight : node.offsetHeight;
    return w+h > 0 ? true : false;
};

Bu çözümün görüntüde kenar boşluğu veya dolgu olmamasını ve boş bir dizenin alternatif metninin sağlanmasını gerektirebileceğini keşfettim. Çoğu durumda, amaçlandığı gibi çalışır. Yalnızca yüklenmemiş görüntünün boyutu sıfırdan büyükse başarısız olur.
Ralph Ritoch

1

Bunun benim için çalıştığını buldum

document.querySelector("img").addEventListener("load", function() { alert('onload!'); });

Kabul edilen cevaba yorum yapan Frank Schwieterman'a kredi verilir. Bunu buraya koymak zorunda kaldım, çok değerli ...


0

Birkaç görüntü yüklediği bir sayfa geliştirdik ve ardından diğer işlevleri yalnızca görüntü yüklendikten sonra gerçekleştirdik. Çok fazla trafik oluşturan yoğun bir siteydi. Aşağıdaki basit komut dosyasının neredeyse tüm tarayıcılarda çalıştığı görülüyor:

$(elem).onload = function() {
    doSomething();
}

AMA BU IE9 İÇİN POTANSİYEL BİR SORUN!

Sorunları bildirdiğimiz TEK tarayıcı IE9'dur. Şaşırmadık mı? Görünüşe göre, sorunu çözmenin en iyi yolu, onload işlevi tanımlandıktan SONRA görüntüye src atamamaktır, örneğin:

$(elem).onload = function() {
    doSomething();
}
$(elem).attr('src','theimage.png');

Görünüşe göre IE 9 bazen onload herhangi bir nedenle olayı atmayacak. Bu sayfadaki diğer çözümler (örneğin Evan Carroll'dan gelen gibi) hala işe yaramadı. Mantıksal olarak, bu, yükleme durumunun zaten başarılı olup olmadığını ve işlevi tetikleyip tetiklemediğini kontrol etti ve değilse, yükleme işleyicisini ayarlayın, ancak bunu yaptığınızda bile, görüntünün bu iki js satırı arasında yüklenebileceğini test ederken gösterdik. ilk satıra yüklenmemiş görünüyor ve ardından yükleme işleyicisi ayarlanmadan önce yükleniyor.

İstediğinizi elde etmenin en iyi yolunun, siz ayarlayana kadar görüntünün src'sini tanımlamamak olduğunu gördük. onload olay tetikleyicisini .

Kısa bir süre önce IE8'i desteklemeyi bıraktık, bu yüzden IE9'dan önceki sürümler için konuşamıyorum, aksi halde sitede kullanılan diğer tüm tarayıcılar - IE10 ve 11 ile Firefox, Chrome, Opera, Safari ve her neyse Kullanıcıların kullandığı mobil tarayıcı - işleyiciyi srcatamadan önce ayarlamak onloadbir sorun bile değildi.


0

Tamamen saf bir CSS çözümü önerebilir miyim?

Görüntüyü içinde göstermek istediğiniz bir Div'e sahip olmanız yeterli. Görüntüyü arka plan olarak ayarlayın. Daha sonra mülke sahip olun background-size: coverveya background-size: containnasıl istediğinize bağlı olarak.

cover küçük kenarlar kutuyu kaplayana kadar resmi kırpacaktır. containtüm resmi div içinde tutacak ve size yanlarda boşluk bırakacaktır.

Aşağıdaki parçacığı kontrol edin.

div {
  height: 300px;
  width: 300px;
  border: 3px dashed grey;
  background-position: center;
  background-repeat: no-repeat;
}

.cover-image {
  background-size: cover;
}

.contain-image {
  background-size: contain;
}
<div class="cover-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
<br/>
<div class="contain-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>


0

Bu basit çözümün benim için en iyisi olduğunu görüyorum:

        function setEqualHeight(a, b) {
            if (!$(a).height()) {
                return window.setTimeout(function(){ setEqualHeight(a, b); }, 1000);
            }
            $(b).height($(a).height());
        }

        $(document).ready(function() {
            setEqualHeight('#image', '#description');
            $(window).resize(function(){setEqualHeight('#image', '#description')});
        });
    </script>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.