Wonderful! WordPress

いまさらのスクロールするとアニメーションで現れる、の独り言

Page No.2

ひとつすっきりしたところで。
動かす要素をクラスで指定して、それで取得したオブジェクトをスクロールイベントが発生するたびに全部をぐるぐるとループさせているのです。10個ぐらいならそんなに重くもならなさそうだけれど・・・。このページも6個ですがそんなに負荷が大きくかかっているような感じはしないような・・・。
でも、それが30、40個とか、いやいや100個以上とかになったらかなり負荷が大きそうでページの動きがごりごりになってしまいそうな気もしないでもない。
実際のところ、自分がこれを施そうと思っているページは画像のページであり、その画像をスクフワッ!効果で出現させようかと考えているわけで、たいてい30枚~50枚ぐらいの画像があるのですね。これね~、なんか重くなってしまいそうで。
ちょっと考えてみると、それぞれの要素のスクフワッ!効果に必要な情報だけをあらかじめ配列に取り出しておいて、それをスクロールイベントでループさせれば負荷が減らせるのではないだろうかと。
必要な情報というのはページ上端からの位置情報、持っているclass、ぐらいなものですし。あとは、全ての要素をループさせるのではなく、必要な部分だけということを考えるなら、それを可能にするための要素が今、表示されているか隠されているかのフラグぐらいでしょうか。
たとえば実際に、要素のオブジェクトと、値が一桁の数字1つの配列ではどれだけループさせるのに違いがあるかということを知りたくなる。
このスクフワッ!効果は、この頃に作ろうとしていた新たな画像ページに適用させたいと思っていたもので、実はこの記事を書いている現段階ではすでにそのページは出来上がっているのです。で、そのページにおいて色々試している時に実行したベンチマークがこれです。ローカルな環境でやってます。おわかりのとおりjQuery

//オブジェクトと簡単な配列をループさせる時のベンチマーク
jQuery( function() {
	var startTimea,
		startTimeb,
		bench = 0,
		benchb = 0,
		pimgalist = new Array(),
		benchtest = new Array();
	
	// ページに表示させている画像が個々に入っている親boxがpimga
	// 今回は40個ありそのオブジェクトを配列に格納
	// 画像があると読み込みに負荷がかかりそうなのでこの場合は画像は指定せず空
	// それと同じ数の要素数の値が1の配列も作る
	if ( jQuery( '.pimga' ).length ) {
		jQuery( '.pimga' ).each( function( i, o ) {
			pimgalist[ i ] = jQuery( o );
			benchtest[ i ] = 1;
		});
	}

	startTimea = new Date();
	while ( bench < 10000) {
		var offset;
		jQuery.each( pimgalist,  function( i, o ) {
			offset = pimgalist[ i ].offset();// 要素の縦位置を取得
		});
		if ( 9999 === bench ) {
			var endTimea = new Date();
			//startTime から endTime までの処理時間をミリ秒で出力。
			console.log(endTimea - startTimea + "ms");
		}
		bench++;
	}

	console.log( pimgalist.length );

	startTimeb = new Date();
	while ( benchb < 10000) {
		var offsetb;
		jQuery.each( benchtest,  function( i, o ) {
			if ( 1 === benchtest[ i ] ) {
				offsetb = benchtest[ i ];
			}
		});
		if ( 9999 === benchb ) {
			var endTimeb = new Date();
			//startTime から endTime までの処理時間をミリ秒で出力。
			console.log(endTimeb - startTimeb + "ms");
		}
		benchb++;
	}
} );
JavaScript
CopyExpand

オブジェクトの方はその縦位置を取得し、配列の方は何の処理もさせていないので、その部分でもかなりハンデがあるようには思います。ローカルな環境でFireFoxChrome でそれぞれ三回づつやってみました。

objectarray
FireFox11428ms14ms
FireFox21435ms13ms
FireFox31449ms13ms
Chrome14231ms28ms
Chrome24270ms26ms
Chrome34477ms29ms

まっ!1万回まわしていますからね。
でも、こうなると予想以上に重いようにも思えるし、そして、予想外にChrome よりもFireFox の方がかなり速いということですね。確かChrome の方が速さには定評があったはずではなかったか。

と、いうことで、考えていた必要な情報だけをあらかじめ配列に入れておいてそれをループで回すということにしたのです。
とりあえず今、考える題材としては自分のメインの鳥画像ページ。と言ってもこの記事を書いている時にはすでにそのページのスクフワッ!は稼働してます。スクロールしていくと画像が少し横にスライドしつつ現れてきます。ご興味があればここへ。
このページはjQuery は使用しておらずjavascript であり、画像のタグ<img>はそれぞれ個々に親ボックスの<span>に入っていて、それのclass'pimga''pimgb'の2種類。こんな具合。

<p>
	<span data-img="2019/12/1912150129.jpg" class="pimga">
		<img itemprop="image" src="/wp-content/uploads/2019/12/1912150129-500x333.jpg" alt="Gadwall" width="500" height="333" class="aligncenter size-medium wp-image-155732" />
	</span>
	<span data-img="2019/12/1912150131.jpg" class="pimgb">
		<img itemprop="image" src="/wp-content/uploads/2019/12/1912150131-500x375.jpg" alt="Gadwall" width="500" height="375" class="aligncenter size-medium wp-image-155734" />
	</span>
	<span data-img="2019/12/1912150132.jpg" class="pimga">
		<img itemprop="image" src="/wp-content/uploads/2019/12/1912150132-500x375.jpg" alt="Gadwall" width="500" height="375" class="aligncenter size-medium wp-image-155735" />
	</span>
</p>
HTML
CopyExpand

その二つのクラスによって現れ方を変えるとかはしない。ちょっと事情があって複数になっているだけのこと。
ページにアクセス、javascript 読み込み時に、タグ<img>のオブジェクトを取得して、その親である<span>タグからページ内での縦位置を取得して配列に格納、その時、それぞれの画像が表示されているか否かのフラグも配列にする。そしてスクロールイベントにおいてループさせるのはその表示フラグの入った配列にするという具合です。

// これらはwindow.onscroll でも使用する
var pimgclasslist = new Array(),
	pimgclassarylength,
	pimgoffsettop = new Array(),
	img_show_flg = new Array();

window.onload = function() {
	var load_show_img_key = new Array(),
		imgtagsidxlen,
		imgtaglist = document.getElementsByTagName( 'img' ),
		imgtaglistlen = imgtaglist.length,
		parentpimg,
		tmpclass,
		rect,
		j = 0,
		winheight = window.innerHeight,
		scrollfromTop = window.pageYOffset;

	// <img>のオブジェクト全てに対して調べる
	for ( var i = 0; i < imgtaglistlen; i++ ) {
		// その<img>の親である<span>タグがclassに'pimga'か'pimgb'を持っているものだけ
		parentpimg = imgtaglist[ i ].parentNode;
		tmpclass = parentpimg.getAttribute( 'class' );
		if ( tmpclass ) {
			if ( -1 !== tmpclass.indexOf( 'pimga' ) || -1 !== tmpclass.indexOf( 'pimgb' ) ) {
				// 親のオブジェクトを配列に格納
				pimgclasslist[ j ] = parentpimg;
				// 親の<span>タグのページ内での縦位置を取得
				// ページ読み込み時でスクロールが0ならscrollfromTopの値は不必要ではあるけれど、
				// 仮に少しでもスクロールしていたら、その数値が小さくずれてしまうので一応
				rect = parentpimg.getBoundingClientRect();
				pimgoffsettop[ j ] = rect.top + scrollfromTop;
				// 画像が表示されている否かのフラグを設定、0:非表示、1:表示
				img_show_flg[ j ] = 0;
				j++;
			}
		}
	}

	pimgclassarylength = pimgclasslist.length;

	// ページがロードされて表示された時にすでに画面内にある画像があるか調べる
	for ( var i = 0; i < pimgclassarylength; i++ ) {
		if ( pimgoffsettop[ i ] < winheight ) {
			load_show_img_key[ i ] = i;
		} else {
			break;
		}
	}

	imgtagsidxlen = load_show_img_key.length;

	// すでに画面内にある画像は上から順々に時間差で表示する
	for ( var j = 0; j < imgtagsidxlen; j++ ) {
		var delayout = ( j + 2 ),
			showkey = load_show_img_key[ j ];

		// 狭い画面の場合とスライドする量を変えて指定。
		if ( 1 === narrow ) {
			pimgclasslist[ showkey ].style.cssText = 'margin-left:0px;opacity:1;transition-delay:' + delayout + 's;';
		} else {
			pimgclasslist[ showkey ].style.cssText = 'opacity:1;transition-delay:' + delayout + 's;';
		}
		// すでに表示した画像のフラグを1に設定
		img_show_flg[ showkey ] = 1;
	}
}
JavaScript
CopyExpand

ここでなにゆえに、親タグの方の<span>を取得せずに<img>の方を取得するのかということが疑問になるのかも。 画像の入った親タグのclass が1つであればその方が良いのだけれど、この場合のようにclass'pimga''pimgb'など、複数ある場合だとそれぞれのクラスのオブジェクトを取得することになる。で、スクロールイベントが発生した時にループで回す配列はページに配置された上からの順番にさせたいということがあって、クラスのオブジェクトを別々に取得しているとそれを1つにまとめて順番に並び替えさせないといけなくなる。それにかかる手間というか負荷を避けたかったということです。 オブジェクトを取得する時に<img>の親という指定の仕方もできたかもしれないけれど、まぁ、それならほとんど変わらないのではと思ったわけで。 で、実は、これの最後の部分、50行めからあとのところですが、すっかり忘れきってしまっていたことがあって、うっかり迷宮にさまよい込んでしまったことがあったのです。 ここの、時間差で表示する、ということをはじめはsetIimeout で書いていたのです。そう、こんなふうに、

// これは希望する結果が得られません。ダメなコードです。
for ( var j = 0; j < imgtagsidxlen; j++ ) {
	var delayout = ( j + 2 ) * 1000,
		showkey = load_show_img_key[ j ];

	setTimeout ( function() {
		pimgclasslist[ showkey ].style.cssText = 'margin-left:0px;opacity:1;'; 
		img_show_flg[ showkey ] = 1;
	}, delayout );
}
JavaScript
CopyExpand

実は、さきにjQuery でも書いていて、style の指定の書式を変えただけで、このまま全く普通に動いていたもので・・・。
一見、良さそうなのですが、これでは動かない。
さんざん、色々やってみて迷った挙げ句、setTimeout を使わず、上記のようなtransition-delay での方法にしたのですが、そうこうしていると記憶の奥の方に小さな光が見えて、あっ、そういえば、これってsetTimeout を別関数にして呼び出せばよかったんだっけ!と、定かではありませんでしたが、なんとなくはるか過去の経験を思い出しました。そして、ちょっと調べてみたらこういう具合に書けば動くということがわかりました。一応、今後の参考までに。

for ( var j = 0; j < imgtagsidxlen; j++ ) {
	( function( pram ) {
		var delayout = ( j + 2 ) * 1000,
			showkey = load_show_img_key[ j ];

		setTimeout ( function() {
			pimgclasslist[ showkey ].style.cssText = 'margin-left:0px;opacity:1;';
			img_show_flg[ showkey ] = 1;
		}, delayout );
	 } )( j );
}
JavaScript
CopyExpand

そしてスクロールイベントの方のjavascript

window.onscroll=function(){
	var numscroll = window.pageYOffset;

	if ( 0 != pimgclassarylength ) {
		var winheight = window.innerHeight,
			last_key,
			highest,
			all_flg = 0;// 全て表示フラグ、0:全て表示されている

		// 親<span>オブジェクトが入っている配列pimgclasslistと
		// 画像表示フラグの配列img_show_flgはそれぞれkeyが対応していて
		// 配列の個数も同じなので、既に求めてある個数を使ってフラグ配列をループ
		// 上の画像から順に表示されていない画像が出てくるまで調べ、
		// 出てきたらスクロールとの条件を調べて処理してからそこでループを抜ける
		// 上へスクロールしている時は非表示の上にあるもので画面から消えているものは非表示にする
		for ( var i = 0; i < pimgclassarylength; i++ ) {
			if ( 0 === img_show_flg[ i ] ) {
				if ( numscroll > pimgoffsettop[ i ] - winheight + winheight  / 4 ) {
					if ( 1 === narrow ) {
						pimgclasslist[ i ].style.cssText = 'margin-left:0px;opacity:1;';
					} else {
						pimgclasslist[ i ].style.cssText = 'opacity:1;';
					}
					img_show_flg[ i ] = 1;
				}
				if ( i  > 0 ) {
					if ( numscroll < pimgoffsettop[ i - 1 ] - winheight ) {
						if ( 1 === narrow ) {
							pimgclasslist[ i - 1 ].style.cssText = 'margin-left:-100px;opacity:0;';
						} else {
							pimgclasslist[ i - 1 ].style.cssText = 'opacity:0;';
						}
						img_show_flg[ i - 1 ] = 0;
					}
				}
				all_flg = 1;
				break;
			}
		}

		// 全ての画像が表示されている場合
		// 上にスクロールして一番下の画像が画面から消えた時点でその画像を非表示にする
		// 1つでも非表示の画像があれば上述の処理にて他の画像も消すことができる
		if ( 0 === all_flg ) {
			last_key = pimgclassarylength - 1;
			highest = pimgoffsettop[ last_key ]; 
			if ( numscroll <  highest- winheight + winheight  / 4 ) {
				if ( numscroll < highest - winheight ) {
					if ( 1 === narrow ) {
						pimgclasslist[ last_key ].style.cssText = 'margin-left:-100px;opacity:0;';
					} else {
						pimgclasslist[ last_key ].style.cssText = 'opacity:0;';
					}
					img_show_flg[ last_key ] = 0;
				}
			}
		}
	}

}
JavaScript
CopyExpand

これの場合はスクロールの値を使用します。
それぞれの要素の縦位置をgetBoundingClientRect で取得していますが、それはjavascript 読み込みの時の値なので、スクロールによって変化する値ではなく、単純にページ上端から要素までの距離だからです。
スクロールの量が少ないほどループで調べる要素の数は少なくなり、ページの下へいくほどその数は増えることになります。
と、いうことでこのスクフワッ!効果を施してあるのは、自分のサイトのトップページです。→«Photographs of Japanese Birds»

・・・

さて、いよいよ本題のページの作成にはいりましょ。
これも画像ページなのですが、はじめからこのスクフワッ!効果を前提に考えてました。で、読み込む画像はとりあえず120枚ということにしました。それだけの数でサクサク動くでしょうか?
画像まわりのHTML はこんなぐあい。

<div class="row">
	<div class="one-image  centerbox">
		<p class="one-image-tbl-img">
			<span data-img="19/11/1911011567.jpg" class="pimga">
				<img src="/tns/wp-content/uploads/2019/11/1911011567-500x375.jpg" alt=""  />
			</span>
		</p>
		<p class="one-image-tbl-caption">0:/2019/11/1911011567</p>
	</div>

	<div class="one-image  leftbox">
		<p class="one-image-tbl-img">
			<span data-img="19/12/1911292772.jpg" class="pimga">
				<img src="/tns/wp-content/uploads/2019/12/1911292772-500x375.jpg" alt=""  />
			</span>
		</p>
		<p class="one-image-tbl-caption">1:/2019/12/1911292772</p>
	</div>

	<div class="one-image  rightbox">
		<p class="one-image-tbl-img">
			<span data-img="19/12/1911292773.jpg" class="pimga">
				<img src="/tns/wp-content/uploads/2019/12/1911292773-500x375.jpg" alt=""  />
			</span>
		</p>
		<p class="one-image-tbl-caption">2:/2019/12/1911292773</p>
	</div>
</div>
HTML
CopyExpand

画像は個々に<span>タグの親ボックスに入っています。
説明のための<p>タグと一緒にまた上の階層の親ボックスに入り、それを1つの単位として、それを3セットまとめて1つのボックスに入れて1つのグループにしています。画像の数が120なのでこのグループが40個ページにはあるということになります。しかし、改めて見てみると画像の部分の階層はもう一段浅くてもよかったですね。
このページはjQuery で作ってます。どちらでもいいんです。その時の気分ですか。ワイドとナローの画面の設定の切り替え点は1200px にしています。実験的で内容の無いページなのであまりこだわることもないだろうと。動かすのは'one-image'class が設定されている<div>タグで画像と説明を一緒に動かします。で、この<div>タグには見ての通り、centerbox、leftbox、rightbox とそれぞれ区別するためのサブクラスをつけてあり、言うまでもなく、これはそれぞれで別の動きをさせるためのものです。
javascript 的には先のものとやることはほぼ同じです。jQuery になるのと3つのクラスで違う動きをさせることだけ。

jQuery( function() {
	var scrlval = 0,
		scrlflg = 0,
		effect_flg = true,
		winheight = jQuery( window ).height(),
		winwidth = jQuery( window ).width(),
		imgtags = new Array(),
		imgtagsidx = 0,
		load_show_img_key = new Array(),
		imgoffsettop = new Array(),
		offset,
		img_show_flg = new Array(),
		tmpclass,
		classid = { 'centerbox': 'c', 'leftbox': 'l', 'rightbox': 'r' },
		img_class_flg = new Array(),
		doc_imgs_len = jQuery( '.one-image' ).length,
		narrow = 1;// 1: wide screen, 0: narrow screen

	if ( winwidth < 1200 ) {
		narrow = 0;// narrow screen
	}

	if ( doc_imgs_len ) {
		jQuery( '.one-image' ).each( function( i, o ) {
			tmpclass = jQuery( o ).attr( 'class' );
			tmpclass = tmpclass.replace( 'one-image ', '' );

			// それぞれのサブクラスを頭文字だけで配列に登録
			img_class_flg[ i ] = classid[ tmpclass ];

			imgtags[ i ] = jQuery( o );
			img_show_flg[ i ] = 0;

			offset = jQuery( o ).offset();
			imgoffsettop[ i ] = offset.top;
		});
	}

	// ページ読み込み時にスクロール0ですでに画面内にある要素を調べる
	jQuery.each( imgoffsettop,  function( i, o ) {
		if ( imgoffsettop[ i ] < winheight ) {
			load_show_img_key[ imgtagsidx ] = i;
			imgtagsidx++;
		} else {
			return false;
		}
	});

	// ページ読み込み時にスクロール0ですでに画面内にある要素を
	// 5秒たってもスクロールがない場合に順に展開させる
	setTimeout ( function() {
		if ( 0 === scrlval ) {
			jQuery.each( load_show_img_key,  function( i, o ) {
				var delayout = ( i + 1 ) * 1000;
				setTimeout ( function() {
					if ( 1 === narrow ) {
						if ( 'c' === img_class_flg[ o ] ) {
							jQuery( imgtags[ o ] ).css( { top:'150px', left:'500px' , width:'0px', opacity: '0' } );
						} else if ( 'l' === img_class_flg[ o ] ) {
							jQuery( imgtags[ o ] ).css( { left:'0px' , width:'500px', opacity: '1' } );
						} else if ( 'r' === img_class_flg[ o ] ) {
							jQuery( imgtags[ o ] ).css( { right:'0px' , width:'500px', visibility: 'visible', opacity: '1', transitionDelay:'0.5s' } );
						}
					} else {
						if ( 'c' === img_class_flg[ o ] ) {
							jQuery( '.pimga', imgtags[ o ] ).css( { left: '0%', width:'100%', opacity: '1' } );
						} else if ( 'l' === img_class_flg[ o ] ) {
							jQuery( '.pimga', imgtags[ o ] ).css( { width:'100%', opacity: '1' } );
						} else if ( 'r' === img_class_flg[ o ] ) {
							jQuery( '.pimga', imgtags[ o ] ).css( { width:'100%', opacity: '1' } );
						}
					}
					img_show_flg[ o ] = 1;
				}, delayout );
			});
		}
	}, 5000 );
} );
JavaScript
CopyExpand
jQuery( function() {
	// ここからスクロールイベント
	jQuery( window ).scroll( function() {
		scrlval = jQuery( window ).scrollTop();

		// scrlflg は一度スクロールさせたら1
		if ( 0 === scrlflg && scrlval > 0) {
			scrlflg = 1;
		}

		if ( imgtags.length ) {
			var last_key,
				highest,
				all_flg = 0;

			// effect_flgはセンターの画像を表示させるために展開処理を停止させるためのもの
			if ( effect_flg ) {
				jQuery.each( img_show_flg,  function( i, o ) {
					if ( 0 === o ) {
						if ( scrlval > imgoffsettop[ i ] - winheight + winheight  / 5 ) {
							if ( 1 === narrow ) {
								if ( 'c' === img_class_flg[ i ] ) {
									jQuery( imgtags[ i ] ).css( { top:'150px', left:'500px' , width:'0px', opacity: '0' } );
								} else if ( 'l' === img_class_flg[ i ] ) {
									jQuery( imgtags[ i ] ).css( { left:'0px' , width:'500px', opacity: '1' } );
								} else if ( 'r' === img_class_flg[ i ] ) {
									jQuery( imgtags[ i ] ).css( { right:'0px' , width:'500px', visibility: 'visible', opacity: '1', transitionDelay:'0.5s' } );
								}
							} else {
								if ( 'c' === img_class_flg[ i ] ) {
									jQuery( '.pimga', imgtags[ i ] ).css( { left: '0%', width:'100%', opacity: '1' } );
								} else if ( 'l' === img_class_flg[ i ] ) {
									jQuery( '.pimga', imgtags[ i ] ).css( { width:'100%', opacity: '1' } );
								} else if ( 'r' === img_class_flg[ i ] ) {
									jQuery( '.pimga', imgtags[ i ] ).css( { width:'100%', opacity: '1' } );
								}
							}
							img_show_flg[ i ] = 1;
						}
						if ( i  > 0 ) {
							if ( scrlval < imgoffsettop[ i - 1 ] - winheight - winheight / 5 ) {
								if ( 1 === narrow ) {
									if ( 'c' === img_class_flg[ i - 1 ] ) {
										jQuery( imgtags[ i - 1 ] ).css( { top:'0px', left:'250px' , width:'502px', opacity: '1' } );
									} else if ( 'l' === img_class_flg[ i - 1 ] ) {
										jQuery( imgtags[ i - 1 ] ).css( { left:'-100px' , width:'0px', opacity: '0' } );
									} else if ( 'r' === img_class_flg[ i - 1 ] ) {
										jQuery( imgtags[ i - 1 ] ).css( { right:'-100px' , width:'0px', visibility: 'hidden', opacity: '0' } );
									}
								} else {
									if ( 'c' === img_class_flg[ i - 1 ] ) {
										jQuery( '.pimga', imgtags[ i - 1 ] ).css( { left: '50%', width:'0%', opacity: '0' } );
									} else if ( 'l' === img_class_flg[ i - 1 ] ) {
										jQuery( '.pimga', imgtags[ i - 1 ] ).css( { width:'0%', opacity: '0' } );
									} else if ( 'r' === img_class_flg[ i - 1 ] ) {
										jQuery( '.pimga', imgtags[ i - 1 ] ).css( { width:'0%', opacity: '0' } );
									}
								}
								img_show_flg[ i - 1 ] = 0;
							}
						}
						all_flg = 1;
						return false;
					}
				});

				// ページの一番下まで展開している場合に一番下のグループを閉じさせる処理
				if ( 0 === all_flg ) {
					last_key = doc_imgs_len - 1;
					highest = imgoffsettop[ last_key ]; 
					if ( scrlval <  highest - winheight + winheight  / 5 ) {
						if ( 1 === narrow ) {
							if ( 'c' === img_class_flg[ last_key ] ) {
								jQuery( imgtags[ last_key ] ).css( { top:'0px', left:'250px' , width:'502px', opacity: '1' } );
							} else if ( 'l' === img_class_flg[ last_key ] ) {
								jQuery( imgtags[ last_key ] ).css( { left:'-100px' , width:'0px', opacity: '0' } );
							} else if ( 'r' === img_class_flg[ last_key ] ) {
								jQuery( imgtags[ last_key ] ).css( { right:'-100px' , width:'0px', opacity: '0', visibility: 'hidden' } );
							}
						} else {
							if ( 'c' === img_class_flg[ last_key ] ) {
								jQuery( '.pimga', imgtags[ last_key ] ).css( { left: '50%', width:'0%', opacity: '0' } );
							} else if ( 'l' === img_class_flg[ last_key ] ) {
								jQuery( '.pimga', imgtags[ last_key ] ).css( { width:'0%', opacity: '0' } );
							} else if ( 'r' === img_class_flg[ last_key ] ) {
								jQuery( '.pimga', imgtags[ last_key ] ).css( { width:'0%', opacity: '0' } );
							}
						}
						img_show_flg[ last_key ] = 0;
					}
				}

				if ( 1 === narrow ) {// wide screen
					if ( 1 === scrlflg && scrlval < 5 ) {
						setTimeout ( function() {
							if ( scrlval < 5 ) {
								jQuery.each( img_show_flg,  function( i, o ) {
									var delayout = ( i + 1 ) * 200;
									if ( 1 === o ) {
										setTimeout ( function() {
											if ( 'c' === img_class_flg[ i ] ) {
												setTimeout( function() {
													jQuery( imgtags[ i ] ).css( { top:'0px', left:'250px' , width:'502px', opacity: '1' } );
												}, 1500 );
											} else if ( 'l' === img_class_flg[ i ] ) {
												jQuery( imgtags[ i ] ).css( { left:'-100px' , width:'0px', opacity: '0' } );
											} else if ( 'r' === img_class_flg[ i ] ) {
												jQuery( imgtags[ i ] ).css( { right:'-100px' , width:'0px', opacity: '0', visibility: 'hidden' } );
											}
											img_show_flg[ i ] = 0;
										}, delayout );
									}
								});
							}
						}, 5000 );
					}// if scrlflg
				}// if narrow
			}// if effect_flg
		}// if imgtags.length
	}// window.scroll
} );
JavaScript
CopyExpand
jQuery( function() {
	// id=mncopenの要素をクリックすると
	// 開いていた左右の要素を閉じてセンターの要素を表示し固定
	// 再びクリックすることで、左右の要素を表示する元々の動作に戻す
	jQuery( '#mncopen' ).click( function() {
		if ( effect_flg ) {
			effect_flg = false;

			var imgtagslen = imgtags.length,
				opencenterID = null,
				i = 0,
				h = 0,
				opentar = new Array(),
				opencount = 0,
				copenflg = 0,
				tarid;

			if ( imgtagslen ) {
				for ( var j = 0; j < imgtagslen; j++ ){
					if ( 1 ===  img_show_flg[ j ] ) {
						opentar[ opencount ] = j;
						opencount++;
					}
				}

				opencenterID = setInterval( function() {
					tarid = opentar[ i ];
					if ( 'c' === img_class_flg[ tarid ] ) {
						jQuery( imgtags[ tarid ] ).css( { top:'0px', left:'250px' , width:'502px', opacity: '1' } );
					} else if ( 'l' === img_class_flg[ tarid ] ) {
						jQuery( imgtags[ tarid ] ).css( { left:'-100px' , width:'0px', opacity: '0' } );
					} else if ( 'r' === img_class_flg[ tarid ] ) {
						jQuery( imgtags[ tarid ] ).css( { right:'-100px' , width:'0px', visibility: 'hidden', opacity: '0' } );
					}
					img_show_flg[ tarid ] = 0;

					i++;
					if ( i === opencount ) {
						clearInterval( opencenterID );
					}
				}, 200 );
			}
		} else {
			effect_flg = true;
		}
	} );
} );
JavaScript
CopyExpand

結構、長いものになってしまいました。
いらないところを削ったり、必要なところを他から移動させたりしたので、ちゃんと動けば良いのですが。
実際に動いているページにおいては、実はちょっと変えている部分があって。
サブでつけているクラスによってそれぞれの動きを変えているわけですが、そのスタイルを設定するコードの部分で同じような部分がだらだらと並んでいたりします。で、その部分をif 文で選別させているわけですが、それを三次元の連想配列に各スタイル設定を格納しておいて、if 文を使わないで配列のkey を指定する方法にしているのです。

jQuery( function() {
	var style_set = {
		c: {
			0: { top:'150px', left:'500px' , width:'0px', opacity: '0' },
			1: { top:'0px', left:'250px' , width:'502px', opacity: '1' },
			2: { left: '0%', width:'100%', opacity: '1' },
			3: { left: '50%', width:'0%', opacity: '0' }
		},
		l: {
			0: { left:'0px' , width:'500px', opacity: '1' },
			1: { left:'-100px' , width:'0px', opacity: '0' },
			2: { width:'100%', opacity: '1' },
			3: { width:'0%', opacity: '0' }
		},
		r: {
			0: { right:'0px' , width:'500px', visibility: 'visible', opacity: '1', transitionDelay:'0.5s' },
			1: { right:'-100px' , width:'0px', visibility: 'hidden', opacity: '0' },
			2: { width:'100%', opacity: '1' },
			3: { width:'0%', opacity: '0' }
		}
	};

	if ( scrlval <  highest - winheight + winheight  / 5 ) {
		if ( 1 === narrow ) {
			/*if ( 'c' === img_class_flg[ last_key ] ) {
				jQuery( imgtags[ last_key ] ).css( { top:'0px', left:'250px' , width:'502px', opacity: '1' } );
			} else if ( 'l' === img_class_flg[ last_key ] ) {
				jQuery( imgtags[ last_key ] ).css( { left:'-100px' , width:'0px', opacity: '0' } );
			} else if ( 'r' === img_class_flg[ last_key ] ) {
				jQuery( imgtags[ last_key ] ).css( { right:'-100px' , width:'0px', opacity: '0', visibility: 'hidden' } );
			}*/
			// ↑上の if 文を↓この文に変更
			jQuery( imgtags[ last_key ] ).css( style_set[ img_class_flg[ last_key ] ][1] );
		} else {
			/*if ( 'c' === img_class_flg[ last_key ] ) {
				jQuery( '.pimga', imgtags[ last_key ] ).css( { left: '50%', width:'0%', opacity: '0' } );
			} else if ( 'l' === img_class_flg[ last_key ] ) {
				jQuery( '.pimga', imgtags[ last_key ] ).css( { width:'0%', opacity: '0' } );
			} else if ( 'r' === img_class_flg[ last_key ] ) {
				jQuery( '.pimga', imgtags[ last_key ] ).css( { width:'0%', opacity: '0' } );
			}*/
			// ↑上の if 文を↓この文に変更
			jQuery( '.pimga', imgtags[ last_key ] ).css( style_set[ img_class_flg[ last_key ] ][3] );
		}
		img_show_flg[ last_key ] = 0;
	}
} );
JavaScript
CopyExpand

自分が試してみたベンチマークでは、if 文と配列を使う方法での違いは、phpでは相当に差があって配列の方法が圧倒的に早く、if 文においては、当然のことながらelseif の段数が多くなるほど、負荷が多くなるという結果を得た覚えがあります。一方の、javascript では、ほとんど差はなく、わずかに配列の方法の方が速いという結果でした。そして、もっとも驚いたことは、当然のこと、ほぼ同じ処理をさせたのですが、php よりもjavascript の方が、ケタ違いに速かったということ。ほんとにケタが違った。javascript は遅いものだとばかり思い込んでいたけれど、これはとんだ思い違いだったようで。

さて、これがいかなる動きをするのかは、ご興味があればこのページを御覧ください。« Roses »
1200px以上のワイド画面での画像読み込みは120枚で、これがナロー画面だと30枚にしてあります。
で、もちろんjQuery ではなくjavascript でも、同じものが動いているページもあり、それは« Images viewer »

Sanbanse Funabashi

Top

スクロールさせるか画像をクリックすると元に戻ります。