Obter a largura real e altura de uma imagem com JavaScript? (No Safari / Chrome)
-
11-07-2019 - |
Pergunta
Estou criando um plugin jQuery.
Como posso obter a largura da imagem real e altura com JavaScript no Safari?
a seguir funciona com 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 em navegadores Webkit como valores Safari e Google Chrome são 0.
Solução
navegadores Webkit definir a altura e largura propriedades após a imagem ser carregada. Em vez de usar o tempo limite, eu recomendo usar evento de carregamento 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 do CSS efeitos pode ter sobre as dimensões da imagem, o código acima faz uma na cópia de memória da imagem. Esta é uma solução muito inteligente sugerido por FDisk .
Você também pode usar o naturalHeight
e naturalWidth
HTML5 atributos.
Outras dicas
Use o naturalHeight
e atributos naturalWidth
de HTML5 .
Por exemplo:
var h = document.querySelector('img').naturalHeight;
Obras em IE9 +, Chrome, Firefox, Safari e Opera ( estatí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;
}
Você não precisa remover estilo a partir da imagem ou dimensões da imagem atributos. Basta criar um elemento com JavaScript e obter a largura objeto criado.
A raiz do problema é que os navegadores WebKit (Safari e Chrome) Carga JavaScript e CSS informações em paralelo. Assim, JavaScript pode executar antes que os efeitos de estilo de CSS foram computados, retornando a resposta errada. Em jQuery, eu descobri que a solução é esperar até document.readyState == 'completa', .e.g.,
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 vai ... dependendo do que você está fazendo, você pode querer offsetWidth e offsetHeight, que incluem coisas como as fronteiras e estofamento.
Há muita discussão na resposta aceita sobre um problema onde o evento onload
não dispara se uma imagem é carregada a partir do cache WebKit.
No meu caso, incêndios onload
para imagens em cache, mas a altura ea largura ainda são 0. Um simples setTimeout
resolvido o problema para mim:
$("img").one("load", function(){
var img = this;
setTimeout(function(){
// do something based on img.width and/or img.height
}, 0);
});
Eu não posso falar a respeito de porque o evento onload
está a disparar mesmo quando a imagem é carregada a partir do cache (melhoria do jQuery 1.4 / 1.5?) - mas se você ainda estiver enfrentando esse problema, talvez uma combinação de minha resposta ea técnica var src = img.src; img.src = ""; img.src = src;
vai funcionar.
(Note-se que para os meus propósitos, eu não estou preocupado com dimensões pré-definidas, seja em atributos da imagem ou estilos CSS -. Mas você pode querer remover aqueles, como por resposta de Xavi ou clonar a imagem.)
Isso funciona para mim (safari 3.2), por aquecimento de dentro do evento window.onload
:
$(window).load(function() {
var pic = $('img');
pic.removeAttr("width");
pic.removeAttr("height");
alert( pic.width() );
alert( pic.height() );
});
Você pode obter programaticamente a imagem e verificar as dimensões usando Javascript, sem ter que mexer com o DOM em tudo.
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';
E sobre image.naturalHeight
e image.naturalWidth
propriedades?
Parece funcionar bem para trás algumas versões no Chrome, Safari e Firefox, mas não em todos no IE8 ou mesmo IE9.
Como temos reais dimensões certas, sem uma imagem real piscar:
(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();});
});
Ele funciona com
Jquery tem duas propriedades chamadas naturalWidth e naturalHeight, você pode usar desta forma.
$('.my-img')[0].naturalWidth
$('.my-img')[0].naturalHeight
Onde meu-img é um nome de classe usado para selecionar a minha imagem.
Como dito antes, Xavi resposta não vai funcionar se as imagens estão no cache. Os responde questão a webkit não disparar o evento de carregamento em imagens em cache, por isso, se a largura / attrs altura não são explicitamente definido no tag img, a única maneira confiável para obter as imagens é esperar para o evento window.load
ser demitido.
O evento window.load
dispara sempre , por isso é seguro para acessar a largura / altura e img depois disso sem qualquer 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ê precisa para obter o tamanho das imagens carregadas dinamicamente que podem ficar armazenadas em cache (previamente carregados), você pode usar o método Xavi além de uma string de consulta para acionar uma atualização de cache. A desvantagem é que ele fará com que outra solicitação para o servidor, para uma img que já está em cache e deve ser já 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ê tem um QueryString no img.src
, já que você terá que analisá-lo e adicione o param extra para limpar o cache.
Como Luke Smith diz: carga imagem é uma bagunça . Não é confiável em todos os navegadores. Este fato tem me dado muita dor. A imagem em cache não irá disparar o evento em tudo em alguns navegadores, então aqueles que disseram "load imagem é melhor do que setTimeout" estão errados.
A solução de Luke Smith é aqui.
E há uma discussão interessante sobre como este bagunça pode ser tratado em jQuery 1.4.
Eu descobri que é bastante confiável para definir a largura de 0, e depois esperar para a propriedade "completa" para ir verdadeiro e a largura propriedade para entrar maior que zero. Você deve prestar atenção para erros, também.
$("#myImg").one("load",function(){
//do something, like getting image width/height
}).each(function(){
if(this.complete) $(this).trigger("load");
});
De comentário Chris': http://api.jquery.com/load-event/
A minha situação é provavelmente um pouco diferente. Eu estou mudando dinamicamente o src de uma imagem via javascript e necessário para garantir que a nova imagem é dimensionada proporcionalmente para caber num recipiente fixo (em uma galeria de fotos). I inicialmente apenas removido a largura e altura atributos da imagem, depois de carregado (via evento de carregamento da imagem) e repor estes depois de calcular as dimensões preferidas. No entanto, isso não funciona no Safari e, possivelmente, IE (eu não testei no IE completamente, mas a imagem não mostram mesmo, então ...).
De qualquer forma, Safari mantém as dimensões da imagem anterior para as dimensões são sempre uma imagem para trás. Presumo que isso tem algo a ver com o cache. Portanto, a solução mais simples é clone da imagem e adicioná-lo ao DOM (é importante que ele seja adicionado ao DOM a obter o com e altura). Dar a imagem um valor visibilidade do oculto (não use nenhum exibição porque não vai funcionar). Depois de obter as dimensões remover 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.
Existe agora um plugin jQuery, event.special.load
, para lidar com casos onde o evento de carga em uma imagem em cache não dispara: http://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js
Recentemente eu precisava encontrar largura e altura para definir o tamanho padrão de .dialog gráfico que representa. 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 no FF3, Opera 10, IE 8,7,6
P.S. Você pode ser encontrar mais algumas soluções que olha dentro de alguns plugins como LightBox ou ColorBox
Para adicionar a resposta de Xavi, Paul Irish github David Desandro gitgub oferece uma função de chamada imagesLoaded () que as obras nos mesmos princípios, e fica em torno do problema de imagens em cache de algum navegador não disparar o evento .load () (com original_src inteligente -> data_uri -> original_src de comutação).
É é amplamente utilizado e atualizado regularmente, o que contribui para que seja a solução mais robusta para o problema, IMO.
Isso funciona para ambas as imagens em cache e carregados 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/
Já fiz alguns função de utilidade solução alternativa, usando imagesLoaded jquery plugin: 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 é realizada após a imagem é carregado e retornar imagem criada, a sua largura e altura.
waitForImageSize("image.png", function(w,h){alert(w+","+h)},this)
Se a imagem já é usado, você sholud:
-
imagem Jogo simensions a inicial
image.css ( 'largura', 'primeiro'); image.css ( 'altura', 'inicial');
-
get dimensões
var originalWidth = $ (this) .width (); var originalHeight = $ (this) .height ();
Você pode usar as propriedades naturalWidth e naturalHeight do elemento de imagem HTML. (Aqui está mais informações ).
Você poderia usá-lo como este:
//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 a partir da versão 8 e abaixo.
Para funções onde você não deseja alterar a localização original ou imagem.
$(this).clone().removeAttr("width").attr("width");
$(this).clone().removeAttr("height").attr("height);
Eu confirmei a resposta de Dio e ele funciona muito bem para mim.
$('#image').fadeIn(10,function () {var tmpW = $(this).width(); var tmpH = $(this).height(); });
Certifique-se de que você chamar todas as suas funções aso. que pega com o tamanho da imagem na função Confirmador de fadeIn ().
Obrigado por isso.
Eu uso abordagem diferente, basta fazer a chamada Ajax ao servidor para obter o tamanho da imagem quando objeto de imagem está 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, o 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);
?>
Isso funciona cross browser
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!
Outra sugestão é usar imagesLoaded plug-in .
$("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 ajuda a mostrar imagem com 200 * 274 dimention
Aqui está uma solução cross browser que desencadeia um evento quando suas imagens selecionadas são carregados: http: //desandro.github .io / imagesloaded / você pode olhar para cima a altura ea largura dentro da função imagesLoaded ().
Tropeçamos a esta discussão tentando encontrar uma resposta para a minha pergunta. Eu estava tentando obter a largura de uma imagem / altura em uma função após o carregador, e manteve chegando com 0. Eu sinto que isso pode ser o que você está procurando, embora, como ele 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);
}
Confira este repositório no github!
grande exemplo para verificar a largura e altura usando Javascript
https://github.com/AzizAK/ImageRealSize
--- Editado é solicitado 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>