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

Posted

技术标签:

【中文标题】使用 JavaScript 获取图像的真实宽度和高度? (在 Safari/Chrome 中)【英文标题】:Get the real width and height of an image with JavaScript? (in Safari/Chrome) 【发布时间】:2010-09-24 00:50:21 【问题描述】:

我正在创建一个 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();

但在 Safari 和 Google Chrome 等 Webkit 浏览器中,值为 0。

【问题讨论】:

接受的答案使用图像加载事件。完全有道理,但在可以缓存图像的情况下,结果证明是一个不可靠的解决方案(令我沮丧)。 我对此的看法可能会对您有所帮助,并在最新的 Webkit 中进行了测试。 ***.com/questions/318630/… @Nosredna,您可能对 imagesLoaded 函数感兴趣,即使图像已被缓存,该函数也会触发。 这个问题的正确答案是简单地使用 naturalWidth 和 naturalHeight 属性。无需骇客。 您也可以完全按照您在加载窗口时所做的操作,而不是准备好文档 【参考方案1】:

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提出的一个非常聪明的解决方案。

您还可以使用naturalHeightnaturalWidth html5 属性。

【讨论】:

这很聪明,不知道你可以这样做 $(img).load(); 除了widthheight,您可能还应该删除min-widthmin-heightmax-widthmax-height,因为它们也会影响图像尺寸。 FDisk 的解决方案非常巧妙。不幸的是,他所写的解决方案只有在图像被缓存或页面已经完成下载时才有效。如果图像未缓存或者如果在window.onload 之前调用此代码,则可能会返回高度/宽度 0。无论如何,我已经将 FDisk 的想法整合到了上面的解决方案中。 当我尝试 console.log(pic_real_height) 时,我每次都不确定。铬,FF,IE9。 您可能遇到的问题是load() 将异步执行,因此如果您想访问widthheight — 它们可能尚未设置。而是在 load() 本身中“施展魔法”!【参考方案2】:

使用来自HTML5 的naturalHeightnaturalWidth 属性。

例如:

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

适用于 IE9+、Chrome、Firefox、Safari 和 Opera (stats)。

【讨论】:

@DavidJohnstone 使用它们的一个例子可能会有所帮助。但我同意,绝对值得更高。 这似乎不适用于最新版本的 FireFox (30.0),除非该图像已存在于缓存中。 我同意大卫约翰斯通的观点。这是个好消息。 请注意,您仍然需要等待图片加载 不,clientHeight/clientWidth 明确不做问题所要求的。它需要返回图像的高度和宽度,而不是图像在页面上显示的高度和宽度。 naturalWidth 和 naturalHeight 是正确的。【参考方案3】:


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 创建一个元素并获取创建的对象宽度。

【讨论】:

几个月以来,使用 jquery 克隆图像(使用最新的 Chrome)并获取它的属性,总是返回 0x0 到目前为止,这是唯一有效的解决方案(已经测试了此页面中的所有其他解决方案) 在返回之前,我也设置了 t=null。 FDisk 不建议使用 jQuery 克隆图像。他建议创建一个新的Image 对象,然后查看它的width 属性。这是一种简单、优雅的方法。 FDisk,你有我的投票权。 :) 这是避免css问题的一种非常聪明的方法。不幸的是,上面写的解决方案只有在图像被缓存或已经完成下载时才有效。如果图片没有被缓存或者如果在window.onload之前调用了这段代码,可能会返回0的宽度。 我在图片库中的手机网站中使用了这种方法。更大的图像,然后分辨率以 100% 的 css 和更小的原始尺寸显示。 正如 Xavi 提到的,这在 IE8 中失败,有时取决于图像缓存。所以我把它和这个方法结合起来,效果很好:先绑定加载事件,然后给图像对象分配源***.com/questions/4921712/…【参考方案4】:

在接受的答案中有很多关于如果从 WebKit 缓存加载图像时不会触发 onload 事件的问题的讨论。

在我的例子中,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() 为我工作的那些浏览器。谢谢!【参考方案5】:

根本问题是 WebKit 浏览器(Safari 和 Chrome)并行加载 JavaScript 和 CSS 信息。因此,JavaScript 可能在计算 CSS 的样式效果之前执行,返回错误的答案。在 jQuery 中,我发现解决方案是等到 document.readyState == 'complete',例如,

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 的加载事件。 $(window).load(function() ... ); 帮助了我【参考方案6】:

这对我有用(safari 3.2),通过从window.onload 事件中触发:

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

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

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

【讨论】:

是的!不能从 $(document).ready(function());谢谢!它需要在读取图像之前完全加载图像。当然。【参考方案7】:

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

【讨论】:

这是最好的解决方案!即使图像未预加载或缓存,它也能正常工作。【参考方案8】:

image.naturalHeightimage.naturalWidth 属性呢?

似乎在 Chrome、Safari 和 Firefox 中的很多版本都可以正常工作,但在 IE8 甚至 IE9 中根本不行。

【讨论】:

这在我的情况下不起作用。给我 NaN 作为回报【参考方案9】:

jquery 有 naturalWidth 和 naturalHeight 两个属性,可以这样使用。

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

其中 my-img 是用于选择我的图像的类名。

【讨论】:

这些不是 jQuery 方法。 naturalWidth(和高度)是图像元素对象的属性。 developer.mozilla.org/en/docs/Web/API/HTMLImageElement【参考方案10】:

我们如何在不闪烁真实图像的情况下获得正确的真实尺寸:

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

它适用于

【讨论】:

【参考方案11】:

如前所述,如果图像在缓存中,Xavi answer 将不起作用。该问题响应 webkit 未触发缓存图像的加载事件,因此如果未在 img 标记中明确设置宽度/高度属性,则获取图像的唯一可靠方法是等待触发 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:如果img.src 中已有查询字符串,则必须在parse it 中添加额外参数以清除缓存。

【讨论】:

第一个代码块只获取加载的 DOM 中元素的尺寸,而不是图像本身的尺寸... 这正是最快和最有效的解决方案。没有插件,没有技巧!我将发布一个类似的答案,但找到了你的答案。【参考方案12】:

正如卢克史密斯所说,image load is a mess。它在所有浏览器上都不可靠。这个事实给了我很大的痛苦。缓存的图片在某些浏览器中根本不会触发事件,所以那些说“图片加载比 setTimeout 更好”的人是错误的。

Luke Smith 的解决方案是here.

还有 an interesting discussion 关于如何在 jQuery 1.4 中处理这种混乱。

我发现将宽度设置为 0 非常可靠,然后等待“完成”属性变为真并且宽度属性大于零。你也应该注意错误。

【讨论】:

答案中的第二个链接已失效。【参考方案13】:
$("#myImg").one("load",function()
  //do something, like getting image width/height
).each(function()
  if(this.complete) $(this).trigger("load");
);

来自克里斯的评论:http://api.jquery.com/load-event/

【讨论】:

【参考方案14】:

我的情况可能有点不同。我正在通过 javascript 动态更改图像的 src,并且需要确保新图像的大小按比例调整以适合固定容器(在照片库中)。我最初只是在加载图像后(通过图像的加载事件)删除了图像的宽度和高度属性,并在计算出首选尺寸后重置这些属性。但是,这在 Safari 和可能的 IE 中不起作用(我没有在 IE 中彻底测试过它,但图像甚至没有显示,所以......)。

无论如何,Safari 会保留前一张图片的尺寸,因此尺寸总是在一张图片后面。我认为这与缓存有关。因此,最简单的解决方案是克隆图像并将其添加到 DOM(重要的是,将其添加到 DOM 以获取 with 和 height)。将图像的可见性值设置为 hidden(不要使用 display none,因为它不起作用)。获得尺寸后,删除克隆。

这是我使用 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);

此解决方案在任何情况下都有效。

【讨论】:

【参考方案15】:

现在有一个 jQuery 插件 event.special.load,用于处理缓存图像上的加载事件不触发的情况:http://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js

【讨论】:

【参考方案16】:

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

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

【讨论】:

【参考方案17】:

添加到 Xavi 的答案,Paul Irish's githubDavid Desandro's gitgub offers a function called imagesLoaded() 工作原理相同,并解决了某些浏览器的缓存图像不触发 .load() 事件的问题(聪明original_src -> data_uri -> original_src 切换)。

它被广泛使用并定期更新,这有助于它成为解决问题的最强大的解决方案,IMO。

【讨论】:

您可以在此处找到imagesLoaded 函数的更新版本:github.com/desandro/imagesloaded 是的,David Desandro 现在正在主持这个功能。感谢您提醒我@somethingkindawierd,更新了我的答案。【参考方案18】:

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

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/

【讨论】:

【参考方案19】:

我使用 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)

【讨论】:

【参考方案20】:

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

    将图像尺寸设置为初始值

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

    获取尺寸

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

【讨论】:

【参考方案21】:

您可以使用 HTML 图像元素的 naturalWidth 和 naturalHeight 属性。 (这里有更多info)。

你会这样使用它:

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

这似乎适用于所有浏览器,除了 IE 8 及以下版本。

【讨论】:

是的,没有更多的 IE8 :D【参考方案22】:

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

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

确保调用所有函数。在fadeIn() 的recaller 函数中处理图像大小。

谢谢。

【讨论】:

【参考方案23】:

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

?>

【讨论】:

这不是一个很好的解决方案,由于 AJAX 加载,这将比任何其他解决方案花费更长的时间。【参考方案24】:

这适用于跨浏览器

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;

干杯!

【讨论】:

【参考方案25】:

另一个建议是使用imagesLoaded plugin。

$("img").imagesLoaded(function()
alert( $(this).width() );
alert( $(this).height() );
);

【讨论】:

【参考方案26】:
$(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 尺寸的图像

【讨论】:

【参考方案27】:

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

【讨论】:

【参考方案28】:

偶然发现这个线程试图为我自己的问题找到答案。我试图在加载程序之后的函数中获取图像的宽度/高度,并不断提出 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);

【讨论】:

【参考方案29】:

在 github 中查看这个存储库!

使用 Javascript 检查宽度和高度的好例子

https://github.com/AzizAK/ImageRealSize

---一些cmets要求编辑..

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>

【讨论】:

如果可能的话,你也可以在这里添加几行代码。因为链接可能会随着时间而改变【参考方案30】:

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

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

【讨论】:

这绝对行不通。它将为两者返回未定义

以上是关于使用 JavaScript 获取图像的真实宽度和高度? (在 Safari/Chrome 中)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JavaScript 获取图像大小(高度和宽度)?

使用 JQuery 获取图像的真实尺寸

JavaScript获取html元素的实际宽度和高度

js和jquery如何获取图片真实的宽度和高度_javascript技巧

获取在 JavaScript 中加载的图像的宽度

获取图像宽度高度javascript