質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.74%

  • JavaScript

    15231questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    6307questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Monaca

    940questions

    「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

  • Cordova

    406questions

    Cordovaは様々なデバイスで使うことができるオープンソースなモバイル用開発プラットフォームです。開発者に各デバイスの元のプラットフォームで開発する必要をなくし、HTML・JavaScript・CSSなどの一般的なウェブのテクノロジーを使ってすべてのデバイスで展開することができるモバイルのアプリケーションを生成することを可能にします。

JavaScript(jQuery)で画像のオリジナルサイズを取得したい

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 258

agepan

score 53

現在Monacaを使ってアプリを開発しております。

アプリの中で画像のオリジナルサイズを取得したいと思い、以下のコードにて試していますが、正しい画像サイズを取得できません。

var array = ['image01.jpg''image02.jpg''image03.jpg'];

for (var i = 0; i < array.length; i++) {

  var path  = array[i];
  var image = new Image();

      image.onload = function () {
        var imageWidth  = image.width ;
        var imageHeight = image.height ;
      }

      image.src = path;

      alert(imageWidth + 'x' + imageHeight);
}


実際の画像サイズは2000x1500pxであるにもかかわらず、上記コードを用いて取得した結果は1124x1999pxとなり、画角も異なります(この値は画像によって異なります)。

iPhoneで動作確認を行っているのですが、iPhoneの画面画角に変形されているようにも思えますが、これも画像によって異なります。正しい画像サイズを取得できる方法お分かりの方いらっしゃいましたらよろしくお願いいたします。

コードを書くにあたって参考にしたページはこちらです。
https://lab.syncer.jp/Web/JavaScript/Snippet/35/

 追記

上記コードになる前に書いていたのが下記のコードです。

上記コードでは省いておりましたが、一連の画像を読み込む前に、別の画像(下記 画像A=「image_A.jpg」)を読み込んでおり、その次に上記コードと同じくfor文で画像(画像B=「image_B1〜B3.jpg」)を読み込んでいます。

画像Aは正しく読み込んで画像サイズを取得するのですが、その次の画像Bに関しては画像サイズが0となって正しく取得できません。

画像Bの方の変数名を変更しても同様で、同じようなコードなのになぜ画像Aが正しく読み込め、画像Bが正しく読めないのか分かりません。画像を何らか先に読み込む必要があるのか?と思い、調べて試してみたのが先に投稿しました上記のコードとなります。

// 画像Aの読み込み-----------------------------------------------------------------------

var image       = new Image();
    image.src   = 'image_A.jpg';
var imageWidth  = image.width;
var imageHeight = image.height;

alert(imageWidth + 'x' + imageHeight); // ←「2000x1500」など、正しい画像サイズを取得できる


// 画像B1〜B3の読み込み------------------------------------------------------------------

var array = ['image_B1.jpg', 'image_B2.jpg', 'image_B3.jpg'];

for (var j = 0; j < array.length; j++) {

  var image       = new Image(); // ←変数名を上と変えて「image2」としても「0」を取得します
      image.src   = array[j];
  var imageWidth  = image.width;
  var imageHeight = image.height;

  alert(imageWidth + 'x' + imageHeight); // ←結果は「0x0」と画像サイズを取得できない

} 

 追記2

先のコードを調整してみました。実際にはこれをfor文で囲み、複数画像を順繰りと舐めて画像サイズを取得したいと考えております。

var image = new Image();
    image.src = 'image.jpg';
    image.onload = function (){ // 引数に「image」を入れても同じ
      var imageWidth = image.naturalWidth;
      var imageHeight = image.naturalHeight;
      alert(imageWidth + 'x' + imageHeight);
    }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • turbgraphics200

    2018/04/28 09:30

    全角になっているところを半角に修正して。

    キャンセル

  • kei344

    2018/04/28 12:19

    まだ質問が「受付中」になっていますが、「ベストアンサー」を選び「解決済」にされてはいかがでしょうか。

    キャンセル

回答 5

checkベストアンサー

+4

for (var i = 0; i < array.length; i++) {

  var path  = array[i];
  var image = new Image();
//...
}


↑ループの周回ごとにimage変数が書き換えられます。
もしonloadイベントが起きる前にループが終わるなら、

      image.onload = function () {
        var imageWidth  = image.width ;
        var imageHeight = image.height ;
      }


↑ここで参照しているimageは、想定しているものと異なっている可能性があります。
 
対策ですが、クロージャを作るか、letを使うなどしてブロックスコープを使うか、またはイベントターゲットの束縛を受けているthisを使ってみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/28 09:13

    ご回答ありがとうございます。
    出力結果をよく確認すると、取得された正しくない画像サイズは、その前に読み込んでいた別の画像のサイズをそのまま引っ張ってきていることが原因だと分かりました。ご指摘の通り「image」が想定と違うものを読んでいたようです。コードを追記させていただきましたので、一度目を通して頂けますと幸いです。

    キャンセル

  • 2018/04/28 09:23

    追記のコードについては、ロードが終わっていないのが原因だと思います。頭書のコードのとおり、イベントを拾った方がよいのでは。
    image_A.jpg が正しく取得されるのは、なぜなのか分かりませんが……

    キャンセル

  • 2018/04/28 10:32

    追記と同様のコードを試してみましたが、分かったことは以下のとおり。

    ・Aのコードでも画像がキャッシュされていなければ、0x0になる。
    ・Bのコードでも画像がキャッシュされていれば、サイズが表示される。
    ・Bのコードでキャッシュされているものといないものを混在させると、キャッシュされているものだけサイズが表示される。

    以上のとおり、追記のコードの現象はループ構造とは関係ないと思います。

    キャンセル

  • 2018/04/28 10:38

    ありがとうございます、コメント拝見して気付きましたが、画像Aに関しては別画面で一旦読み込んでおりました。現在課題となっているのはそれとは別の画面での処理なのですが、おそらく画像Aは先に読んでいたキャッシュから画像サイズを取得し、どの画面でも読み込んでいなかった画像Bに関しては取得できなかった、ということだと思います。やはり画像が完全に読み込まれてからでないとサイズは取得できないようですね。

    キャンセル

  • 2018/04/28 10:42

    ご解決されたようで何よりです。
    その他、ご不明な点があればコメントしてください。

    キャンセル

  • 2018/04/28 12:47

    先のコードに戻るのですが、onloadで読み込んでから画像サイズを取得できるかなと思い、【追記2】のようなコードを書いたのですが、結果がundefinedとなってしまいます。このコードで問題ありそうな部分など分かりますでしょうか?

    キャンセル

  • 2018/04/28 12:55

    それは引数に「image」を入れた時だと思いますが、イベントハンドラの第1引数は event オブジェクトですから、想定されているようなオブジェクトを受け取ることはできません。繰り返しになりますが、this を使うなどしてください。または、event.targetでも動くかもしれません。

    キャンセル

  • 2018/04/28 13:35

    「回答4」に記したコードに書き換えることで無事に取得できました!ありがとうございます!

    もう一つよければお尋ねしたいのですが、onloadで画像を読み込んでから画像サイズを取得する処理に入りますが、この処理が完了するのを待つことなく、後ろ(下)に書いている続きのコードが実行されてしまうのですが、画像サイズ取得完了してから続きに書いたコードを実行させるスマートな方法はあるんでしょうか?

    キャンセル

  • 2018/04/28 13:40

    それは難しいので、続きのコードを別の関数の中につめこんで、onloadのハンドラの中からその関数を呼び出して実行するようにするしかないと思います。

    キャンセル

  • 2018/04/28 13:44

    なるほどやはりそうですか、では別関数化させて続きの処理をさせてみようと思います。どうもありがとうございました!

    キャンセル

  • 2018/04/28 13:54

    あ、promise と async/await という方法がありましたね……
    IEで動作しないのが難点ですが、ご興味があれば。
    https://sbfl.net/blog/2016/07/13/simplifying-async-code-with-promise-and-async-await/

    キャンセル

  • 2018/05/10 21:39

    ありがとうございます、参考になります。
    Monacaの環境ですとiOSとAndroidで対応していれば大丈夫ですので、上記勉強させて頂きます!

    キャンセル

+2

naturalHeight、naturalWidthプロパティを使ってください。https://developer.mozilla.org/ja/docs/Web/API/HTMLImageElement

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/27 17:56

    ご回答ありがとうございます。最初naturalWidth、naturalHeightを用いていたのですが、結果が変わりませんでしたので、いろいろいじって現在のimage.widthとimage.height指定に行き着いております。

    キャンセル

  • 2018/04/27 17:59

    どういうコードを書いていたのでしょうか?
    提示コードではそもそもエラーになって動かないのでは?

    キャンセル

  • 2018/04/28 09:14

    コードを追記させていただきました。お目を通して頂けますと幸いです。

    キャンセル

+1

Promise.all() を使え」といわれそうですが。

'use strict';
const getImgNaturalSizeAll = (() => {
  function handleLoad (event) {
    const img = event.target,
          map = this.map;

    map.set(img.getAttribute('src'), {naturalWidth: img.naturalWidth, naturalHeight: img.naturalHeight});

    if (this.size === map.size) {
      this.resolve(map);
    }
  }

  return function getImgNaturalSizeAll (imgList, resolve) {
    const map = new Map,
          doc = document;

    for (let fileName of imgList) {
      const img = doc.createElement('img');

      img.src = fileName;
      img.addEventListener('load', {handleEvent: handleLoad,size: imgList.length, map: map, resolve: resolve}, false);
    }

  };
})();

function resolve (map) {
  console.log(JSON.stringify([...map]));
}

getImgNaturalSizeAll(['https://placehold.jp/4000x4000.png','https://placehold.jp/1000x1000.png', 'https://placehold.jp/150x150.png'],resolve);  // [["https://placehold.jp/4000x4000.png",{"naturalWidth":4000,"naturalHeight":4000}],["https://placehold.jp/1000x1000.png",{"naturalWidth":1000,"naturalHeight":1000}],["https://placehold.jp/150x150.png",{"naturalWidth":150,"naturalHeight":150}]]

※「ファイル名の配列」とMapの順序性保持はさぼりました。
上の結果ではたまたま一致していますが、保証しません。

※このコードは既存のdocumentにあるimg要素ノードに適用できない点で汎用性がありません。img要素ノードの配列を渡す設計にすると、NodeListも渡せるようになるのでそれなりに便利です。

Re: agepan さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/10 21:43

    回答遅れまして申し訳ございません。
    わざわざコードを書いて頂きましてありがとうございます!
    今回は今までに頂きました情報と、それをなんとかコードを弄くり回しまして実装することができました。たださらに優れたコードを取り入れたいと思いますので、頂きましたコードは今現在行っている作業が終わり次第、貴重な勉強材料として確認させて頂きます。ありがとうございました!

    キャンセル

0

Jquery未使用でも簡単に取得できます。

// オリジナル画像サイズを取得
const getOriginalSize = () => {
  const img = document.getElementsByClassName('fn-imageSize')[0];
  const imgSizeWidth = img.naturalWidth;
  const imgSizeHeight = img.naturalHeight;
  console.log(imgSizeWidth);
  console.log(imgSizeHeight);
}

window.addEventListener('load', getOriginalSize, false);


------ 複数要素取得したい時 ------

// オリジナル画像サイズを取得
const getOriginalSize = () => {
  const img = document.getElementsByClassName('fn-imageSize');
  // 取得したNodeListを配列化する
  const images = [].slice.call(img);
  images.forEach(function(item) {
    const imgSizeWidth = item.naturalWidth;
    const imgSizeHeight = item.naturalHeight;
    console.log(imgSizeWidth);
    console.log(imgSizeHeight);
  });
}

window.addEventListener('load', getOriginalSize, false);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/28 12:55

    ご回答ありがとうございます!
    > const img = document.getElementsByClassName('fn-imageSize')[0];
    この部分はHTML上にある画像を差していると思いますが、画像をファイルパスで指定することでも可能でしょうか?

    キャンセル

0

このようなコードにすることで無事取得できました。

var image = new Image();
    image.src = 'image.jpg';    

    image.onload = function (){
      var imageWidth = this.width;
      var imageHeight = this.height;
      alert(imageWidth + 'x' + imageHeight);
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.74%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    15231questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    6307questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Monaca

    940questions

    「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

  • Cordova

    406questions

    Cordovaは様々なデバイスで使うことができるオープンソースなモバイル用開発プラットフォームです。開発者に各デバイスの元のプラットフォームで開発する必要をなくし、HTML・JavaScript・CSSなどの一般的なウェブのテクノロジーを使ってすべてのデバイスで展開することができるモバイルのアプリケーションを生成することを可能にします。