Back to Top
Room A
WEB - JavaScript
  • Twitter
  • Facebook
  • Pinterest
  • Hatena
  • instagram
  • YouTube

JavaScript : 画像ビューワ : Ver.2.00【拡大・縮小表示対応版】

2014.12.05

先のJavaScript 画像ビューワ Ver.1.00 を元にして閲覧者のブラウジングサイズに合わせた画像の拡大・縮小表示機能を追加しました。(※モバイル端末には非対応)

元々は、当サイトのブログ( Room B )で使用している WordPress に組み込む為に書いたプログラムですが(※現在は Viewer.js を使用)、HTML と JavaScript で構成されているので、WordPressに限らず一般のHTMLページでも動作します。

WordPress に Lightbox風の画像ビューワを実装するのに一番簡単な方法は、公開されている WordPress向けのプラグイン、もしくは Viewer.js などを使用する事ですが、自分で調べた限りでは、記事(画像)を投稿する際に画像をメディアファイルとして WordPress経由で画像をアップ、登録しておかないと、後からプラグインを組み込んでも正しく機能しないモノが殆どでした。

これは、WordPress の記事に埋め込まれた画像は、記事の本文(ID)とデータベース(DB)内でリンクされており、プラグインはこのDBを参照して格納先の画像を呼び出し、Lightbox風の画像表示を行う仕様だからです。

WordPressのようなCMS(Content Management System)を使うのであれば、全ての情報をDBで管理するのが当然なのですが、個人的にメディアファイル投稿が面倒で画像情報のDB登録も行っていませんでした。なので、エントリー数が150件を超えた段階で後からプラグインを使ってのLightbox風画像ビューワの実現は困難であり、現実的で無いと判断しました。

が・・・、それでもやはりブログ内の画像をクリックする度にページ遷移したり別タブが増えるのはアレなので、何とかメディアファイル投稿をしなくても Lightbox風画像表示が出来ないモノかと...(゚ー゚*)。oO

色々と調べて考えた結果、JavaScriptに必要なパラメータを与える(投げる)事さえ出来れば後はどうにかなりそうだったので、記事内の画像リンクのほうを全て修正して強引に実現しました。

投稿済みの全ての画像をメディアファイルとして再投稿する場合は本文側の修正・編集・調整も必要となりますが、本文内の画像リンク(<a>タグ)だけなら何とかなるかなと・・・。(それでも数千箇所の修正が必要になりましたがw)

ついでに画像リンク情報の記述(書式)も統一化し、後からでも疑似ギャラリー表示機能も実装可能な様にHTMLを一工夫しました。(※今回は実装していません)

処理の流れ

コードの大部分は以前に書いた Ver.1.00 を流用し、処理手順・内容ともほぼ同じです。

相違点は本文内の<a>タグからJavaScriptにリンクさせている点と、表示画像を閲覧者のブラウジング環境(サイズ)に合わせて拡大・縮小表示するようにコードを追加しています。

  • 本文内の画像(img要素)を<a>タグでマークアップ
  • 画像(img要素)のonclick でdivをblock化
  • 同時に<a>タグに記述したパラメータ(ディレクトリ名・ファイル名)をJavaScriptに投げる
  • 受け取ったパラメータを元にオリジナルサイズの画像を呼び出し
  • ブラウザの表示可能領域と画像サイズを比較、拡大・縮小の必要性をチェック
  • 非表示のdiv要素に呼び出した画像をimgをアタッチ
  • 非表示divを表示

フルサイズの実体画像を<img src="ディレクトリ+ファイル名">で呼び出し、CSSで縮小表示しています。

一般的には縮小表示専用のサムネイル画像を用意するところですが、画像レイアウトや画像の入れ替え等が面倒になるのでサムネイル画像を別途用意していません。

この方法は元の画像データが大きい場合、ページの読み込みに時間が掛かり表示が遅くなる(閲覧側のPC性能・通信環境に依存)ので、予め画像データの軽量化を図るなどしてデータサイズに留意する必要があります。

画像格納先ディレクトリは、1つのエントリー(記事)に対して1つのディレクトリとする必要は有りませんが、少なくとも画像の上位ディレクトリは共通にしておかないと、本文にリンクを記述するのが大変になり JavaScript での処理が複雑になります。

今後は、モバイル端末によるブラウジングへの対応も必要となってきますが、WEBページでの縮小表示もクリックによる拡大表示も、基本的には端末の表示幅(もしくは方向)を基準として JavaScript や CSS で縮小・拡大比率を調整・指定するだけなので改編も難しくはない...ハズです。

imgv_200_sample.html : CODE

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Lightbox風 画像ビューワ : Ver.1.01【拡大・縮小表示対応版】サンプル</title>
<link rel="stylesheet" type="text/css" media="all" href="like_lightbox_200.css">
</head>

<body>
<h3>Lightbox風 画像ビューワ : Ver.1.01【拡大・縮小表示対応版】サンプル</h3>
<div id="content">
<p>下の3つの画像は元サイズがwidth="800"ピクセルです。<br>
クリックするとブラウザのサイズに合わせて拡大・縮小表示されます。</p>
<p>
<a class="sample2" onclick="return Simg('sample2','01.jpg');">
<img src="img/sample2/01.jpg" width="800" height="639" alt="DANBOARD + Mac" class="resize200">
</a>
<a class="sample2" onclick="return Simg('sample2','02.jpg');">
<img src="img/sample2/02.jpg" width="800" height="639" alt="DANBOARD + Win" class="resize200">
</a>
<a class="sample2" onclick="return Simg('sample2','03.jpg');">
<img src="img/sample2/03.jpg" width="800" height="639" alt="DANBOARD in Mac" class="resize200">
</a>
</p>
<p>この画像は元のサイズが width="1024"です。クリックすると原寸大で表示</p>
<p>
<a class="sample2" onclick="return Simg('sample2','120213-1.jpg');" style="display:block; width:530px;">
<img src="img/sample2/120213-1.jpg" width="1024" height="683" alt="DANBOARD with Snow-man" class="resize500">
</a>
</p>
</div>
 
<div id="imglay">
<div onClick="return Limg()"><img id="img_view" src="" style="border: 15px solid #FFFFFF;"></div>
<div id="img_close">
<a href="javascript:void(0)" onClick="return Limg()">
<img src="img/close.png" alt="CLOSE" title="CLOSE"></a>
</div> 
</div>
 
<script>
function Simg(d,n){
	document.getElementById('imglay').style.display='block';
	var img_dir = 'img/' + d + '/';
	var img_num = n;
	var img_file = img_dir + img_num;
	document.getElementById('img_view').src = img_file;   //表示画像
 
/*------------------------------------------画像サイズ・表示サイズ制御*/
 
	if(document.all){
		Ws = document.documentElement.clientWidth;   //表示領域取得 (IE8:標準モード)
		Hs = document.documentElement.clientHeight;
		//Ws = document.body.clientWidth;            //表示領域取得 (IE6.7:互換モード)
		//Hs = document.body.clientHeight;
	}else{
		Ws = window.innerWidth;  //表示領域取得
		Hs = window.innerHeight;
	}
 
	img_F = new Image();
	img_F.src = img_file;
	img_W = img_F.width;
	img_H = img_F.height;
	mg_prop = img_W / img_H; //画像縦横比率
 
	if( img_W <= 800 ){
		if(Ws*0.8 >= img_W && Hs*0.8 >= img_H){  //Ws=80% Hs=80%基準
			imgTru();
		}else if(Ws*0.8 < img_W || Hs*0.8 < img_H){
			img_resW = Math.ceil(Ws * 0.8);                       //image Wサイズ優先
			img_resH = Math.ceil(img_H * (img_resW / img_W));     //画像:Hサイズ比率適用
			if(img_resH >= Hs * 0.8){
				img_resH = Math.ceil(Hs * 0.8);                      //image Hサイズ優先
				img_resW = Math.ceil(img_W * (img_resH / img_H));    //画像:Wサイズ比率適用
				imgRes();
			}else{
				imgRes();
			}
		}
	}else{
		imgTru();
	}
}
 
function imgRes(){
	document.getElementById('img_view').style.width = img_resW +'px';
	document.getElementById('img_view').style.height = img_resH +'px';
}
function imgTru(){
	document.getElementById('img_view').style.width = img_W +'px';
	document.getElementById('img_view').style.height = img_H +'px';
}

function Limg(){
	document.getElementById('imglay').style.display='none';
}

</script>
</body>
</html>

ほぼ上記のコードのまま、実際にこのサイトのブログ( Room B )に実装しています。

WordPressに組み込む場合は記事内の画像リンク箇所を修正し、テンプレートファイルに(自分は footer.php に記述)【div id="imglay"】で囲まれた部分とJavaScriptのコード全てを追記します。

ただし、画像リンクの書式が決まっているので後付けの場合は全エントリーの修正が必要になり、記事数が多ければ多いほど大変な作業になるのでプラグインのように簡単・お手軽に機能拡張...というワケには行きませんが、こういう方法も有るよ、という参考にでもなればと思います。

 

解説・注意点

コードのポイントなど・・・(´・ω・`)

画像の拡大・縮小表示部分のスタイルシートについてはコチラのページを参照して下さい。
※今回はスタイルシートは別ファイルにしています。

画像リンクの記述

<a class="sample2" onclick="return Simg('sample2','01.jpg');">
<img src="img/sample2/01.jpg" width="800" height="639" alt="DANBOARD + Mac" class="resize200">
</a>

HTML本文内に記述した画像部分のコードです。

普通は(?)アンカーポイントを示す <a> タグを使う場合、href属性を記述するのですが <img> タグで実体ファイルを呼び出しているので href属性は必要なく、JavaScriptへのリンクのみとなっています。

JavaScriptに投げるパラメーターはディレクトリ名と画像ファイル名のみとしていますが、OSやブラウザが対応している画像形式であれば、どんな画像でも問題ないハズです。

※一部のサイトでは<a>タグにはhref属性が無いとW3CのHTMLバリデーション・チェックに引っ掛かるとか、SEO的に不利とか書かれていましたが、実際はそんな決まり事は無いので安心してして下さい。

<a>タグの class="sample2" は画像の格納先ディレクトリ名をそのままクラス名にしています。

これは将来的にギャラリー風画像表示を実現する際に【getElementsByClassName】を使えば処理が簡単になると考えたからで、同一階層に同一ディレクトリ名が存在する事は、システム的に絶対有り得ないので直感的にも判りやすくてベターかなと・・・。

ブロックレベル要素の範囲指定

<a class="sample2" onclick="return Simg('sample2','120213-1.jpg');" style="display:block; width:530px;">

基本的に<a>タグはinline要素なのですが、1行に大きく画像を1枚表示する場合は display:block; としてブロックレベル要素として範囲指定をしないと1行分すべてがクリック可能な範囲となってしまいます。

実際に使用する際には、ブログやサイトのレイアウトによって表示画像サイズとブロックレベルの範囲を変更する事になると思うので適宜変更して下さい。

 

ブロックレベル要素の範囲指定

var img_file = img_dir + img_num;
document.getElementById('img_view').src = img_file;   //表示画像

ページに配置された画像をクリックする事で投げられるパラメーターを元にして画像ファイルを特定しています。

変数の img_file は、後の画像拡大・縮小表示でも必要となるので、今回はディレクトリ名とファイル名の情報を一つの変数にまとめて処理しています。

 

ブラウザの表示領域取得

	if(document.all){
		Ws = document.documentElement.clientWidth;   //表示領域取得 (IE8:標準モード)
		Hs = document.documentElement.clientHeight;
		//Ws = document.body.clientWidth;            //表示領域取得 (IE6.7:互換モード)
		//Hs = document.body.clientHeight;
	}else{
		Ws = window.innerWidth;  //表示領域取得
		Hs = window.innerHeight;
	}

ユーザーのブラウジングサイズを取得します。

例によってIE8がぁ・・・ヽ(´o`;
なのでこの様な事になっています。

場合によってはスクロールバーも含んだ領域を取得する必要があると思いますが、その場合には検索して適宜書き換えて下さい。(※IE6・7については、既にサポートの必要が無いかも?ですが一応・・・)

 

画像の縦横比

	img_F = new Image();
	img_F.src = img_file;
	img_W = img_F.width;
	img_H = img_F.height;
	mg_prop = img_W / img_H; //画像縦横比率

対象画像のW・Hサイズの取得、画像の縦横比を取得しています。
確実に取得できるように new を使い、先の変数:img_file をソースとして指定しています。

今回、画像の縦横比率は必要ありませんが、備忘録代わりに・・・。

 

表示画像の拡大・縮小

	if( img_W <= 800 ){
		if(Ws*0.8 >= img_W && Hs*0.8 >= img_H){  //Ws=80% Hs=80%基準
			imgTru();
		}else if(Ws*0.8 < img_W || Hs*0.8 < img_H){
			img_resW = Math.ceil(Ws * 0.8);                       //image Wサイズ優先
			img_resH = Math.ceil(img_H * (img_resW / img_W));     //画像:Hサイズ比率適用
			if(img_resH >= Hs * 0.8){
				img_resH = Math.ceil(Hs * 0.8);                      //image Hサイズ優先
				img_resW = Math.ceil(img_W * (img_resH / img_H));    //画像:Wサイズ比率適用
				imgRes();
			}else{
				imgRes();
			}
		}
	}else{
		imgTru();
	}

ブラウジングサイズに合わせて対象画像を拡大縮小する処理です。

ターゲット画像ファイルのW・Hを取得し、ブラウザの表示領域に合わせてスタイル指定で拡大・縮小を行っています。

一番先頭の条件判定は、自分が横:800ピクセルの画像を基本サイズとしている為で、横:800ピクセル以上の画像はそのまま表示するようにしています。

その際はブラウザの表示領域次第で画像全体が表示されませんが意図的に実サイズで表示する必要が有る画像もブログに含まれているのでこの様な処理にしています。

表示可能領域の縦横各80%を基準として、このサイズより大きな画像は縮小し、表示可能領域の80%より小さな画像はそのまま表示しています。
80%という数字もサイトによって最適な数値は変わって来ると思いますのでデザインやレイアウトに合わせて変更して下さい。

縮小表示判定は最初に横(W)方向のサイズについて行い、同じ縮小比率を縦(H)方向に適用しています。(自分は ceil で画像ピクセルを整数化しています)

横長画面で横長画像のみの表示を行うだけであればこの処理だけで済むのですが、横長画面で縦長画像を表示する場合も考えられ、画像のサイズによっては縮小しても縦方向の表示領域をオーバーする事も有り得ます。(例えば正方形の画像等)

なので横方向の縮小比率を縦方向に適用した後、縦方向の表示領域をオーバーしていないか再度チェックしています。

このチェックで縦サイズの表示領域をオーバーしている場合は、縦方向の縮小を優先してその縮小比率を横方向に適用しています。

最初は横長ブラウジングか?縦長ブラウジングか?横長画像か?縦長画像か?・・・などと細かく条件分岐させていましたがダラダラと長いコードになってしまったので、最終的には単純にブラウザの表示領域をオーバーしているか否かのみで判定を行う処理にしました。

実際にWordPressに記事を投稿する際は、色々なサイズの画像が混在すると思いますが先のコードで最低限の見栄えは整えられると思います。

最初からメディアファイル投稿をしておけばこんな苦労はしなくて良いのでしょうが・・・後悔先に立たずです(´・ω・`)