Получить реальную ширину и высоту изображения с помощью JavaScript? (в Safari / Chrome) - PullRequest
272 голосов
/ 25 ноября 2008

Я создаю плагин jQuery.

Как получить реальную ширину и высоту изображения с помощью Javascript в Safari?

Следующие работы с Firefox 3, IE7 и Opera 9:

var pic = $("img")

// need to remove these in of case img-element has set width and height
pic.removeAttr("width"); 
pic.removeAttr("height");

var pic_real_width = pic.width();
var pic_real_height = pic.height();

Но в браузерах Webkit, таких как Safari и Google Chrome, значения равны 0.

Ответы [ 30 ]

3 голосов
/ 27 сентября 2011

Как указано выше, ответ Xavi не будет работать, если изображения находятся в кеше. Эта проблема связана с тем, что webkit не запускает событие загрузки для кэшированных изображений, поэтому, если атрибуты width / height явно не заданы в теге img, единственный надежный способ получить изображения - дождаться запуска события window.load .

Событие window.load будет запускать всегда , так что после этого можно без труда получить доступ к ширине / высоте и img.

$(window).load(function(){

   //these all work

   $('img#someId').css('width');
   $('img#someId').width();
   $('img#someId').get(0).style.width;
   $('img#someId').get(0).width; 

});

Если вам нужно получить размер динамически загружаемых изображений, которые могут кэшироваться (загружаться ранее), вы можете использовать метод Xavi плюс строку запроса для запуска обновления кэша. Недостатком является то, что это вызовет другой запрос к серверу, для img, который уже кешируется и должен быть уже доступен. Глупый Webkit.

var pic_real_width   = 0,
    img_src_no_cache = $('img#someId').attr('src') + '?cache=' + Date.now();

$('<img/>').attr('src', img_src_no_cache).load(function(){

   pic_real_width = this.width;

});

ps: если у вас уже есть строка QueryString в img.src, вам придется проанализировать ее и добавить дополнительный параметр для очистки кэша.

2 голосов
/ 06 ноября 2009

Как говорит Люк Смит, загрузка изображения - беспорядок . Это не надежно во всех браузерах. Этот факт причинил мне большую боль. Кэшированное изображение вообще не будет запускать событие в некоторых браузерах, поэтому те, кто сказал «загрузка изображения лучше, чем setTimeout», ошибаются.

Решение Люка Смита здесь .

И есть интересная дискуссия о том, как этот беспорядок может быть обработан в jQuery 1.4.

Я обнаружил, что довольно надежно установить ширину равной 0, а затем подождать, пока свойство "complete" станет истинным, а свойство width станет больше нуля. Вам также следует следить за ошибками.

2 голосов
/ 01 ноября 2012

Моя ситуация, вероятно, немного отличается. Я динамически изменяю src изображения через javascript, и мне нужно было убедиться, что новое изображение имеет размеры, пропорциональные размеру фиксированного контейнера (в фотогалерее). Сначала я просто удалил атрибуты ширины и высоты изображения после его загрузки (через событие загрузки изображения) и сбросил их после расчета предпочтительных размеров. Однако, это не работает в Safari и, возможно, IE (я не проверил это в IE полностью, но изображение даже не показывается, так что ...).

В любом случае, Safari сохраняет размеры предыдущего изображения, поэтому размеры всегда на одно изображение позади. Я предполагаю, что это как-то связано с кешем. Таким образом, самое простое решение - просто клонировать изображение и добавить его в DOM (важно, чтобы оно было добавлено в DOM для получения и высоты). Дайте изображению значение видимости скрытого (не используйте display none, потому что оно не будет работать). После того, как вы получите размеры, удалите клон.

Вот мой код с использованием jQuery:

// Hack for Safari and others
// clone the image and add it to the DOM
// to get the actual width and height
// of the newly loaded image

var cloned, 
    o_width, 
    o_height, 
    src = 'my_image.jpg', 
    img = [some existing image object];

$(img)
.load(function()
{
    $(this).removeAttr('height').removeAttr('width');
    cloned = $(this).clone().css({visibility:'hidden'});
    $('body').append(cloned);
    o_width = cloned.get(0).width; // I prefer to use native javascript for this
    o_height = cloned.get(0).height; // I prefer to use native javascript for this
    cloned.remove();
    $(this).attr({width:o_width, height:o_height});
})
.attr(src:src);

Это решение работает в любом случае.

2 голосов
/ 10 июля 2010
$("#myImg").one("load",function(){
  //do something, like getting image width/height
}).each(function(){
  if(this.complete) $(this).trigger("load");
});

Из комментария Криса: http://api.jquery.com/load-event/

1 голос
/ 25 сентября 2010

Теперь существует плагин jQuery, event.special.load, для работы со случаями, когда событие загрузки для кэшированного изображения не запускается: http://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js

1 голос
/ 17 августа 2011

Чтобы добавить к ответу Хави, Github Пола Айриша Gitgub Дэвида Десандро предлагает функцию imagesLoaded () , которая работает по тем же принципам и обходит проблема в том, что кэшированные изображения некоторых браузеров не запускают событие .load () (с умным переключением original_src -> data_uri -> original_src).

Он широко используется и регулярно обновляется, что делает его самым надежным решением проблемы, IMO.

1 голос
/ 19 апреля 2012

Я сделал несколько вспомогательных функций, используя плагин imagesLoaded jquery: https://github.com/desandro/imagesloaded

            function waitForImageSize(src, func, ctx){
                if(!ctx)ctx = window;
                var img = new Image();
                img.src = src;
                $(img).imagesLoaded($.proxy(function(){
                    var w = this.img.innerWidth||this.img.naturalWidth;
                    var h = this.img.innerHeight||this.img.naturalHeight;
                    this.func.call(this.ctx, w, h, this.img);
                },{img: img, func: func, ctx: ctx}));
            },

Вы можете использовать это, передавая URL, функцию и ее контекст. Функция выполняется после загрузки изображения и возврата созданного изображения, его ширины и высоты.

waitForImageSize("image.png", function(w,h){alert(w+","+h)},this)
1 голос
/ 15 декабря 2017

Вы можете использовать свойства naturalWidth и naturalHeight элемента изображения HTML. (Вот еще информация ).

Вы бы использовали это так:

//you need a reference to the DOM element, not a jQuery object. It would be better if you can use document.getElementByTagsName or ID or any other native method
var pic = $("img")[0];
var pic_real_width = pic.naturalWidth;
var pic_real_height = pic.naturalHeight;

Похоже, что это работает во всех браузерах, кроме IE от версии 8 и ниже.

1 голос
/ 26 января 2011

Недавно мне нужно было найти ширину и высоту для установки размера по умолчанию для .dialog, представляющего график. Решение, которое я использую, было:

 graph= $('<img/>', {"src":'mySRC', id:'graph-img'});
    graph.bind('load', function (){
        wid = graph.attr('width');
        hei = graph.attr('height');

        graph.dialog({ autoOpen: false, title: 'MyGraphTitle', height:hei, width:wid })
    })

Для меня это работает в FF3, Opera 10, IE 8,7,6

P.S. Вы можете найти еще несколько решений, заглянув внутрь некоторых плагинов, таких как LightBox или ColorBox

1 голос
/ 20 февраля 2012

Это работает как для кэшированных, так и для динамически загружаемых изображений.

function LoadImage(imgSrc, callback){
  var image = new Image();
  image.src = imgSrc;
  if (image.complete) {
    callback(image);
    image.onload=function(){};
  } else {
    image.onload = function() {
      callback(image);
      // clear onLoad, IE behaves erratically with animated gifs otherwise
      image.onload=function(){};
    }
    image.onerror = function() {
        alert("Could not load image.");
    }
  }
}

Чтобы использовать этот скрипт:

function AlertImageSize(image) {
  alert("Image size: " + image.width + "x" + image.height);
}
LoadImage("http://example.org/image.png", AlertImageSize);

Демо: http://jsfiddle.net/9543z/2/

...