POPSブログ

jQuery非同期、Image()で画像読み込み表示

189

  Category:  jquery2012/12/29 pops 

jQueryで、画像読み込み表示には色々な方法はありますが、javascriptの new Image()を使用して表示させる例が多いようです。

 

new Image()での、画像読み込み表示

jQueryで、画像読み込み表示には色々な方法はありますが、javascriptの new Image()を使用して表示させる例が多いようです。ネットで調べれば沢山の情報がありますが、私の場合の経験を踏まえて記述します。
Image()が使用される理由は、


1. 表示サイズではなく画像の実寸を得ることができる。
2. 画像にアクセスして、ロード完了を知ることができる。
3. ERRORの場合の処理ができる。(余り使用はされていないが、、)
4. Loading中の「Loading画像」など表示させる時に便利。
5. jQueryで画像のロードに適したメソッドがない。(ほとんどが、html text などの読み込み用メソッド)


● 追加記事の案内、一括して「複数画像」を読み込む場合は、下記記事を参照ください。(2015/05/14)

【参照】当方の記事: jQuery 非同期、Imageオブジェクトで複数画像を読み込む


画像読み込み表示


Example


「シミュレーション」操作で「INDEX3」の画像URLを異常なURLにすることが試験的に出来ます。
画像をロード出来ない状態になります。「Loading画像」を「クリック」すれば解除されます。


  • INDEX1
  • INDEX2
  • INDEX3


シミュレーション

「INDEX3」の画像URLを間違ったURLにします。画像をロード出来ない状態になります。

「INDEX3」画像URLの切替 : 正常 異常 :初期値 正常


 

new Image()、画像読み込みの基本形


HTMLの例

下記のような構造があり、其の中に画像をロードすると仮定します。


最初、画像がない場合
<div id="image-box"><img /></div>

最初、画像がある場合
<div id="image-box"><img src="images/test1.jpg" /></div>

new Image()使用のJSの例 (javascrpt)

Image()は画像の先読み込み、キャッシュされる。onload イベントハンドラを追加して、ロード完了後「画像表示」処理する。srcに画像URLを設定するのを最後に行うのがコツ。


//画像URL
var url="images/test2.jpg";
//imgPreloaderオブジェクトを作る、名前は任意
var imgPreloader=new Image();
//onloadイベントハンドラ追加
imgPreloader.onload=function() {
	//ロード完了で画像を表示
	$("#image-box").children("img").attr({'src':url});
}
//重要、最後に書く
imgPreloader.src=url;

------------------------------------------------------

現在
.onload=function().............
と書いているが下の記述でもOK
.onLoad=function().............

ここで一番に注意しなければならないのは、onload イベントハンドラなど付随処理を書いてから、imgPreloader.src で最後に画像パスを入れている事です。最後に書かないとIEで(IE6でエラー確認済み)、エラーになる場合があります。
以前ここでエライ苦労した。イベントハンドラの存在をしらしめてから、src を書くということかナ。
1万回位は試しているが、最後に書いて、全ブラウザでエラーは1度もない。(IEは常に不安定だから、常時、最後に書いた方が無難と思う)


以前、Operaで var imgPreloader=new Image(); が機能しなく、下記のようにした事がある、Operaバージョンにより違いあり、現在バージョンは正常に機能する。(2012/12)


//変数を、スクリプト先頭で宣言する
var imgPreloader;

途中略

//imgPreloaderを作る、使いまわしになる
imgPreloader=new Image();

以後同じ

new Image() の正体 (2015/05/14追記)

document.createElement('img') と同じですが、new Image() と書けると言うことだけです。
htmlにappendしない場合はメモリー上の処理になり、「読み込み済み画像」はブラウザに「キャッシュ」されますから、後で利用出来ることになります。
● 画像URLで保存したほうが、後で使い易いのでここでは「画像URL」を保存します。


//Image()オブジェクト名は自由
var img=new Image();

上と下は同じです
var img=document.createElement('img');

オブジェクトに onload onerror 等のイベントを付加できるので

var img=new Image();
img.onload=function(){
	//処理
};
img.onerror=function(){
	//処理
};
img.src="画像URL";

と成る
------------------------------------------------

その他、読み込み中断時の処理をする.onabortがあるが完全に機能するかは不明
img.onabort=function(){
	//処理
};

● 保存画像URLで画像を表示する。divに収容した方が何かと便利です。


空画像の構造があれば
<div id="top-image-box"><img /></div>

次の処理で画像を表示できる、ここではキャッシュがあるので瞬時に表示する
$('#top-image-box').children("img").attr({'src':保存画像URL});

画像を取り替えるなら、別の保存画像URLを入れれば、階層(z-index)が変わること無く瞬時に表示できる
$('#top-image-box').children("img").attr({'src':別の保存画像URL});

画像URLの取得

上記の例では直接スクリプトに書いているが、画像URLは使用者がどこかに潜ませることが多い。


HTMLが次ぎのような場合
<li text="/main/images/toyota_car10.jpg">INDEX1</li>

JSでの取得例、text属性にあるとする(text属性は勝手に作った属性)

img_url=$("URLの記載しているところ").attr('text');
場所などは、設計により違いがあるので、旨く記載する

JSに配列で書いておき、利用することもある

var image_urls=['/main/images/toyota_car10.jpg','/main/images/toyota_car11.jpg',........];
配列番号を利用して、取り込めばよい

これらは使用者の設計で良い方法を決定すればよい

サンプルでの画像URLの取得の例

メニュー、li要素の中に埋め込んでいるので。ボタンがクリックされた時に取得しています。
li要素の中の「text属性」は勝手に作った属性ですが、attr() で読み込みます。一般的には「a要素」を入れて「href属性」で読み出しているのが多いようですが、、、。


HTML
<ul id="tab-menu">
	<li text="/main/images/toyota_car10.jpg">INDEX1</li>
	<li text="/main/images/toyota_car11.jpg">INDEX2</li>
	<li text="/main/images/toyota_car12.jpg">INDEX3</li>
</ul>

JS
//click-action
$("#tab-menu").find("li").click(function() {
	//画像URL取得
	img_url=$(this).attr('text');
});

画像サイズを得る場合

画像ロード完了後、実際の画像サイズを取得できます。其の値を元にリサイズなどの処理を行います。

画像ロード完了以前の値は 0 です。


//画像サイズ格納変数
var img_W,img_H;

途中略

//onloadイベントハンドラ
imgPreloader.onload=function() {

	//画像の実際の大きさを取得、ここでは利用はしていない
	img_W=imgPreloader.width;
	img_H=imgPreloader.height;

	//ロード完了で画像を表示
	$("#image-box").children("img").attr({'src':url});
}


Loading画像を表示する場合

くるくる回るLoading画像などを表示させる場合、事前にLoading用のGIF画像を配置しておき「表示」「非表示」の切り替えをするだけです。
Loading画像収容BOXを、$("#loading") とします。


途中略

//画像読み込みの直前にLoading画像を表示する
$("#loading").css({'display':'block'});

//onloadイベントハンドラ
imgPreloader.onload=function() {

	//ロード完了でLoading画像を非表示にする
	$("#loading").css({'display':'none'});

	//ロード完了で画像を表示
	$("#image-box").children("img").attr({'src':url});
}

上記例では.css({'display':'none'})等とダイレクトに処理しているが、Loading画像はクラスで処理しても良い


ERROR処理

new Image()のERROR処理機能として onErrorがあるので利用できる。但しこれも使用しているのを見たことがない。あれば細やかな処理を書けるが返って面倒になるので使用しないのであろう。実際には onload だけで十分のことが多い。


//onErrorイベントハンドラ
imgPreloader.onerror=function() {
	//画像読み込みERRORの場合の処理を書く
}
onerrorでもonErrorでも機能する

IE8のjQueryでのCSS設定の注意

重要、jQueryでのCSS設定の場合、文字形で設定(設定が1個の時)できるが、IE8で機能しないことがある。
不具合を知ってから、私は全て .css({'display':'block'}) 等の連想配列形で書いている。
IE9 10... とどうなるか予想もつかないので、「連想配列形」で書いたほうが良いと思われる。



CSSの設定が「1個」の時にjQueryでは
.css('display','block');
と、文字形で設定しても良い事になっているが、文字形で設定はIE8で機能しないことがある
(例では'display'としているが、全部確認はしていないので、何処でどうなるかは不明、IE8の気分次第)

よって常に.css() は全て、下記のように連想配列形で記載したほうが無難である
.css({'display':'block'});
.css({'margin':'2px'});
などと、、、
これだと問題なく、すべて設定できる

Microsoftでは、IE8は「標準仕様」にあわせたので、CSSは連想配列形記載だから、連想配列形で書くのが「正当」であるそうです。まあ理屈としては「正当」なんですが、、。


attr()だけでの画像表示


new Image()を利用しないで、attr()だけでも画像の表示、切り替えは出来ますが、細やかな付随処理が出来なくなる。
簡単に作りたい場合に限る。画像取得に失敗すれば何も表示しないだけです。


var img_url="画像URL";
$("画像BOX要素").children("img").attr({'src':img_url});

jQueryでは、こちらが基本的な画像読み込み表示になる。ただ単なる表示ならよいが、使い勝手が悪い。


load()を利用した画像表示


jquery .load() を利用した画像表示であるが、「読み込めないことは無い」と言う程度で、実際に利用しているのは見たことがない。勿論画像サイズの取得は出来ない。画像処理は、上の new Image() 形式が定番である。
参考に記載しておく。ロード完了処理を追加したような形である。



var img_url="画像URL";
$("画像BOX要素").children("img").attr({'src':img_url}).load(function(){
	//処理を書く
});

特殊だから使用しないほうが良い。各要素のloadイベントに関数をbindする、.load(fn) は問題が多いので、jquery1.8 で削除になりました。




サンプル


サンプルのHTML JS CSS


一応、上でのサンプルのJSなどを以下に記載しておきます。(IE6で一部CSS非対応です)


HTML

サンプルでは次ぎのように記述しています。


<ul id="tab-menu">
	<li text="/main/images/toyota_car10.jpg">INDEX1</li>
	<li text="/main/images/toyota_car11.jpg">INDEX2</li>
	<li text="/main/images/toyota_car12.jpg">INDEX3</li>
</ul>
<div id="image-box-base">
	<div id="image-box"><img /></div>
	<div id="loading"></div>
</div>

JS

imgload01.js 必要な設定はJS上部参照。


//imgload01.js
//日本語 画像読み込み表示

(function($){

	$(function () {

		//最初に開く指定場所番号、最初は 0 になる
		var select_no=0;

		//--------------------------------------

		var no=0;
		var keep_no=select_no;
		var img_url="";
		var tabmenu=$("#tab-menu");
		var boxbase=$("#image-box-base");
		var imagebox=$("#image-box");
		var loading=$("#loading");

		loading.css({'display':'none'});
		//指定場所のOPEN
		tabmenu.find("li").eq(select_no).addClass("active");
		img_url=tabmenu.find("li").eq(select_no).attr('text');
		//指定画像を表示
		imagebox.children("img").attr({'src':img_url});

		//click-action
		tabmenu.find("li").click(function() {

			no=tabmenu.find("li").index(this);

			tabmenu.find("li").removeClass("active");
			$(this).addClass("active");

			fade_flag=true;
			//画像URL取得、画像の読み込み
			img_url=$(this).attr('text');
			imgload (img_url);
			return false;

		});

		//loading-click
		loading.click(function() {
			//
			loading.css({'display':'none'});
			//menuを前に戻す
			tabmenu.find("li").removeClass("active");
			tabmenu.find("li").eq(keep_no).addClass("active");
			return false;
		});

		//
		function imgload (url) {

			loading.css({'display':'block'});
			//imgPreloaderを作成
			var imgPreloader=new Image();
			//イベントハンドラ
			imgPreloader.onload=function() {

				loading.css({'display':'none'});
				imagebox.children("img").attr({'src':url});

				keep_no=no;

			}
			//url-Set
			imgPreloader.src=url;
		}

	});

})(jQuery);

JS名、クラス名など修正したい場合は、html js css 共に該当部分を修正ください。自由な名前で設定できます。


CSS

imgload01.css


/* imgload01.css 日本語 */

/* tab-menu  */
ul#tab-menu {
display:inline-block;
list-style:none;
width:100%;
height:20px;
margin:0;
padding:0;
}
#tab-menu li {
display:inline;
list-style:none;
width:60px;
height:20px;
line-height:20px;
font-size:11px;
font-weight:bold;
text-align:center;
margin-right:2px;
border-top-left-radius:5px;
border-top-right-radius:5px;
-moz-border-radius-topleft:5px;
-moz-border-radius-topright:5px;
-webkit-border-radius-top-left:5px;
-webkit-border-radius-top-right:5px;
background-color:#888888;
float:left;
cursor:pointer;/*default*/
}
#tab-menu li.active {
background-color:#EEEEEE;
}
#tab-menu li:hover {
color:#FFFFFF;
background-color:#FF1493;
}

/* image-box-base */
#image-box-base {
position:relative;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
margin:0;
background-color:#000000;
overflow:hidden;
}

/* image-box */
#image-box-base #image-box {
position:absolute;
top:0;left:0;
display:block;
width:640px;
height:300px;
padding:0;
margin:0;
background-color:#FFFFFF;
}
#image-box-base #image-box img {
width:100%;
height:100%;
}

#image-box-base #text-box {
position:absolute;
top:0;left:0;
width:640px;
}
#image-box-base #image-box.close {
display:none;
}
#image-box-base #image-box.open {
display:block;
}

/* loading */
#image-box-base #loading {
display:block;
position:absolute;
top:0;left:0;
width:100%;height:100%;
background:url("/main/images/loading.gif") no-repeat center center;
background-color:transparent;
}

注意、loadingは一般的によく使用されています、他のJSと競合する場合は、ID名を変えるなどの処置をして下さい。


Loading画像など

使用画像は原則、使用者がご用意ください。Loading画像は好きなものが使用可能です。

loading.gif 31x31 :


以上です。

 


[ この記事のURL ]


タグ:memo , photo , jquery

 

ブログ記事一覧



[1]