使用JavaScript获取图像的实际宽度和高度?(在Safari / Chrome中)


278

我正在创建一个jQuery插件。

如何在Safari中使用Javascript获得真实的图像宽度和高度?

以下适用于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。


4
接受的答案使用图像加载事件。完全有道理,但是在可以缓存图像的情况下,结果证明这是不可靠的解决方案(令我非常沮丧)。
Nosredna,2009年

在最新的Webkit中测试,我对此可能会有所帮助。stackoverflow.com/questions/318630/...
xmarcos

5
@Nosredna,您可能对即使在缓存了图像后仍会触发的imagesLoaded函数感兴趣。
bejonbee 2011年

7
这个问题的正确答案是简单地使用naturalWidth和naturalHeight属性。无需黑客。
David Johnstone 2013年

您也可以完全按照窗口加载的方式进行操作,而不是准备好文档
user1380540 2015年

Answers:


356

Webkit浏览器在加载图像后设置height和width属性。建议不要使用超时,而建议使用图像的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建议的非常聪明的解决方案。

您还可以使用naturalHeightnaturalWidthHTML5属性。


5
那很聪明,不知道你可以做$(img).load();
SeanJA

3
除了widthheight你或许应该还能去除min-widthmin-heightmax-widthmax-height他们一样也可能会影响图像的尺寸。
mqchen 2010年

5
FDisk的解决方案非常聪明。不幸的是,他编写的解决方案仅在图像已缓存或页面已完成下载时才有效。如果未缓存图像,或者如果之前调用了此代码,则window.onload可能会返回高度/宽度0。无论如何,我已经将FDisk的想法集成到了上面的解决方案中。
哈维

5
当我尝试console.log(pic_real_height)时,我每次都不确定。chrome,FF,IE9。
helgatheviking 2011年

10
您可能在这里遇到的问题是,load()它将异步执行,因此如果您要访问width,则height-可能尚未设置它们。而是自己做“魔术” load()
daGrevis 2012年

286

使用HTML5中naturalHeightnaturalWidth属性。

例如:

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

适用于IE9 +,Chrome,Firefox,Safari和Opera(统计信息)。


3
@DavidJohnstone使用它们的示例可能会有所帮助。但是我同意,绝对值得更高。
斯蒂芬,

5
除非映像已存在于缓存中,否则在最新版本的FireFox(30.0)中似乎无法使用。
Joel Kinzel 2014年

1
我同意戴维·约翰斯通(David Johnstone)的观点。这是个好消息。
jchwebdev

请注意,您仍然需要等待图像加载
赫苏斯·卡雷拉

不,clientHeight / clientWidth明确不执行问题要求。它需要返回图像的高度和宽度,而不是页面上看起来的图像的高度和宽度。naturalWidth和naturalHeight是正确的。
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;
}

您无需从图像或图像尺寸属性中删除样式。只需使用javascript创建元素并获取创建的对象宽度。


3
几个月以来,使用jquery克隆图像(使用最新的Chrome)并获取其属性始终返回0x0到目前为止,这是唯一可行的解​​决方案(已测试了此页面中的所有其他解决方案)在返回之前,我设置了t =也为空。
Omiod

1
FDisk不建议使用jQuery克隆图像。他建议创建一个新Image对象,然后查看其width属性。这是一种简单,优雅的方法。FDisk,我有表决权。:)
davidchambers

3
这是避免CSS问题的非常聪明的方法。不幸的是,上述解决方案仅在图像已缓存或已完成下载时才有效。如果未缓存图像,或者如果之前调用了此代码,则window.onload可能会返回宽度0。
哈维

1
我在图片库中的手机网站上使用这种方法。更大的图像然后显示分辨率,其中css为100%,原始尺寸为较小。
FDisk

1
如Xavi所述,这在IE8中失败,有时取决于图像缓存。因此,我这种方法连接它,它工作完美:绑定加载事件第一,然后分配图象对象其源stackoverflow.com/questions/4921712/...
凯文C.

16

根本问题是WebKit浏览器(Safari和Chrome)并行加载JavaScript和CSS信息。因此,JavaScript可能会在计算CSS的样式效果之前执行,从而返回错误的答案。在jQuery中,我发现解决方案是等到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) 

就宽度和高度而言...根据您的工作,可能需要offsetWidth和offsetHeight,其中包括边框和填充等内容。


是的,这就是原因。更好的解决方法是使用jQuery的load-event。
Frank Bannister

6
$(window).load(function(){ ... });对我来说有帮助
kolypto

16

在已接受的答案中,有很多讨论涉及以下问题: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的回答将其删除。或克隆图像。)


我在IE7和IE8中遇到了这个问题。setTimeout()对我来说适合那些浏览器。谢谢!
Vasile Tomoiaga 2013年

11

通过在window.onload事件内触发,这对我有效(Safari 3.2):

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

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

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

是的 在$(document).ready(function(){})中无效;谢谢!它需要完全加载图像才能读取它。当然。
Frank Bannister

8

您可以使用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';

2
这是最好的解决方案!即使未预加载或缓存图像,它也可以工作。
marlar 2012年

6

什么image.naturalHeightimage.naturalWidth属性?

似乎可以很好地支持Chrome,Safari和Firefox中的许多版本,但在IE8甚至IE9中根本无法使用。


就我而言这不起作用。回报我NaN
saadk '17

5

我们如何获得正确的真实尺寸而又不眨眼的真实图像:

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

它适用于<img class =“ toreaddimensions” ...



3

如前所述, 如果图像在缓存中 Xavi答案将不起作用。该问题是由于webkit无法在缓存的图像上触发加载事件,因此,如果未在img标签中明确设置width / height attrs,则获取图像的唯一可靠方法是等待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应该已经可用。愚蠢的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,则必须对其进行解析并添加额外的参数以清除缓存。


1
第一段

1
这正是最快,最有效的解决方案。没有插件,没有花招!我将发布类似的答案,但找到了您的答案。
vantrung -cuncon

2

正如卢克·史密斯(Luke Smith)所说,图像加载是一团糟。并非在所有浏览器上都可靠。这个事实使我非常痛苦。在某些浏览器中,缓存的图像根本不会触发该事件,因此那些说“图像负载比setTimeout更好”的人是错误的。

卢克·史密斯(Luke Smith)的解决方案就在这里。

而且有一个有趣的讨论有关如何这个烂摊子可能在jQuery的1.4进行处理。

我发现将width设置为0,然后等待“ complete”属性变为true,并且width属性大于零是非常可靠的。您也应该注意错误。


答案中的第二个链接已死。


2

我的情况可能有所不同。我正在通过javascript动态更改图像的src,需要确保新图像的大小成比例以适合固定容器(在照片库中)。最初,我只是在加载图像后(通过图像的load事件)删除了图像的width和height属性,并在计算了首选尺寸后将其重置。但是,这在Safari和可能的IE中不起作用(我尚未在IE中进行全面测试,但是图像甚至没有显示出来,所以...)。

无论如何,Safari会保留前一张图像的尺寸,因此尺寸始终是后一张图像。我认为这与缓存有关。因此,最简单的解决方案是仅克隆图像并将其添加到DOM(重要的是将它的with和height添加到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);

该解决方案在任何情况下均有效。



1

最近,我需要找到宽度和高度来设置.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

PS:您可能会在LightBox或ColorBox等一些插件中找到更多解决方案


1

为了增加Xavi的答案,Paul Irish的github David Desandro的gitgub提供了一个名为imagesLoaded()的函数。以相同的原理工作,并解决了一些浏览器的缓存图像无法触发.load()事件的问题(使用了聪明的original_src-> data_uri-> original_src切换)。

它得到了广泛的使用和定期更新,这使其成为解决该问题的最强大的解决方案IMO。


1
您可以在imagesLoaded此处找到该功能的更新版本:github.com/desandro/imagesloaded
bejonbee 2011年

是的,David Desandro现在正在主持该功能。感谢您提醒我@somethingkindawierd,更新了我的答案。
RobW 2011年

1

这适用于缓存和动态加载的图像。

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

要使用此脚本:

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

演示:http//jsfiddle.net/9543z/2/


1

我已经使用imagesLoaded 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}));
            },

您可以通过传递url,函数及其上下文来使用它。在加载图像并返回创建的图像及其宽度和高度之后执行功能。

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

1

如果图像已被使用,您应该:

  1. 将图像模拟设置为初始

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

  2. 获取尺寸

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


1

您可以使用HTML图像元素的naturalWidth和naturalHeight属性。(更多信息)。

您可以这样使用它:

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

看来这适用于所有浏览器,但版本8及以下版本的IE除外。


是的,不再有IE8:D
雷纳

0

我检查了Dio的答案,它对我很有用。

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

确保您也调用所有函数。在fadeIn()的回调函数中处理图像大小的对象。

谢谢你


0

我使用不同的方法,只是在使用图像对象时对服务器进行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);

?>

1
这不是一个很好的解决方案,并且比其他任何解决方案都要花费更长的时间,因为它会加载AJAX。
Halfpastfour.am 2011年

0

这适用于跨浏览器

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;

干杯!



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

//此代码有助于显示尺寸为200 * 274的图像


0

这是一个跨浏览器解决方案,可在加载所选图像时触发事件:http : //desandro.github.io/imagesloaded/您可以在imagesLoaded()函数中查找高度和宽度。


0

偶然发现此线程试图为我自己的问题找到答案。我正在尝试在加载程序之后的函数中获取图像的宽度/高度,并一直保持为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);
}

0

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

如果可能的话,您还可以在此处添加几行代码。因为链接可能会因时机改变
Tejus Prasad

-1

对于您不想更改原始位置或图像的功能。

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

1
这绝对是行不通的。两者都会返回undefined
Chris Cinelli 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.