Отримати реальну ширину та висоту зображення за допомогою JavaScript? (на Safari / Chrome)


278

Я створюю плагін jQuery.

Як отримати реальну ширину та висоту зображення за допомогою Javascript у Safari?

Наступні роботи з 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

Моя думка про це може допомогти вам, протестована в останніх веб-сайтах. stackoverflow.com/questions/318630 / ...
xmarcos

5
@Nosredna, вас може зацікавити функція imagesLoaded, яка запускатиметься навіть у кешованих зображеннях.
bejonbee

7
Правильна відповідь на це питання полягає у простому використанні властивостей naturalWidth та naturalHeight. Не потрібно хакерства.
Девід Джонстоун

Ви також можете зробити саме те, що робите під час завантаження вікна, а не готового документа
user1380540

Відповіді:


356

Веб-браузери встановлюють властивість висоти та ширини після завантаження зображення. Замість використання тайм-аутів я рекомендую використовувати подію завантаження зображення. Ось короткий приклад:

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 .

Ви також можете використовувати атрибути naturalHeightта naturalWidthHTML5.


5
Це розумно, не знав, що ти можеш зробити $ (img) .load ();
SeanJA

3
Крім того , widthі heightвам , ймовірно , слід також видалити min-width, min-height, max-widthі max-heightяк вони можуть також впливати на розміри зображення.
mqchen

5
Рішення FDisk дуже розумне. На жаль, рішення, яке він написав, буде працювати лише в тому випадку, якщо зображення є кешованим або якщо сторінка вже закінчується завантаженням. Якщо зображення не є кешованим або якщо цей код викликався раніше window.onload, висота / ширина можуть бути повернуті 0. У будь-якому випадку, я інтегрував ідею FDisk у рішення вище.
Xavi

5
коли я намагаюся console.log (pic_real_height), я щоразу стає невизначеним. хром, FF, IE9.
helgatheviking

10
Проблема, яка може виникнути тут, полягає в тому, що load()вони будуть виконані асинхронно, тому, якщо ви хочете отримати доступ, widthі heightвони, можливо, ще не встановлені. Замість цього робіть «магію» в load()собі!
daGrevis

286

Використовуйте naturalHeightта naturalWidthатрибути з HTML5 .

Наприклад:

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

Працює в IE9 +, Chrome, Firefox, Safari та Opera ( статистика ).


3
@DavidJohnstone Приклад їх використання може допомогти. Але я згоден, безумовно, заслуговує на те, щоб бути вище.
Стівен

5
Схоже, це не працює в останній версії FireFox (30.0), якщо зображення вже не існує в кеші.
Джоель Кінзель

1
Я згоден з Девідом Джонстоном. Це чудова новина.
jchwebdev

Зауважте, що ще потрібно дочекатися завантаження зображення
Jesús Carrera

Ні, 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 = нульовий теж.
Оміод

1
FDisk не пропонує клонувати зображення jQuery. Він пропонує створити новий Imageоб’єкт, потім перегляне його widthвластивість. Це простий, елегантний підхід. FDisk, ти маєш мій голос. :)
davidchambers

3
Це дуже розумний спосіб уникнути проблем css. На жаль, рішення, як написано вище, працюватиме лише в тому випадку, якщо зображення є кешованим або завантаженням вже закінчено. Якщо зображення не є кешованим або якщо цей код викликався раніше window.onload, можливо повернути ширину 0.
Xavi

1
Я використовую такий підхід на веб-сайті для мобільних телефонів у галереї зображень. Більш великі зображення, ніж роздільна здатність, відображаються зі 100% css і меншими за вихідними розмірами.
FDisk

1
Як згадував Xavi, це не вдається в IE8, а іноді і залежить від кешування зображень. Тож я поєднав його з таким підходом, і він працює ідеально: спочатку зв’яжіть подію завантаження, а потім призначте об'єкту зображення його джерело stackoverflow.com/questions/4921712/…
Кевін К.

16

Основна проблема полягає в тому, що браузери WebKit (Safari і Chrome) паралельно завантажують інформацію JavaScript та CSS. Таким чином, JavaScript може виконуватися до того, як будуть обчислені ефекти стилів CSS, повернувши неправильну відповідь. У jQuery я виявив, що рішення - чекати, поки document.readyState == 'завершено', .eg,

jQuery(document).ready(function(){
  if (jQuery.browser.safari && document.readyState != "complete"){
    //console.info('ready...');
    setTimeout( arguments.callee, 100 );
    return;
  } 
  ... (rest of function) 

Що стосується ширини та висоти ... залежно від того, що ви робите, вам може знадобитися зміщення ширини та зсуву висоти, які включають такі речі, як бордюри та оббивка.


Так, це причина. Кращим рішенням є використання завантаження події jQuery.
Френк Банністер,

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 () працював для мене для цих браузерів. Дякую!
Василь Томояга

11

це працює для мене (сафарі 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 () {}); Дякую! Потрібно повністю завантажити зображення, перш ніж він зможе його прочитати. Звичайно.
Френк Банністер

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
Це найкраще рішення! Він працює навіть у тому випадку, якщо зображення не попередньо завантажене чи кешоване.
березень

6

Як щодо image.naturalHeightі image.naturalWidthвластивості?

Здається, спрацьовує досить багато версій у Chrome, Safari та Firefox, але зовсім не в IE8 або навіть IE9.


у моєму випадку це не працює. даючи мені NaN у відповідь
saadk

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


5

Jquery має дві властивості під назвою naturalWidth та naturalHeight, якими ви можете скористатися таким чином.

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

Де my-img - це ім'я класу, яке використовується для вибору мого зображення.


2
Це не методи jQuery. naturalWidth(та висота) - це властивості об’єкта елемента зображення. developer.mozilla.org/uk/docs/Web/API/HTMLImageElement
sandstrom

3

Як було сказано раніше, відповідь Xavi не буде працювати, якщо зображення є в кеші. Проблема відповідає на те, що 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 плюс рядок запиту, щоб викликати оновлення кешу. Мінус полягає в тому, що він викличе ще один запит на сервер, для імг, який уже є кешованим і повинен бути вже доступний. Дурний вебкіт.

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
Перший блок коду просто отримує розміри елемента в завантаженому DOM, а не самого зображення ...
BasTaller

1
Це саме найшвидше та найефективніше рішення. Ні плагіна, ні хитрості! Я збираюся розмістити аналогічну відповідь, але знайшов вашу.
vantrung -cuncon

2

Як каже Люк Сміт, завантаження зображення - це безлад . Це не надійно для всіх браузерів. Цей факт доставив мені великий біль. Кешоване зображення взагалі не запустить подію в деяких браузерах, тому ті, хто сказав, що "завантаження зображення краще, ніж setTimeout", помиляються.

Рішення Люка Сміта є тут.

І є цікава дискусія про те, як можна поводитися з цим безладом у jQuery 1.4.

Я виявив, що досить надійно встановити ширину на 0, а потім дочекайтеся, коли властивість "завершеного" здійсниться, а властивість ширини стане більше нуля. Ви також повинні стежити за помилками.


Друга посилання у відповідь мертва.
Панг


2

Моя ситуація, мабуть, трохи інша. Я динамічно змінюю src зображення за допомогою JavaScript і потрібно, щоб нове зображення було розмір пропорційно, щоб відповідати фіксованому контейнеру (у фотогалереї). Я спочатку просто видалив атрибути ширини та висоти зображення після його завантаження (через подія завантаження зображення) і скинув їх після обчислення бажаних розмірів. Однак це не працює в Safari і, можливо, в IE (я не перевіряв його в IE ретельно, але зображення навіть не показується, так що ...).

У будь-якому випадку, Safari зберігає розміри попереднього зображення, тому розміри завжди на одному зображенні позаду. Я припускаю, що це має щось спільне з кешем. Тому найпростішим рішенням є просто клонувати зображення та додати його до DOM (важливо, щоб воно було додане до 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

Щоб додати відповідь Хаві, gitub Пола Ірландського Девіда Десандро пропонує гітгуб функцію, що називається imagesLoaded (), яка працює на тих же принципах, і обходить проблему кешованих зображень деяких веб-переглядачів, не запускаючи подію .load () (з розумним original_src -> data_uri -> перемикання original_src).

Він широко використовується та оновлюється регулярно, що сприяє тому, що він є найбільш надійним рішенням проблеми, IMO.


1
Ви можете знайти оновлену версію imagesLoadedфункції тут: github.com/desandro/imagesloaded
bejonbee

Так, Девід Десандро зараз приймає цю функцію. Дякую, що нагадали мені @somethingkindawierd, оновили мою відповідь.
RobW

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 ('ширина', 'початковий'); image.css ('висота', 'початковий');

  2. отримати розміри

    var originalWidth = $ (це) .width (); var originalHeight = $ (це) .height ();


1

Ви можете використовувати властивості naturalWidth та naturalHeight елемента зображення HTML. (Ось додаткова інформація ).

Ви б використовували це так:

//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
Jair Reina

0

Я перевірив відповідь Діо, і це чудово працює для мене.

$('#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

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

Натрапивши на цю нитку, намагаючись знайти відповідь на моє власне питання. Я намагався отримати ширину / висоту зображення у функції ПІСЛЯ навантажувача, і постійно придумував 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>

по можливості ви можете також додати сюди кілька рядків коду. оскільки посилання можуть змінитися через
timw

-1

Для функцій, де ви не хочете змінювати оригінальне розташування чи зображення.

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

1
Це абсолютно не працює. Він повернеться невизначеним для обох
Кріс Сінеллі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.