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

279

Я создаю плагин 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.

Фрэнк Баннистер
источник
4
Принятый ответ использует событие загрузки изображения. Имеет смысл, но оказывается ненадежным решением в ситуациях, когда изображения могут быть кэшированы (к моему ужасу).
Носредна,
Мой взгляд на это может помочь вам, протестирован в последней версии Webkit. stackoverflow.com/questions/318630/…
xmarcos
5
@Nosredna, вас может заинтересовать функция imagesLoaded, которая будет срабатывать, даже если изображения были кэшированы.
Бежонби
7
Правильный ответ на этот вопрос - просто использовать свойства naturalWidth и naturalHeight. Никаких взломов не требуется.
Дэвид Джонстон,
Вы также можете делать то же, что и при загрузке окна, вместо того, чтобы готовый документ
user1380540

Ответы:

357

Браузеры Webkit устанавливают свойство высоты и ширины после загрузки изображения. Вместо использования тайм-аутов я бы рекомендовал использовать событие загрузки изображения. Вот быстрый пример:

var img = $("img")[0]; // Get my img elem
var pic_real_width, pic_real_height;
$("<img/>") // Make in memory copy of image to avoid css issues
    .attr("src", $(img).attr("src"))
    .load(function() {
        pic_real_width = this.width;   // Note: $(this).width() will not
        pic_real_height = this.height; // work for in memory images.
    });

Чтобы избежать какого-либо влияния CSS на размеры изображения, приведенный выше код создает копию изображения в памяти. Это очень умное решение, предложенное FDisk .

Вы также можете использовать атрибуты naturalHeightи naturalWidthHTML5.

Хави
источник
5
Это умно, не знал, что вы можете сделать $ (img) .load ();
SeanJA
3
Кроме того , widthи heightвам , вероятно , следует также удалить min-width, min-height, max-widthи max-heightкак они могут также влиять на размеры изображения.
10
5
Решение FDisk очень умное. К сожалению, решение, которое он написал, будет работать только в том случае, если изображение кэшировано или страница уже загружена. Если изображение не кэшируется или этот код вызывается ранее window.onload, высота / ширина 0 может быть возвращена. В любом случае, я интегрировал идею FDisk в решение выше.
Хави
5
когда я пытаюсь console.log (pic_real_height), я получаю неопределенный каждый раз. хром, FF, IE9.
helgatheviking
10
Проблема, которая может у вас возникнуть, заключается в том, что load()она будет выполняться асинхронно, поэтому, если вы хотите получить доступ widthи height- они могут быть еще не установлены. Вместо этого делайте «магию» в load()себе!
daGrevis
286

Используйте naturalHeightи naturalWidthатрибуты из HTML5 .

Например:

var h = document.querySelector('img').naturalHeight;

Работает в IE9 +, Chrome, Firefox, Safari и Opera ( статистика ).

Сандстр
источник
3
@DavidJohnstone Пример их использования может помочь. Но я согласен, определенно заслуживает того, чтобы быть выше.
Стивен
5
Похоже, что это не работает в последней версии FireFox (30.0), если изображение уже не существует в кэше.
Джоэл Кинзел
1
Я согласен с Дэвидом Джонстоном. Это отличные новости.
jchwebdev
Обратите внимание, что вам все еще нужно ждать загрузки изображения
Jesús Carrera
Нет, clientHeight / clientWidth явно не делают то, что задает вопрос. Он должен возвращать высоту и ширину изображения, а не высоту и ширину изображения, как оно выглядит на странице. naturalWidth и naturalHeight верны.
Йерун ван ден Брук
61


function getOriginalWidthOfImg(img_element) {
    var t = new Image();
    t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src;
    return t.width;
}

Вам не нужно удалять стиль из изображения или атрибутов размеров изображения. Просто создайте элемент с помощью JavaScript и получите ширину созданного объекта.

FDisk
источник
3
Спустя несколько месяцев клонирование изображения с помощью jquery (с использованием последней версии Chrome) и получение его свойств всегда возвращает 0x0. Пока это единственное работающее решение (проверили все остальные на этой странице). Перед возвратом я установил t = тоже ноль.
Omiod
1
FDisk не предлагает клонировать изображение с помощью jQuery. Он предлагает создать новый Imageобъект, а затем посмотреть на его widthсобственность. Это простой, элегантный подход. FDisk, у тебя есть мой голос. :)
Дэвид Чамберс
3
Это очень умный способ избежать проблем с CSS. К сожалению, решение, как написано выше, будет работать, только если изображение кэшировано или уже завершило загрузку. Если изображение не кэшировано или этот код вызывается ранее window.onload, может быть возвращена ширина 0.
Хави
1
Я использую этот подход на веб-сайте для мобильных телефонов в галерее изображений. Изображения большего размера, чем разрешение, отображаются со 100% в CSS и меньше в исходных размерах.
FDisk
1
Как упоминал Хави, это не работает в IE8 и иногда зависит от кэширования изображений. Так что я связал его с этим подходом, и он отлично работает: сначала свяжите событие загрузки, а затем назначьте объект изображения его источником stackoverflow.com/questions/4921712/…
Кевин С.
16

Основная проблема заключается в том, что браузеры WebKit (Safari и Chrome) загружают информацию JavaScript и CSS параллельно. Таким образом, JavaScript может выполняться до того, как будут вычислены эффекты стиля CSS, возвращая неправильный ответ. В jQuery я обнаружил, что решение состоит в том, чтобы ждать, пока document.readyState == 'complete', .eg,

jQuery(document).ready(function(){
  if (jQuery.browser.safari && document.readyState != "complete"){
    //console.info('ready...');
    setTimeout( arguments.callee, 100 );
    return;
  } 
  ... (rest of function) 

Что касается ширины и высоты ... в зависимости от того, что вы делаете, вы можете захотеть offsetWidth и offsetHeight, которые включают в себя такие вещи, как границы и отступы.

Cugel
источник
Да, это причина. Лучшее решение - использовать load-событие jQuery.
Фрэнк Баннистер
6
$(window).load(function(){ ... });помогло в моем случае
колыпто
16

В принятом ответе много говорится о проблеме, при которой onloadсобытие не срабатывает, если изображение загружается из кэша WebKit.

В моем случае onloadсрабатывает кэширование изображений, но высота и ширина по-прежнему равны 0. Простой setTimeoutвопрос решил для меня:

$("img").one("load", function(){
    var img = this;
    setTimeout(function(){
        // do something based on img.width and/or img.height
    }, 0);
});

Я не могу сказать, почему onloadсобытие запускается, даже когда изображение загружается из кэша (улучшение jQuery 1.4 / 1.5?), Но если вы все еще испытываете эту проблему, возможно, сочетание моего ответа иvar src = img.src; img.src = ""; img.src = src; техники работай.

(Обратите внимание, что для моих целей меня не интересуют заранее определенные измерения, как в атрибутах изображения, так и в стилях CSS - но вы можете удалить их, как указано в ответе Хави. Или клонировать изображение.)

JKS
источник
У меня была эта проблема с IE7 и IE8. setTimeout () работал для меня в этих браузерах. Спасибо!
Василе Томояга
11

это работает для меня (сафари 3.2), стреляя изнутри window.onloadсобытия:

$(window).load(function() {
  var pic = $('img');

  pic.removeAttr("width"); 
  pic.removeAttr("height");

  alert( pic.width() );
  alert( pic.height() );
});
Оуэн
источник
Да! Не работает с $ (document) .ready (function () {}); Спасибо! Необходимо полностью загрузить изображение, прежде чем оно сможет прочитать его. Конечно.
Фрэнк Баннистер
8

Вы можете программно получить изображение и проверить размеры, используя Javascript без необходимости связываться с DOM.

var img = new Image();
img.onload = function() {
  console.log(this.width + 'x' + this.height);
}
img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
Еко
источник
2
Это лучшее решение! Это работает, даже если изображение предварительно не загружено или не кэшировано.
marlar
7

А как насчет image.naturalHeightи image.naturalWidthсвойства?

Кажется, хорошо работает довольно много версий в Chrome, Safari и Firefox, но не совсем в IE8 или даже IE9.

Эндрю Маккензи
источник
это не работает в моем случае. давая мне NaN взамен
saadk
6

Jquery имеет два свойства, называемых naturalWidth и naturalHeight, которые вы можете использовать таким образом.

$('.my-img')[0].naturalWidth 
$('.my-img')[0].naturalHeight

Где my-img - это имя класса, используемое для выбора моего изображения.

Самуэль Сантос
источник
2
Это не методы jQuery. naturalWidth(и высота) являются свойствами объекта элемента изображения. developer.mozilla.org/en/docs/Web/API/HTMLImageElement
sandstrom
5

Как мы получаем правильные реальные размеры без мерцания реального изображения:

(function( $ ){
   $.fn.getDimensions=function(){
         alert("First example:This works only for HTML code without CSS width/height definition.");
         w=$(this, 'img')[0].width;
         h=$(this, 'img')[0].height;

         alert("This is a width/height on your monitor: " + $(this, 'img')[0].width+"/"+$(this, 'img')[0].height);

         //This is bad practice - it shows on your monitor
         $(this, 'img')[0].removeAttribute( "width" );
         $(this, 'img')[0].removeAttribute( "height" );
         alert("This is a bad effect of view after attributes removing, but we get right dimensions: "+  $(this, 'img')[0].width+"/"+$(this, 'img')[0].height);
         //I'am going to repare it
         $(this, 'img')[0].width=w;
         $(this, 'img')[0].height=h;
         //This is a good practice - it doesn't show on your monitor
         ku=$(this, 'img').clone(); //We will work with a clone
         ku.attr( "id","mnbv1lk87jhy0utrd" );//Markup clone for a final removing
         ku[0].removeAttribute( "width" );
         ku[0].removeAttribute( "height" );
         //Now we still get 0
         alert("There are still 0 before a clone appending to document: "+ $(ku)[0].width+"/"+$(ku)[0].height);
         //Hide a clone
         ku.css({"visibility" : "hidden",'position':'absolute','left':'-9999px'}); 
         //A clone appending
         $(document.body).append (ku[0]);
         alert("We get right dimensions: "+ $(ku)[0].width+"/"+$(ku)[0].height);
         //Remove a clone
         $("#mnbv1lk87jhy0utrd").remove();

         //But a next resolution is the best of all. It works in case of CSS definition of dimensions as well.
         alert("But if you want to read real dimensions for image with CSS class definition outside of img element, you can't do it with a clone of image. Clone method is working with CSS dimensions, a clone has dimensions as well as in CSS class. That's why you have to work with a new img element.");
         imgcopy=$('<img src="'+ $(this, 'img').attr('src') +'" />');//new object 
         imgcopy.attr( "id","mnbv1lk87jhy0aaa" );//Markup for a final removing
         imgcopy.css({"visibility" : "hidden",'position':'absolute','left':'-9999px'});//hide copy 
         $(document.body).append (imgcopy);//append to document 
         alert("We get right dimensions: "+ imgcopy.width()+"/"+imgcopy.height());
         $("#mnbv1lk87jhy0aaa").remove();


   }
})( jQuery );

$(document).ready(function(){

   $("img.toreaddimensions").click(function(){$(this).getDimensions();});
});

Работает с <img class = "toreaddimensions" ...

Лиса
источник
3

Как было сказано ранее, ответ Xavi не будет работать, если изображения находятся в кеше. Эта проблема связана с тем, что webkit не запускает событие load для кэшированных изображений, поэтому, если атрибуты 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 , вам придется проанализировать его и добавить дополнительный параметр для очистки кэша.

xmarcos
источник
1
Первый блок кода просто получает размеры элемента в загруженном DOM, а не самого изображения ...
BasTaller
1
Это самое быстрое и эффективное решение. Нет плагин, нет трюк! Я собираюсь опубликовать аналогичный ответ, но нашел ваш.
vantrung -cuncon
2

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

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

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

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

Nosredna
источник
Вторая ссылка в ответе мертва.
Панг
2
$("#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/

Джером Ягла
источник
2

Моя ситуация, вероятно, немного отличается. Я динамически изменяю 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);

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

Duane Comeaux
источник
1

Недавно мне нужно было найти ширину и высоту для установки размера по умолчанию для .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

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

SDemonUA
источник
1

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

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

RobW
источник
1
Вы можете найти обновленную версию imagesLoadedфункции здесь: github.com/desandro/imagesloaded
bejonbee,
Да, Дэвид Десандро сейчас принимает эту функцию. Спасибо, что напомнили мне @somethingkindawierd, обновил мой ответ.
RobW
1

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

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/

CheeseSucker
источник
1

Я сделал несколько вспомогательных функций, используя плагин 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

Если изображение уже используется, вы должны:

  1. установить исходные размеры изображения

    image.css ('width', 'initial'); image.css ('height', 'initial');

  2. получить размеры

    var originalWidth = $ (this) .width (); var originalHeight = $ (this) .height ();

Себастьян Рохас
источник
1

Вы можете использовать свойства 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 и ниже.

Jair Reina
источник
Да, не больше IE8: D
Jair Reina
0

Я проверил ответ Дио, и он прекрасно работает для меня.

$('#image').fadeIn(10,function () {var tmpW = $(this).width(); var tmpH = $(this).height(); });

Убедитесь, что вы вызываете все свои функции так же. этот дескриптор с размером изображения в функции recaller функции fadeIn ().

Спасибо за это.

drublic
источник
0

Я использую другой подход, просто делаю Ajax-вызов на сервер, чтобы получить размер изображения, когда объект изображения используется.

//make json call to server to get image size
$.getJSON("http://server/getimagesize.php",
{"src":url},
SetImageWidth
);

//callback function
function SetImageWidth(data) {

    var wrap = $("div#image_gallery #image_wrap");

    //remove height
     wrap.find("img").removeAttr('height');
    //remove height
     wrap.find("img").removeAttr('width');

    //set image width
    if (data.width > 635) {
        wrap.find("img").width(635);
    }
    else {
         wrap.find("img").width(data.width);
    }
}

и, конечно, код на стороне сервера:

<?php

$image_width = 0;
$image_height = 0;

if (isset ($_REQUEST['src']) && is_file($_SERVER['DOCUMENT_ROOT'] . $_REQUEST['src'])) {

    $imageinfo = getimagesize($_SERVER['DOCUMENT_ROOT'].$_REQUEST['src']);
    if ($imageinfo) {
       $image_width=  $imageinfo[0];
       $image_height= $imageinfo[1];
    }
}

$arr = array ('width'=>$image_width,'height'=>$image_height);

echo json_encode($arr);

?>
damijanc
источник
1
Это не очень хорошее решение, и оно займет больше времени, чем любое другое решение из-за загрузки AJAX.
halfpastfour.am
0

Это работает кросс-браузер

var img = new Image();
$(img).bind('load error', function(e)
{
    $.data(img, 'dimensions', { 'width': img.width, 'height': img.height });                    
});
img.src = imgs[i];              

получить размеры с помощью

$(this).data('dimensions').width;
$(this).data('dimensions').height;

Ура!

foxybagga
источник
0

Еще одно предложение - использовать плагин imagesLoaded .

$("img").imagesLoaded(function(){
alert( $(this).width() );
alert( $(this).height() );
});
Gadelkareem
источник
0
$(document).ready(function(){
                            var image = $("#fix_img");
                            var w = image.width();
                            var h = image.height();
                            var mr = 274/200;
                            var ir = w/h
                            if(ir > mr){
                                image.height(200);
                                image.width(200*ir);
                            } else{
                                image.width(274);
                                image.height(274/ir);
                            }
                        }); 

// Этот код помогает показать изображение с размером 200 * 274

Eranda
источник
0

Вот кросс-браузерное решение, которое запускает событие при загрузке выбранных изображений: http://desandro.github.io/imagesloaded/ вы можете посмотреть высоту и ширину в функции imagesLoaded ().

Пол Мейсон
источник
0

Наткнулся на эту ветку, пытаясь найти ответ на свой вопрос. Я пытался определить ширину / высоту изображения в функции ПОСЛЕ загрузчика и продолжал выдавать 0. Я чувствую, что это может быть то, что вы ищете, хотя, как это работает для меня:

tempObject.image = $('<img />').attr({ 'src':"images/prod-" + tempObject.id + ".png", load:preloader });
xmlProjectInfo.push(tempObject);

function preloader() {
    imagesLoaded++;
    if (imagesLoaded >= itemsToLoad) { //itemsToLoad gets set elsewhere in code
        DetachEvent(this, 'load', preloader); //function that removes event listener
        drawItems();
    }   
}

function drawItems() {
    for(var i = 1; i <= xmlProjectInfo.length; i++)
        alert(xmlProjectInfo[i - 1].image[0].width);
}
Стивен Синовски
источник
0

Проверьте этот репозиторий в github!

Отличный пример для проверки ширины и высоты с использованием Javascript

https://github.com/AzizAK/ImageRealSize

--- Отредактировано запрашивается из некоторых комментариев ..

Javascript код:

 function CheckImageSize(){
var image = document.getElementById("Image").files[0];
           createReader(image, function (w, h) {

                alert("Width is: " + w + " And Height is: "+h);
});            
}


  function  createReader(file, whenReady) {
        var reader = new FileReader;
        reader.onload = function (evt) {
            var image = new Image();
            image.onload = function (evt) {
                var width = this.width;
                var height = this.height;
                if (whenReady) whenReady(width, height);
            };
            image.src = evt.target.result;
        };
        reader.readAsDataURL(file);
    }

и HTML-код:

<html>
<head>
<title>Image Real Size</title>
<script src="ImageSize.js"></script>
</head>
<body>
<input type="file" id="Image"/>
<input type="button" value="Find the dimensions" onclick="CheckImageSize()"/>
</body>
<html>
Абдулазиз Альхараши
источник
если возможно, вы также можете добавить несколько строк кода здесь. так как ссылки могут измениться через Timw
Tejus Prasad
-1

Для функций, в которых вы не хотите изменять исходное расположение или изображение.

$(this).clone().removeAttr("width").attr("width");
$(this).clone().removeAttr("height").attr("height);
Дэвин
источник
1
Это абсолютно не работает. Это возвратит неопределенное для обоих
Крис Синелли