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

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

Ответ 1

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

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 и naturalWidth HTML5.

Ответ 2

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

Например:

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

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

Ответ 3


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 и получите ширину созданного объекта.

Ответ 4

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

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

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

Ответ 5

В принятом ответе много обсуждений о проблеме, когда событие 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, но вы можете удалить их в соответствии с ответом Xavi или клонировать изображение.)

Ответ 6

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

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

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

  alert( pic.width() );
  alert( pic.height() );
});

Ответ 7

Вы можете программно получить изображение и проверить размеры с помощью 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';

Ответ 8

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

(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 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"...

Ответ 9

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

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

Ответ 10

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

Ответ 11

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

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

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

Ответ 12

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

Решение Luke Smith здесь.

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

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

Ответ 13

$("#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/

Ответ 14

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

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

Вот мой код с помощью 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);

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

Ответ 16

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

Ответ 17

Чтобы добавить к ответу Xavi, Paul Irish github David Desandro gitgub предлагает функцию imagesLoaded(), которая работает на тех же принципах и обходит проблему некоторых кешированных изображений браузера, не запуская событие .load() (с умным оригиналом_src → data_uri → original_src).

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

Ответ 18

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

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.");
    }
  }
}

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

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

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

Ответ 19

Я сделал некоторую функцию утилиты обхода, используя плагин jQuery imagesLoaded: 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)

Ответ 20

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

  • установить симуляции изображения в начальный

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

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

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

Ответ 21

Пожалуйста, используйте нижеприведенный код для получения высоты и ширины

var VarHeight = imgLogo.clientHeight;
var VarWidth = imgLogo.clientWidth;

Пожалуйста, проверьте полную демонстрационную ссылку

DEMO

Ответ 22

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

$(this).clone().removeAttr("width").attr("width");
$(this).clone().removeAttr("height").attr("height);

Ответ 23

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

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

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

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

Ответ 24

Я использую другой подход, просто сделайте вызов 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);

?>

Ответ 25

Другое предложение - использовать imagesLoaded plugin.

$("img").imagesLoaded(function(){
alert( $(this).width() );
alert( $(this).height() );
});

Ответ 26

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

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;

Ура!

Ответ 27

$(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

Ответ 28

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

Ответ 29

Наткнулся на эту тему, пытаясь найти ответ по моему собственному вопросу. Я пытался получить ширину/высоту изображения в функции ПОСЛЕ загрузчика и продолжал приходить с 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);
}

Ответ 30

Проверьте этот репозиторий в 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>