Obter a largura e a altura reais de uma imagem com JavaScript? (no Safari / Chrome)


278

Estou criando um plugin jQuery.

Como obtenho a largura e a altura reais da imagem com Javascript no Safari?

O seguinte funciona com o Firefox 3, IE7 e 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();

Mas nos navegadores Webkit, como Safari e Google Chrome, os valores são 0.


4
A resposta aceita usa o evento de carregamento de imagem. Faz todo o sentido, mas acaba sendo uma solução não confiável em situações em que as imagens podem ser armazenadas em cache (para minha decepção).
Nosredna

Minha opinião sobre isso pode ajudá-lo, testado no Webkit mais recente. stackoverflow.com/questions/318630/…
xmarcos

5
@Nosredna, você pode estar interessado na função imagesLoaded que será acionada mesmo quando as imagens forem armazenadas em cache.
precisa saber é o seguinte

7
A resposta correta para essa pergunta é simplesmente usar as propriedades naturalWidth e naturalHeight. Não é necessária nenhuma invasão.
David Johnstone

Você também pode fazer exatamente o que você está fazendo na carga janela em vez de documento pronto
user1380540

Respostas:


356

Os navegadores Webkit definem a propriedade height e width após o carregamento da imagem. Em vez de usar tempos limite, recomendo usar o evento onload de uma imagem. Aqui está um exemplo rápido:

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

Para evitar qualquer efeito que o CSS possa ter nas dimensões da imagem, o código acima faz uma cópia na memória da imagem. Esta é uma solução muito inteligente sugerida pelo FDisk .

Você também pode usar os atributos naturalHeighte naturalWidthHTML5.


5
Isso é inteligente, não sabia que você poderia fazer $ (img) .load ();
SeanJA

3
Além de widthe heightvocê provavelmente deve também remover min-width, min-height, max-widthe max-heightcomo eles também poderiam influenciar as dimensões da imagem.
Mqchen 6/06

5
A solução da FDisk é muito inteligente. Infelizmente, a solução, como ele escreveu, funcionará apenas se a imagem estiver em cache ou se a página já tiver terminado o download. Se a imagem não estiver armazenada em cache ou se esse código for chamado antes window.onload, uma altura / largura igual a 0 poderá ser retornada. De qualquer forma, integrei a ideia do FDisk na solução acima.
Xavi

5
quando tento console.log (pic_real_height) fico indefinido toda vez. cromado, FF, IE9.
helgatheviking

10
O problema que você pode ter aqui é que load()será executado de forma assíncrona, portanto, se você deseja acessar widthe height- eles ainda não foram definidos. Em vez disso, faça “a mágica” por load()si só!
DaGrevis

286

Use os atributos naturalHeighte naturalWidthdo HTML5 .

Por exemplo:

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

Funciona no IE9 +, Chrome, Firefox, Safari e Opera ( estatísticas ).


3
@DavidJohnstone Um exemplo deles sendo usado pode ajudar. Mas eu concordo, definitivamente merece ser mais alto.
21413 Stephen

5
Isso não parece funcionar na versão mais recente do FireFox (30.0), a menos que a imagem já exista no cache.
Joel Kinzel

1
Eu concordo com David Johnstone. Esta é uma grande notícia.
21715 jjwebdev

Note que você ainda precisa esperar a imagem carregar
Jesús Carrera

Não, clientHeight / clientWidth explicitamente não faz o que a pergunta faz. Ele precisa retornar a altura e a largura da imagem, não a altura e a largura da imagem como aparece na página. naturalWidth e naturalHeight estão corretos.
Jeroen van den Broek

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;
}

Você não precisa remover o estilo da imagem ou dos atributos das dimensões da imagem. Basta criar um elemento com javascript e obter a largura do objeto criado.


3
Desde alguns meses, a clonagem de uma imagem com jquery (usando o Chrome mais recente) e a obtenção de suas propriedades sempre retornam 0x0. Até agora, essas são as únicas soluções que funcionam (testaram todas as outras nesta página). Antes de retornar, defino t = nulo também.
Omiod 14/08/10

1
O FDisk não está sugerindo a clonagem da imagem com o jQuery. Ele está sugerindo a criação de um novo Imageobjeto, depois analisando sua widthpropriedade. Essa é uma abordagem simples e elegante. FDisk, você tem meu voto. :)
davidchambers

3
Esta é uma maneira muito inteligente de evitar problemas de css. Infelizmente, a solução descrita acima funcionará apenas se a imagem estiver em cache ou já tiver terminado o download. Se a imagem não estiver armazenada em cache ou se esse código for chamado antes window.onload, uma largura de 0 poderá ser retornada.
Xavi

1
Estou usando essa abordagem em um site para telefones celulares na galeria de imagens. Imagens maiores, em seguida, a resolução é exibida com 100% em css e menor nas dimensões originais.
FDisk

1
Como o Xavi mencionou, isso falha no IE8 e, às vezes, dependendo do cache da imagem. Então, eu juntamente com esta abordagem, e ele funciona perfeito: bind do evento de carga em primeiro lugar, em seguida, atribuir o objeto imagem sua fonte stackoverflow.com/questions/4921712/...
Kevin C.

16

O principal problema é que os navegadores WebKit (Safari e Chrome) carregam informações JavaScript e CSS em paralelo. Portanto, o JavaScript pode ser executado antes que os efeitos de estilo do CSS sejam calculados, retornando a resposta errada. No jQuery, descobri que a solução é esperar até 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) 

Quanto à largura e altura, dependendo do que você está fazendo, você pode querer offsetWidth e offsetHeight, que incluem itens como bordas e preenchimento.


Sim, essa é a razão. Uma solução melhor é usar o evento de carregamento do jQuery.
Frank Bannister

6
$(window).load(function(){ ... });ajudou no meu caso
kolypto

16

Há muita discussão na resposta aceita sobre um problema em que o onloadevento não é acionado se uma imagem é carregada do cache do WebKit.

No meu caso, é onloadacionado para imagens em cache, mas a altura e a largura ainda são 0. Um simples setTimeoutresolveu o problema para mim:

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

Não sei dizer por que o onloadevento está sendo disparado, mesmo quando a imagem é carregada do cache (aprimoramento do jQuery 1.4 / 1.5?) - mas se você ainda estiver com esse problema, talvez uma combinação da minha resposta e da var src = img.src; img.src = ""; img.src = src;técnica trabalhos.

(Observe que, para meus propósitos, não estou preocupado com dimensões predefinidas, nem nos atributos da imagem nem nos estilos CSS - mas você pode removê-las, conforme resposta do Xavi. Ou clonar a imagem.)


Eu tive esse mesmo problema com o IE7 e o IE8. setTimeout () funcionou para mim para esses navegadores. Obrigado!
Vasile Tomoiaga

11

isso funciona para mim (safari 3.2), disparando de dentro do window.onloadevento:

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

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

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

sim! Não funcionou em $ (document) .ready (function () {}); Obrigado! Ele precisa ter a imagem totalmente carregada antes de poder lê-la. Claro.
Frank Bannister

8

Você pode obter programaticamente a imagem e verificar as dimensões usando Javascript sem precisar mexer no 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
Essa é a melhor solução! Funciona mesmo que a imagem não seja pré-carregada ou armazenada em cache.
marlar 21/09/12

6

E sobre image.naturalHeighte image.naturalWidthpropriedades?

Parece funcionar bem em algumas versões no Chrome, Safari e Firefox, mas não no IE8 ou mesmo no IE9.


isso não está funcionando no meu caso. dando-me NaN em troca
saadk

5

Como obtemos as dimensões reais corretas sem uma imagem real piscante:

(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();});
});

Funciona com <img class = "toreaddimensions" ...


5

O Jquery possui duas propriedades chamadas naturalWidth e naturalHeight, que você pode usar dessa maneira.

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

Onde my-img é um nome de classe usado para selecionar minha imagem.


2
Estes não são métodos jQuery. naturalWidth(e altura) são propriedades no objeto de elemento de imagem. developer.mozilla.org/en/docs/Web/API/HTMLImageElement
sandstrom

3

Como afirmado anteriormente, a resposta do Xavi não funcionará se as imagens estiverem no cache. O problema responde ao webkit que não dispara o evento load em imagens em cache; portanto, se os atributos width / height não estão definidos explicitamente na tag img, a única maneira confiável de obter as imagens é aguardar o disparo do evento window.load.

O window.loadevento será acionado sempre , por isso é seguro acessar a largura / altura e o img depois disso sem nenhum truque.

$(window).load(function(){

   //these all work

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

});

Se você precisar obter o tamanho de imagens carregadas dinamicamente que podem ser armazenadas em cache (carregadas anteriormente), use o método Xavi mais uma sequência de consultas para acionar uma atualização de cache. A desvantagem é que isso causará outra solicitação ao servidor, para um img que já esteja em cache e já esteja disponível. Webkit estúpido.

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: se você já tem um QueryString no img.src, precisará analisá-lo e adicionar o parâmetro extra para limpar o cache.


1
Primeiro bloco de código começa apenas as dimensões de um elemento no DOM carregado, não de uma imagem em si ...
BasTaller

1
Esta é exatamente a solução mais rápida e eficaz. Nenhum plugin, nenhum truque! Vou postar uma resposta semelhante, mas encontrei a sua.
vantrung -cuncon

2

Como diz Luke Smith, o carregamento da imagem é uma bagunça . Não é confiável em todos os navegadores. Esse fato me deu muita dor. Uma imagem em cache não dispara o evento em alguns navegadores; portanto, aqueles que disseram "carregar a imagem é melhor que setTimeout" estão errados.

A solução de Luke Smith está aqui.

E há uma discussão interessante sobre como essa bagunça pode ser tratada no jQuery 1.4.

Eu descobri que é bastante confiável definir a largura como 0 e aguarde a propriedade "complete" se tornar verdadeira e a propriedade width seja maior que zero. Você deve observar também os erros.


O segundo link da resposta está morto.
Pang


2

Minha situação provavelmente é um pouco diferente. Estou alterando dinamicamente o src de uma imagem via javascript e necessário para garantir que a nova imagem seja dimensionada proporcionalmente para caber em um contêiner fixo (em uma galeria de fotos). Inicialmente, acabei de remover os atributos de largura e altura da imagem depois de carregada (por meio do evento de carregamento da imagem) e redefini-los depois de calcular as dimensões preferidas. No entanto, isso não funciona no Safari e possivelmente no IE (eu não testei completamente no IE, mas a imagem nem aparece, então ...).

De qualquer forma, o Safari mantém as dimensões da imagem anterior, para que as dimensões estejam sempre uma imagem atrás. Presumo que isso tenha algo a ver com o cache. Portanto, a solução mais simples é clonar a imagem e adicioná-la ao DOM (é importante que ela seja adicionada ao DOM para obter o with e height). Atribua à imagem um valor de visibilidade oculto (não use nenhum, pois não funcionará). Depois de obter as dimensões, remova o clone.

Aqui está o meu código usando 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);

Esta solução funciona em qualquer caso.



1

Recentemente, precisei encontrar largura e altura para definir o tamanho padrão de .dialog representando o gráfico. A solução que eu uso foi:

 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 })
    })

Para mim, isso funciona em FF3, Opera 10, IE 8,7,6

PS Você pode encontrar mais algumas soluções procurando dentro de alguns plugins como LightBox ou ColorBox


1

Para adicionar à resposta de Xavi, o gitubub de Paul Irish, David Desandro, oferece uma função chamada imagesLoaded () que funciona com os mesmos princípios e contorna o problema de as imagens em cache de alguns navegadores não dispararem o evento .load () (com inteligente original_src -> data_uri -> comutação original_src).

É amplamente utilizado e atualizado regularmente, o que contribui para ser a solução mais robusta para o problema, a IMO.


1
Você pode encontrar uma versão atualizada da imagesLoadedfunção aqui: github.com/desandro/imagesloaded
bejonbee

Sim, David Desandro está hospedando a função agora. Obrigado por me lembrar @somethingkindawierd, atualizei minha resposta.
RobW

1

Isso funciona para imagens armazenadas em cache e carregadas dinamicamente.

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

Para usar este script:

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

Demonstração: http://jsfiddle.net/9543z/2/


1

Eu fiz alguma função do utilitário de solução alternativa, usando o plugin 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}));
            },

Você pode usar isso passando url, função e seu contexto. A função é executada depois que a imagem é carregada e retorna a imagem criada, sua largura e altura.

waitForImageSize("image.png", function(w,h){alert(w+","+h)},this)

1

Se a imagem já estiver sendo usada, você deverá:

  1. defina as simulações de imagem como inicial

    image.css ('largura', 'inicial'); image.css ('altura', 'inicial');

  2. obter dimensões

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


1

Você pode usar as propriedades naturalWidth e naturalHeight do elemento de imagem HTML. (Aqui está mais informações ).

Você usaria assim:

//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;

Parece que isso funciona em todos os navegadores, exceto no IE da versão 8 e abaixo.


Sim, não mais IE8: D
Jair Reina

0

Eu verifiquei a resposta de Dio e funciona muito bem para mim.

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

Certifique-se de chamar todas as suas funções também. que lidam com o tamanho da imagem na função recorder de fadeIn ().

Obrigado por isso.


0

Eu uso uma abordagem diferente, basta fazer o Ajax chamar o servidor para obter o tamanho da imagem quando o objeto de imagem estiver em uso.

//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);
    }
}

e, claro, código do lado do servidor:

<?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);

?>

1
essa não é uma ótima solução e levará mais tempo do que qualquer outra solução devido ao carregamento do AJAX.
Halfpastfour.am

0

Isso funciona em vários navegadores

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

obter as dimensões usando

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

Felicidades!



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

// Este código ajuda a mostrar imagens com 200 * 274 dimensões



0

Tropecei nessa discussão tentando encontrar uma resposta para minha própria pergunta. Eu estava tentando obter a largura / altura de uma imagem em uma função APÓS o carregador e continuava com 0. Eu sinto que isso pode ser o que você está procurando, pois funciona para mim:

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

Confira este repositório no github!

Ótimo exemplo para verificar a largura e altura usando Javascript

https://github.com/AzizAK/ImageRealSize

--- Editado é solicitado a partir de alguns comentários.

Código 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);
    }

e código 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>

se possível, você também pode adicionar algumas linhas de código aqui. como os links podem mudar ao longo do tempo
Tejus Prasad 30/11/2015

-1

Para funções nas quais você não deseja alterar o posicionamento ou a imagem original.

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

1
Isso absolutamente não funciona. Ele retornará indefinido para ambos
Chris Cinelli
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.