Pregunta

Estoy creando un plugin de jQuery.

¿Cómo puedo obtener la imagen real de la anchura y la altura con Javascript en Safari?

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.

¿Fue útil?

Solución

Los navegadores Webkit establecer la altura y la anchura de la propiedad después de que se carga la imagen.En lugar de utilizar los tiempos de espera, me gustaría recomendar el uso de una imagen del evento onload.Aquí está 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 que alguno de los efectos CSS podría tener sobre las dimensiones de la imagen, el código anterior hace que una copia de la memoria de la imagen.Esta es una solución muy inteligente sugerido por FDisk.

También puede utilizar el naturalHeight y naturalWidth HTML5 atributos.

Otros consejos

El uso de la naturalHeight y naturalWidth atributos de HTML5.

Por ejemplo:

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

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


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.

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', .e.g.,

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.

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

En mi caso, setTimeout dispara para imágenes en caché, pero la altura y el ancho siguen siendo 0. Un simple var src = img.src; img.src = ""; img.src = src; resolvió el problema para mí:

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

No puedo hablar de por qué el evento <=> se dispara incluso cuando la imagen se carga desde el caché (¿mejora jQuery 1.4 / 1.5?) & # 8212; pero si todavía tiene este problema, tal vez una combinación de mi respuesta y la técnica <=> funcionen.

(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 & # 8212; pero es posible que desee eliminarlos, según la respuesta de Xavi. O clonar la imagen.)

esto funciona para mí (safari 3.2), disparando desde el evento window.onload:

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

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

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

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

¿Qué acerca de image.naturalHeight y image.naturalWidth propiedades?

Parece funcionar bien muy pocas versiones de Chrome, Firefox y Safari, pero no a todos los IE8 o incluso IE9.

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

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.

Como se indicó anteriormente, La respuesta de Xavi no funcionará si las imágenes están en el caché. El problema responde a que el kit web no activa el evento de carga en las imágenes almacenadas 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 evento window.load .

El evento img.src se activará 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 una QueryString en <=>, deberá analizarlo y agregar el parámetro adicional para borrar el caché.

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 algunos navegadores, por lo que aquellos que dijeron & Quot; la carga de la imagen es mejor que setTimeout & Quot; están equivocados.

La solución de Luke Smith es aquí.

Y hay una discusión interesante sobre cómo esto El desorden se puede manejar en jQuery 1.4.

He descubierto que es bastante confiable establecer el ancho en 0, luego esperar a que " complete " propiedad para que se cumpla y la propiedad de ancho para que sea mayor que cero. También debe estar atento a los errores.

$("#myImg").one("load",function(){
  //do something, like getting image width/height
}).each(function(){
  if(this.complete) $(this).trigger("load");
});

Del comentario de Chris: http://api.jquery.com/load-event/

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 a fondo 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 detrá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.

Ahora hay un complemento jQuery, event.special.load, para tratar casos donde el evento de carga en una imagen en caché no se dispara: http://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js

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 utilicé 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

P.S. Es posible que encuentre más soluciones buscando dentro de algunos complementos como LightBox o ColorBox

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

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

Esto funciona para imágenes cargadas 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/

He hecho 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)

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

  1. establece las dimensiones de la imagen en inicial

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

  2. obtener dimensiones

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

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

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.

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

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 también. que se maneja con el tamaño de la imagen en la función de recordatorio de fadeIn ().

Gracias por esto.

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

?>

Esto funciona en varios navegadores

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

obtenga las dimensiones usando

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

¡Salud!

Otra sugerencia es utilizar imagesLoaded plugin .

$("img").imagesLoaded(function(){
alert( $(this).width() );
alert( $(this).height() );
});
$(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 dimensiones

Aquí hay una solución de navegador cruzado que desencadena un evento cuando se cargan las imágenes seleccionadas: http: //desandro.github .io / imagesloaded / puede buscar el alto y el ancho dentro de la función imagesLoaded ().

Me topé 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);
}

¡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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top