¿Obtener el ancho y alto real de una imagen con JavaScript? (en Safari / Chrome)


279

Estoy creando un complemento jQuery.

¿Cómo obtengo el ancho y la altura de la imagen real con Javascript en Safari?

Lo siguiente funciona con Firefox 3, IE7 y 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();

Pero en los navegadores Webkit como Safari y Google Chrome los valores son 0.


44
La respuesta aceptada utiliza el evento de carga de imagen. Tiene mucho sentido, pero resulta ser una solución poco confiable en situaciones donde las imágenes se pueden almacenar en caché (para mi consternación).
Nosredna el

Mi opinión sobre esto puede ayudarlo, probado en el último Webkit. stackoverflow.com/questions/318630/…
xmarcos

55
@Nosredna, puede interesarle la función imagesLoaded que se activará incluso cuando las imágenes se hayan almacenado en caché.
bejonbee

77
La respuesta correcta a esta pregunta es simplemente usar las propiedades naturalWidth y naturalHeight. No se requieren hackers.
David Johnstone

También podría hacer exactamente lo que está haciendo con la carga de la ventana en lugar de tener el documento listo
usuario1380540

Respuestas:


357

Los navegadores Webkit establecen la propiedad de alto y ancho después de cargar la imagen. En lugar de usar tiempos de espera, recomiendo usar el evento de carga de una imagen. Aquí hay un ejemplo 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 cualquiera de los efectos que CSS puede tener en las dimensiones de la imagen, el código anterior hace una copia en memoria de la imagen. Esta es una solución muy inteligente sugerida por FDisk .

También puede usar los atributos naturalHeighty naturalWidthHTML5.


55
Eso es inteligente, no sabía que podía hacer $ (img) .load ();
SeanJA

3
Además de widthy heightprobablemente debería también eliminar min-width, min-height, max-widthy max-heightque también podrían influir en las dimensiones de imagen.
mqchen

55
La solución de FDisk es muy inteligente. Desafortunadamente, la solución tal como la ha escrito solo funcionará si la imagen está en caché o si la página ya ha terminado de descargarse. Si la imagen no se almacena en caché o si se llama a este código antes window.onload, se puede devolver un alto / ancho de 0. En cualquier caso, he integrado la idea de FDisk en la solución anterior.
Xavi

55
cuando trato de console.log (pic_real_height) me sale indefinido cada vez. cromo, FF, IE9.
helgatheviking

10
El problema que puede tener aquí es que load()se ejecutará de forma asincrónica, por lo que si desea acceder widthy height, es posible que aún no se hayan configurado. En cambio, ¡haz "la magia" en load()sí mismo!
daGrevis

286

Use los atributos naturalHeighty naturalWidthde HTML5 .

Por ejemplo:

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

Funciona en IE9 +, Chrome, Firefox, Safari y Opera ( estadísticas ).


3
@DavidJohnstone Un ejemplo de ellos utilizados podría ayudar. Pero estoy de acuerdo, definitivamente merece estar más arriba.
Stephen

55
Esto no parece funcionar en la última versión de FireFox (30.0) a menos que la imagen ya exista en el caché.
Joel Kinzel

1
Estoy de acuerdo con David Johnstone. Esta es una gran noticia.
jchwebdev

Tenga en cuenta que aún debe esperar a que se cargue la imagen
Jesús Carrera,

No, clientHeight / clientWidth explícitamente no hace lo que hace la pregunta. Debe devolver el alto y el ancho de la imagen, no el alto y el ancho de la imagen como se ve en la página. naturalWidth y naturalHeight son correctos.
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;
}

No necesita eliminar el estilo de la imagen o los atributos de dimensiones de la imagen. Simplemente cree un elemento con javascript y obtenga el ancho del objeto creado.


3
Desde hace unos meses, clonar una imagen con jquery (usando el último Chrome) y obtener sus propiedades, siempre devuelve 0x0 Hasta ahora, esta es la única solución que funciona (he probado todas las demás en esta página) Antes de regresar, configuré t = nulo también
Omiod

1
FDisk no sugiere clonar la imagen con jQuery. Sugiere crear un nuevo Imageobjeto y luego mirar su widthpropiedad. Este es un enfoque simple y elegante. FDisk, tienes mi voto. :)
davidchambers

3
Esta es una forma muy inteligente de evitar problemas de CSS. Desafortunadamente, la solución como se escribió anteriormente solo funcionará si la imagen está en caché o ya ha finalizado la descarga. Si la imagen no se almacena en caché o si se llama a este código antes window.onload, se puede devolver un ancho de 0.
Xavi

1
Estoy usando este enfoque en un sitio web para teléfonos móviles en la galería de imágenes. Imágenes más grandes que la resolución se muestra con 100% en CSS y menor en dimensiones originales.
FDisk

1
Como mencionó Xavi, esto falla en IE8 y, a veces, depende del almacenamiento en caché de la imagen. Así que lo combiné con este enfoque, y funciona perfecto: primero vincula el evento de carga, luego asigna al objeto de imagen su fuente stackoverflow.com/questions/4921712/…
Kevin C.

16

El problema raíz es que los navegadores WebKit (Safari y Chrome) cargan información de JavaScript y CSS en paralelo. Por lo tanto, JavaScript puede ejecutarse antes de que se hayan calculado los efectos de estilo de CSS, devolviendo la respuesta incorrecta. En jQuery, descubrí que la solución es esperar hasta 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) 

En cuanto al ancho y la altura ... dependiendo de lo que esté haciendo, es posible que desee offsetWidth y offsetHeight, que incluyen elementos como bordes y relleno.


Sí, esa es la razón. Una mejor solución es usar el evento de carga de jQuery.
Frank Bannister

66
$(window).load(function(){ ... });ayudado en mi caso
kolypto

16

Hay mucha discusión en la respuesta aceptada sobre un problema en el onloadque el evento no se dispara si se carga una imagen desde el caché de WebKit.

En mi caso, se onloadactivan las imágenes en caché, pero la altura y el ancho siguen siendo 0. Un simple setTimeoutresolvió el problema por mí:

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

No puedo decir por qué el onloadevento se dispara incluso cuando la imagen se carga desde el caché (¿mejora de jQuery 1.4 / 1.5?), Pero si aún experimenta este problema, tal vez una combinación de mi respuesta y la var src = img.src; img.src = ""; img.src = src;técnica trabajo.

(Tenga en cuenta que, para mis propósitos, no me preocupan las dimensiones predefinidas, ya sea en los atributos de la imagen o en los estilos CSS, pero es posible que desee eliminarlos, según la respuesta de Xavi. O clonar la imagen).


Tuve este mismo problema con IE7 y IE8. setTimeout () funcionó para mí para esos navegadores. ¡Gracias!
Vasile Tomoiaga

11

esto funciona para mí (safari 3.2), disparando desde dentro del window.onloadevento:

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

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

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

¡Si! No funcionó desde $ (document) .ready (function () {}); ¡Gracias! Necesita tener la imagen completamente cargada antes de poder leerla. Por supuesto.
Frank Bannister el

8

Puede obtener la imagen mediante programación y verificar las dimensiones usando Javascript sin tener que meterse con el 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
¡Esta es la mejor solución! Funciona incluso si la imagen no está precargada o en caché.
marlar

7

¿Qué pasa con image.naturalHeighty image.naturalWidthpropiedades?

Parece funcionar bien con algunas versiones en Chrome, Safari y Firefox, pero no en IE8 o incluso IE9.


Esto no funciona en mi caso. dándome NaN a cambio
Sábado

6

Jquery tiene dos propiedades llamadas naturalWidth y naturalHeight, que puede usar de esta manera.

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

Donde my-img es un nombre de clase utilizado para seleccionar mi imagen.


2
Estos no son métodos jQuery. naturalWidth(y altura) son propiedades en el objeto del elemento de imagen. developer.mozilla.org/en/docs/Web/API/HTMLImageElement
sandstrom

5

Cómo obtenemos las dimensiones reales correctas sin una imagen real parpadeante:

(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 con <img class = "toreaddimensions" ...


3

Como se indicó anteriormente, la respuesta de Xavi no funcionará si las imágenes están en el caché. El problema responde a que webkit no dispara el evento de carga en las imágenes en caché, por lo que si los atributos de ancho / alto no están establecidos explícitamente en la etiqueta img, la única forma confiable de obtener las imágenes es esperar a que se active el window.loadevento.

El window.loadevento se disparará siempre , por lo que es seguro acceder al ancho / alto de e img después de eso sin ningún truco.

$(window).load(function(){

   //these all work

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

});

Si necesita obtener el tamaño de las imágenes cargadas dinámicamente que podrían almacenarse en caché (previamente cargadas), puede usar el método Xavi más una cadena de consulta para activar una actualización de caché. La desventaja es que causará otra solicitud al servidor, para un img que ya está en caché y ya debería estar disponible. Estúpido 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: si ya tiene un QueryString en el img.src, tendrá que analizarlo y agregar el parámetro adicional para borrar el caché.


1
En primer bloque de código sólo se pone las dimensiones de un elemento de DOM cargado, no de una imagen en sí ...
BasTaller

1
Esta es exactamente la solución más rápida y efectiva. ¡Sin plugin, sin truco! Voy a publicar una respuesta similar pero encontré la tuya.
vantrung -cuncon

2

Como dice Luke Smith, la carga de imágenes es un desastre . No es confiable en todos los navegadores. Este hecho me ha dado mucho dolor. Una imagen en caché no activará el evento en absoluto en algunos navegadores, por lo que aquellos que dijeron "cargar la imagen es mejor que setTimeout" están equivocados.

La solución de Luke Smith está aquí.

Y hay una discusión interesante sobre cómo se podría manejar este desastre en jQuery 1.4.

He descubierto que es bastante confiable establecer el ancho en 0, luego esperar a que la propiedad "completa" se haga realidad y la propiedad del ancho sea mayor que cero. También debes estar atento a los errores.


El segundo enlace en respuesta está muerto.
Pang


2

Mi situación es probablemente un poco diferente. Estoy cambiando dinámicamente el src de una imagen a través de javascript y necesitaba asegurarme de que la nueva imagen tenga un tamaño proporcional para adaptarse a un contenedor fijo (en una galería de fotos). Inicialmente, eliminé los atributos de ancho y alto de la imagen después de cargarla (a través del evento de carga de la imagen) y los restablecí después de calcular las dimensiones preferidas. Sin embargo, eso no funciona en Safari y posiblemente en IE (no lo he probado completamente en IE, pero la imagen ni siquiera se muestra, así que ...).

De todos modos, Safari mantiene las dimensiones de la imagen anterior para que las dimensiones siempre estén una imagen atrás. Supongo que esto tiene algo que ver con el caché. Entonces, la solución más simple es simplemente clonar la imagen y agregarla al DOM (es importante que se agregue al DOM para obtener el con y la altura). Otorgue a la imagen un valor de visibilidad oculto (no use display none porque no funcionará). Después de obtener las dimensiones, elimine el clon.

Aquí está mi 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 solución funciona en cualquier caso.



1

Recientemente necesitaba encontrar el ancho y la altura para configurar el tamaño predeterminado de .dialog que representa el gráfico. La solución que uso fue:

 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 mí esto funciona en FF3, Opera 10, IE 8,7,6

PD: Puede encontrar algunas soluciones más buscando dentro de algunos complementos como LightBox o ColorBox


1

Para agregar a la respuesta de Xavi, el gitub de Paul Irish, David Desandro, ofrece una función llamada imagesLoaded () que funciona con los mismos principios y evita el problema de que las imágenes en caché de algunos navegadores no activen el evento .load () (con inteligente original_src -> data_uri -> conmutación original_src).

Es ampliamente utilizado y actualizado regularmente, lo que contribuye a que sea la solución más sólida para el problema, la OMI.


1
Puede encontrar una versión actualizada de la imagesLoadedfunción aquí: github.com/desandro/imagesloaded
bejonbee

Sí, David Desandro está organizando la función ahora. Gracias por recordarme @somethingkindawierd, actualicé mi respuesta.
RobW

1

Esto funciona para imágenes en caché y cargadas dinámicamente.

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

Demostración: http://jsfiddle.net/9543z/2/


1

He realizado alguna función de utilidad de solución alternativa, usando el complemento imagesqueaded 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}));
            },

Puede usar esto pasando url, function y su contexto. La función se realiza después de cargar la imagen y devolver la imagen creada, su ancho y alto.

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

1

Si la imagen ya está en uso, debes sholud:

  1. establecer simensiones de imagen a inicial

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

  2. obtener dimensiones

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


1

Puede usar las propiedades naturalWidth y naturalHeight del elemento de imagen HTML. (Aquí hay más información ).

Lo usarías así:

//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 esto funciona en todos los navegadores, excepto en IE desde la versión 8 y posteriores.


Sí, no más IE8: D
Jair Reina

0

Revisé la respuesta de Dio y me funciona muy bien.

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

Asegúrate de llamar a todas tus funciones aso. que se maneja con el tamaño de la imagen en la función de recordatorio de fadeIn ().

Gracias por esto.


0

Utilizo un enfoque diferente, simplemente hago una llamada Ajax al servidor para obtener el tamaño de la imagen cuando el objeto de la imagen está en 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);
    }
}

y, por supuesto, el código del lado del 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
Esta no es una gran solución y tomará más tiempo que cualquier otra solución debido a la carga de AJAX.
halfpastfour.am

0

Esto funciona entre navegadores

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

obtener las dimensiones usando

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

¡Salud!



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 ayuda a mostrar la imagen con 200 * 274 dimention



0

Tropecé con este hilo tratando de encontrar una respuesta para mi propia pregunta. Intenté obtener el ancho / alto de una imagen en una función DESPUÉS del cargador, y seguí apareciendo 0. Sin embargo, creo que esto podría ser lo que estás buscando, ya que funciona para mí:

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

¡Mira este repositorio en github!

Gran ejemplo para verificar el ancho y la altura usando Javascript

https://github.com/AzizAK/ImageRealSize

--- Se solicita la edición de algunos comentarios.

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

y 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>

si es posible, también puede agregar algunas líneas de código aquí. como los enlaces pueden cambiar con el tiempo
Tejus Prasad

-1

Para funciones en las que no desea alterar la ubicación o la imagen original.

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

1
Esto absolutamente no funciona. Volverá indefinido para ambos
Chris Cinelli
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.