♠
Page No.2
ひとつすっきりしたところで。
動かす要素をクラスで指定して、それで取得したオブジェクトをスクロールイベントが発生するたびに全部をぐるぐるとループさせているのです。10個ぐらいならそんなに重くもならなさそうだけれど・・・。このページも6個ですがそんなに負荷が大きくかかっているような感じはしないような・・・。
でも、それが30、40個とか、いやいや100個以上とかになったらかなり負荷が大きそうでページの動きがごりごりになってしまいそうな気もしないでもない。
実際のところ、自分がこれを施そうと思っているページは画像のページであり、その画像をスクフワッ!効果で出現させようかと考えているわけで、たいてい30枚~50枚ぐらいの画像があるのですね。これね~、なんか重くなってしまいそうで。
ちょっと考えてみると、それぞれの要素のスクフワッ!効果に必要な情報だけをあらかじめ配列に取り出しておいて、それをスクロールイベントでループさせれば負荷が減らせるのではないだろうかと。
必要な情報というのはページ上端からの位置情報、持っているclass、ぐらいなものですし。あとは、全ての要素をループさせるのではなく、必要な部分だけということを考えるなら、それを可能にするための要素が今、表示されているか隠されているかのフラグぐらいでしょうか。
たとえば実際に、要素のオブジェクトと、値が一桁の数字1つの配列ではどれだけループさせるのに違いがあるかということを知りたくなる。
このスクフワッ!効果は、この頃に作ろうとしていた新たな画像ページに適用させたいと思っていたもので、実はこの記事を書いている現段階ではすでにそのページは出来上がっているのです。で、そのページにおいて色々試している時に実行したベンチマークがこれです。ローカルな環境でやってます。おわかりのとおりjQuery 。
オブジェクトの方はその縦位置を取得し、配列の方は何の処理もさせていないので、その部分でもかなりハンデがあるようには思います。ローカルな環境でFireFox とChrome でそれぞれ三回づつやってみました。
object array
FireFox1 1428ms 14ms
FireFox2 1435ms 13ms
FireFox3 1449ms 13ms
Chrome1 4231ms 28ms
Chrome2 4270ms 26ms
Chrome3 4477ms 29ms
まっ!1万回まわしていますからね。
でも、こうなると予想以上に重いようにも思えるし、そして、予想外にChrome よりもFireFox の方がかなり速いということですね。確かChrome の方が速さには定評があったはずではなかったか。
と、いうことで、考えていた必要な情報だけをあらかじめ配列に入れておいてそれをループで回すということにしたのです。
とりあえず今、考える題材としては自分のメインの鳥画像ページ。と言ってもこの記事を書いている時にはすでにそのページのスクフワッ!は稼働してます。スクロールしていくと画像が少し横にスライドしつつ現れてきます。ご興味があればここへ。
このページはjQuery は使用しておらずjavascript であり、画像のタグ<img> はそれぞれ個々に親ボックスの<span> に入っていて、それのclass は'pimga' と'pimgb' の2種類。こんな具合。
その二つのクラスによって現れ方を変えるとかはしない。ちょっと事情があって複数になっているだけのこと。
ページにアクセス、javascript 読み込み時に、タグ<img> のオブジェクトを取得して、その親である<span> タグからページ内での縦位置を取得して配列に格納、その時、それぞれの画像が表示されているか否かのフラグも配列にする。そしてスクロールイベントにおいてループさせるのはその表示フラグの入った配列にするという具合です。
ここでなにゆえに、親タグの方の<span>を取得せずに<img>の方を取得するのかということが疑問になるのかも。
画像の入った親タグのclass が1つであればその方が良いのだけれど、この場合のようにclass に'pimga' と'pimgb' など、複数ある場合だとそれぞれのクラスのオブジェクトを取得することになる。で、スクロールイベントが発生した時にループで回す配列はページに配置された上からの順番にさせたいということがあって、クラスのオブジェクトを別々に取得しているとそれを1つにまとめて順番に並び替えさせないといけなくなる。それにかかる手間というか負荷を避けたかったということです。
オブジェクトを取得する時に<img>の親という指定の仕方もできたかもしれないけれど、まぁ、それならほとんど変わらないのではと思ったわけで。
で、実は、これの最後の部分、50行めからあとのところですが、すっかり忘れきってしまっていたことがあって、うっかり迷宮にさまよい込んでしまったことがあったのです。
ここの、時間差で表示する、ということをはじめはsetIimeout で書いていたのです。そう、こんなふうに、
実は、さきにjQuery でも書いていて、style の指定の書式を変えただけで、このまま全く普通に動いていたもので・・・。
一見、良さそうなのですが、これでは動かない。
さんざん、色々やってみて迷った挙げ句、setTimeout を使わず、上記のようなtransition-delay での方法にしたのですが、そうこうしていると記憶の奥の方に小さな光が見えて、あっ、そういえば、これってsetTimeout を別関数にして呼び出せばよかったんだっけ!と、定かではありませんでしたが、なんとなくはるか過去の経験を思い出しました。そして、ちょっと調べてみたらこういう具合に書けば動くということがわかりました。一応、今後の参考までに。
そしてスクロールイベントの方のjavascript 。
これの場合はスクロールの値を使用します。
それぞれの要素の縦位置をgetBoundingClientRect で取得していますが、それはjavascript 読み込みの時の値なので、スクロールによって変化する値ではなく、単純にページ上端から要素までの距離だからです。
スクロールの量が少ないほどループで調べる要素の数は少なくなり、ページの下へいくほどその数は増えることになります。
と、いうことでこのスクフワッ!効果を施してあるのは、自分のサイトのトップページです。→«Photographs of Japanese Birds»
・・・
さて、いよいよ本題のページの作成にはいりましょ。
これも画像ページなのですが、はじめからこのスクフワッ!効果を前提に考えてました。で、読み込む画像はとりあえず120枚ということにしました。それだけの数でサクサク動くでしょうか?
画像まわりのHTML はこんなぐあい。
画像は個々に<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 ;
if ( winwidth < 1200 ) {
narrow = 0 ;
}
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;
} ) ;
}
jQuery. each ( imgoffsettop, function ( i, o ) {
if ( imgoffsettop[ i ] < winheight ) {
load_show_img_key[ imgtagsidx ] = i;
imgtagsidx++ ;
} else {
return false ;
}
} ) ;
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 ) ;
} ) ;
Copy Expand ‹ › ‹ ›
jQuery ( function ( ) {
jQuery ( window ) . scroll ( function ( ) {
scrlval = jQuery ( window ) . scrollTop ( ) ;
if ( 0 === scrlflg && scrlval > 0 ) {
scrlflg = 1 ;
}
if ( imgtags. length ) {
var last_key,
highest,
all_flg = 0 ;
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 ) {
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 ) ;
}
}
}
}
}
} ) ;
Copy Expand ‹ › ‹ › ‹ ›
結構、長いものになってしまいました。
いらないところを削ったり、必要なところを他から移動させたりしたので、ちゃんと動けば良いのですが。
実際に動いているページにおいては、実はちょっと変えている部分があって。
サブでつけているクラスによってそれぞれの動きを変えているわけですが、そのスタイルを設定するコードの部分で同じような部分がだらだらと並んでいたりします。で、その部分をif 文で選別させているわけですが、それを三次元の連想配列に各スタイル設定を格納しておいて、if 文を使わないで配列のkey を指定する方法にしているのです。
自分が試してみたベンチマークでは、if 文と配列を使う方法での違いは、php では相当に差があって配列の方法が圧倒的に早く、if 文においては、当然のことながらelseif の段数が多くなるほど、負荷が多くなるという結果を得た覚えがあります。一方の、javascript では、ほとんど差はなく、わずかに配列の方法の方が速いという結果でした。そして、もっとも驚いたことは、当然のこと、ほぼ同じ処理をさせたのですが、php よりもjavascript の方が、ケタ違いに速かったということ。ほんとにケタが違った。javascript は遅いものだとばかり思い込んでいたけれど、これはとんだ思い違いだったようで。
さて、これがいかなる動きをするのかは、ご興味があればこのページを御覧ください。« Roses »
1200px以上のワイド画面での画像読み込みは120枚で、これがナロー画面だと30枚にしてあります。
で、もちろんjQuery ではなくjavascript でも、同じものが動いているページもあり、それは« Images viewer »
page : 1 < 2 ☆このページはコンテンツの量が多いので分割しています