一定時間で画像を切り替えるscriptを作りました。
切り替えるときに一つ目の画像をフェードアウトさせて、
次の画像を表示させたいのですが、
いい方法がありましたら、どなたかご教授ください。
お願いします。
ちょっと不細工ですが、なんとか下まではできました。
下のほうで関数内で自分の関数を呼んでいるのですが、引数の「season」がわたりません。
「season」の部分に直接「sprn」などを入れれば動くのですが・・・
この方法は無理があるでしょうか。
また、他の方法がありましたらお教えください。お願いします。
<SCRIPT language="JavaScript">
<!--
sprn='sprn'; summ='summ'; autm='autm'; wint='wint';
imgnum= 1;
timer = 5000;
function SeasonImage(season){
clearTimeout();
if (imgnum< 4){
imgnum++;
}else{
imgnum= 1;
}
document.img.filters.revealTrans.Apply();
document.img.src = "../images/huukei/" + season + imgnum + ".jpg";
document.img.filters.revealTrans.Play();
setTimeout("SeasonImage(season)",timer);
}
こんな感じで使用するイメージを配列に読み込んでおいて、
その配列の[n]番目を呼び出すようにすれば良いかも。
(サンプルは、URL欄をご確認ください)
<html>
<head>
<title></title>
<script language="JavaScript">
<!--
var cnt = 0;
var dat = new Array("img1.jpg","img2.jpg","img3.jpg","img4.jpg");
prLdImg= new Array();
for (i=0; i<dat.length; i++){
prLdImg[i] = new Image();
prLdImg[i].src = dat[i];
}
function nextImg(){
var obj = window.document.all('myImg');
if(timerID){clearTimeout(timerID);}
cnt++;
cnt %= dat.length;
obj.filters.revealTrans.Apply();
obj.src = dat[cnt];
obj.filters.revealTrans.Play();
var timerID = setTimeout("nextImg()",3000);
}
//-->
</script>
</head>
<body>
<img id="myImg" src="img1.jpg" style="filter:revealTrans(duration=2,transition=12)" onClick="nextImg()">
</body>
</html>
ちなみに、上記スクリプトの元ネタは、OpenSpec様のJavaScript例文辞典(http://www.openspc2.org/reibun/javascript/)の
以下のソースです。
■ 画像編
[02] 複数の画像をあらかじめ読み込む(プレロード)
http://www.openspc2.org/reibun/javascript/image/002/index.html
■ フィルタ/グラフィック編
[02] 画像をワイプ効果を使い切り替えるhttp://www.openspc2.org/reibun/javascript/graphic/002/index.html
↑
失礼致しました。上記のサイト名は以下の誤りでした。
訂正させてください。申し訳ありません。
誤)OpenSpec
正)OpenSpace
それに対しては、このように理由付けする (結果的には間違いではないので、これを鵜呑みにしても大きな害はない)。
setTimeout の最初の実引数として渡されている文字列の展開が、timer で設定された時間後に初めてなされると仮定すれば、関数のスコープ内からではなくて、setTimeout の属するグローバルな階層から変数を探そうとすることになる。既にコンパイル済みの関数内にあるローカル変数や実引数は無視される、というか、見えていない。グローバルに宣言すらされていない season と言われても困るだろう。season は SeasonImage の仮引数でしかなかった。しかしグローバルに定義されている sprn に関しては動く。
(従って、関数内部のコンパイル時に渡さないとどうしようもないから) 以下のように書いて setTimeout の最初の実引数である文字列を動的に作成しなさい、とヴェンダーの使用説明書には書いてあるだろう。
setTimeout("SeasonImage("+season+")", timer);
質問者は、季節を表す 4 種類の自作接頭辞と 1 から 4 までの番号を結合して画像ファイルを名前付けして整理している。つまり、季節ごとに 4 枚、合計 16 枚の JPEG 画像を用意している。質問文をもう少し慎重に読まないと、回答にならないと思う (非笑)。。。
/* そもそも >>2 は 3 ヶ月毎に自動的にこの 4 群を切り替えたいのかどうかを述べていないので適切な回答は無理だが。
*/
ともかく。>>2 が拾ってきたという画像先読みを取り上げる。どこを見ても同じ書き方をしているから、全ての人が何の疑いもなく無意味な処理を行っていると想像される、このように。
var
images=new Array,
i=16;
while(i--)
(images[i]=new Image).src='..';
何処が無意味であるかを言う。欲しいのは src プロパティをセットすることであたかも副産物のように得られる画像データだけだから、Image オブジェクトをわざわざ 16 個作ることによって配列の各要素に構造を持たせる必要は全く無い。1 つの Image オブジェクトの src プロパティを次々に書き換えることでも同じ結果を得られるならばそうする方が良いに決まっている。
var
image=new Image,
srcs=new Array,
i=16;
while(i--)
srcs[i]=(image.src='..');
JScript と古い JavaScript エンジンを無視すれば、
const
image=new Image,
srcs=new Array;
var
i=16;
while(i--)
srcs[i]=(image.src='..');
という分かりやすい記述になる。さらに言えば、
const
srcs=new Array;
srcs.load=function(i){
const
image=new Image;
while(i--)
this[i]=(image.src='..');
}
srcs.load(16);
delete srcs.load;
とする方がより良いのかもしれない。
訂正
/* そもそも >>1 は
ありゃ、また失礼いたしました。
ご指摘ありがとうございます。
それはそうと、動的にsrcを書き換えてやる処理を走らせた場合、
画像の切り替え時に毎回画像データを読みに行くとか、そういうことは
無いのでしょうか?
元スレの質問に便乗してしまって申し訳ないのですが、宜しかったら
ご教示いただけるよう、お願いします。
以下の2つのソースで比較してみたところ、2番目のやり方だと
画像の切り替えがギクシャクするのですが...?
ご指摘いただいた内容を上手く理解できていないので、妙なソースを
書いてしまっているのでしょうか。
【最初のソース】
※これだと切り替えがスムーズに動いているように見えます。
<html>
<head>
<title></title>
<script language="JavaScript">
<!--
var cnt = 0;
var dat = new Array("sprn1.jpg","sprn2.jpg","sprn3.jpg","sprn0.jpg");
prLdImg= new Array();
for (i=0; i<dat.length; i++){
prLdImg[i] = new Image();
prLdImg[i].src = dat[i];
}
function nextImg(){
var obj = window.document.all('myImg');
if(timerID){clearTimeout(timerID);}
cnt++;
cnt %= dat.length;
obj.filters.revealTrans.Apply();
obj.src = dat[cnt];
obj.filters.revealTrans.Play();
var timerID = setTimeout("nextImg()",3000);
}
// --></script>
</head>
<body>
<img id="myImg" src="sprn1.jpg" style="filter:revealTrans(duration=2,transition=12)" onClick="nextImg()">
</body>
</html>
【2番目のソース】
※こちらだと、切り替え時に画像を読みに行っているようで
画像の切り替え時のフィルタ処理がギクシャクするのですが?
何かとんでもない勘違いをしているのでしょうか...。
<html>
<head>
<title></title>
<script language="JavaScript">
<!--
var cnt = 0;
var image=new Image,
srcs=new Array,
i=4;
while(i--){srcs[i]=(image.src='sprn' + i + '.jpg');}
function nextImg(){
var obj = window.document.all('myImg');
if(timerID){clearTimeout(timerID);}
cnt++;
cnt %= srcs.length;
obj.filters.revealTrans.Apply();
obj.src = srcs[cnt];
obj.filters.revealTrans.Play();
var timerID = setTimeout("nextImg()",3000);
}
// --></script>
</head>
<body>
<img id="myImg" src="sprn1.jpg" style="filter:revealTrans(duration=2,transition=12)" onClick="nextImg()">
</body>
</html>
おっしゃる通りです。その指摘は正しい。ど素人なことを書いてしまった。プクプクプク。。。
読み込む画像それぞれに Image オブジェクトを割り当てた場合、それら全ての Image オブジェクトに src プロパティをセットすることの副作用としての画像データ読み込みはそれぞれ順次完了するまで続くだろう。
しかし、1 つの Image オブジェクトを使いまわした場合、画像データ取り込みに必要な時間は十分には取られていないから、先読みは全て途中止めになっている。
後者では特にロード完了イベントがあれば対処できる。JScript で手早く書けば、
var
srcs=new Array;
(srcs.load=function($directory, $prefix, $count, $extension){
var
image=new Image,
i=$count;
do
this[i]=$directory+$prefix+i+$extension;
while(1<i--);
i++;
image.onreadystatechange=function(){
this.readyState=='complete'&&
++i<=$count&&
this.loadNext(i);
}
(image.loadNext=function(i){
this.src=srcs[i];
})(i);
})('../images/huukei/', 'sprn', 4, '.jpg');
delete srcs.load;
という感じの常套手段で回せば対応できる。。。が、わかりにくいな、これは。やはり結果的に「簡単」「確実」なのは、前者だ。やっちまった。。。
なんとかできました。ありがとうございました。