QA@IT

onloadが複数ある場合について

3775 PV

はじめまして。

javascriptで簡易おみくじを作りましたが、"文字の切り替え"と"
文字の点滅"の部分の速度が不規則です。
原因は、複数のonloadと,及び"大吉~小凶"と点滅部分の"運"のIDが
同じだからと思いますが、それならばどのように書き換えればいいのか
分かりません。ご教示いただけませんか。

なお、下記の質問のソースコードは、IE以外のブラウザでは、うまく動作するか
分かりません。また、保存する場合は、"unicode"形式にしてください。

(ソースコード)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <HTML>
 <HEAD>
 <META http-equiv="Content-Type" content="text/html; charset=shift_jis"> 
 <meta http-equiv="Content-Script-Type" content="text/javascript">
 <meta http-equiv="Content-Style-Type" content="text/css">

 <TITLE>おみくじ</TITLE> 


<SCRIPT type="text/javascript">
<!--

var txt1="<span>&#x301C 今年は</span><span>"</span><span id='blink_1' style='color:deeppink; font-size:26px; font-weight:bold;'>大吉</span><span>"</span><span'>ですよ</span><span>♪♪♪ </span><span>&#x301C</span>";
var txt2="<span>&#x301C 今年は</span><span>"</span><span id='blink_1' style='color:deeppink; font-size:26px; font-weight:bold;'>中吉</span><span>"</span><span>ですよ</span><span>♪♪ </span><span>&#x301C</span>";
var txt3="<span>&#x301C 今年は</span><span>"</span><span id='blink_1' style='color:deeppink; font-size:26px; font-weight:bold;'>小吉</span><span>"</span><span>ですよ</span><span>♪ </span><span>&#x301C</span>";
var txt4="<span>&#x301C 今年は</span><span>"</span><span id='blink_1' style='color:chocolate; font-size:26px; font-weight:bold;'>大凶</span><span>"</span><span>ですよ</span><span>!!! </span><span>&#x301C</span>";
var txt5="<span>&#x301C 今年は</span><span>"</span><span id='blink_1' style='color:chocolate; font-size:26px; font-weight:bold;'>中凶</span><span>"</span><span>ですよ</span><span>!! </span><span>&#x301C</span>";
var txt6="<span>&#x301C 今年は</span><span>"</span><span id='blink_1' style='color:chocolate; font-size:26px; font-weight:bold;'>小凶</span><span>"</span><span>ですよ</span><span>! </span><span>&#x301C</span>";

function omikuji() {
 document.getElementById("good_or_bad").innerHTML=txt;
 rand = Math.floor(Math.random()*6);
 if (rand == 0) document.getElementById("good_or_bad").innerHTML=txt1; blink1();
 if (rand == 1) document.getElementById("good_or_bad").innerHTML=txt2; blink1();
 if (rand == 2) document.getElementById("good_or_bad").innerHTML=txt3; blink1();
 if (rand == 3) document.getElementById("good_or_bad").innerHTML=txt4; blink1();
 if (rand == 4) document.getElementById("good_or_bad").innerHTML=txt5; blink1();
 if (rand == 5) document.getElementById("good_or_bad").innerHTML=txt6; blink1();
}

var txt="<p id='good_or_bad'><span>&#x301C </span><span id='output'></span><span > が出るか…それは</span><span style='color:gold; font-size:26px; font-weight:bold;'>"</span><span id='blink_1' style='color:gold; font-size:26px; font-weight:bold;'> 運 </span><span style='color:gold; font-size:26px; font-weight:bold;'>"</span></span><span>次第です</span><span > &#x301C</span></p>";

function reset(){
 document.getElementById("good_or_bad").innerHTML=txt;
 wordChange();
 blink1();
}

 // -->
 </SCRIPT>

<script type="text/javascript">
<!--

onload=function(){
blink1();
wordChange();
}

 var n = 0;
function wordChange()
  {
var iv = 3000;
var words = [ '鬼', '福' ,'蛇' ,'仏' ];
var color = ["chocolate", "deeppink", "chocolate","deeppink"];
document.getElementById('output').innerHTML = words[n];
document.getElementById('output').style.color = color[n];
document.getElementById('output').style.fontSize =fontSize="26px";
document.getElementById('output').style.fontWeight ="bold";
 n++;
 if (n > words.length - 1) n = 0;
 setTimeout(wordChange, iv);
  }

var iv = 1000;
function blink1()
 {
 if (document.all("blink_1").style.visibility == "visible")
 {
 document.all.blink_1.style.visibility = "hidden";
 }
 else
 {
 document.all.blink_1.style.visibility = "visible";
 }
 setTimeout("blink1()", iv);
 }
//-->
</script>

 </head>


<BODY bgcolor="black" text="white" onload="wordChange();blink1();">

<script type="text/javascript">
<!--
document.write("<p id='good_or_bad'>");
document.write("<span>&#x301C </span>");
document.write("<span id='output'></span>");
document.write("<span> が出るか…それは</span>");
document.write("<span style='color:gold; font-size:26px; font-weight:bold;'>"</span>");
document.write("<span id='blink_1' style='color:gold; font-size:26px; font-weight:bold;'> 運 </span>");
document.write("<span style='color:gold; font-size:26px; font-weight:bold;'>"</span>");
document.write("<span>次第です&#x301C</span>");
document.write("</p>");
//-->
</script>
<br>
<input type="button" id="omikujiButton" value="おみくじ" onClick="omikuji();">
<br>
<input type="button" value="リセット" onClick="reset();">


 </BODY>
 </HTML> 

  • javascript はブラウザ依存の部分が多いです。なので、javascript の質問をする場合は必ず対象とするブラウザ / バージョンを書きましょう。 -
  • ご指摘は分かりました。
    しかし、ブラウザはたくさんありますので、分かりません。ただ、ソースコードでは、IEでは動作します。
    なお、function wordChange(){}内のsetTimeout(wordChange, iv);の中の"wordChange"に()が抜けていました。すみませんでした。
    -
  • 表題の「onloadが複数ある場合」の対応についてもブラウザによって変わってくるのですが・・・ -
  • これも、ブラウザによって変わるのですか。
    分かりました。
    -
  • 上に書いていた"wordChange"に()は不要のようです。
    すみませんでした。
    -

回答

ご質問の内容はonloadやIDの問題では無いと思います。

しかしながらwindow.onloadとbody要素のonload属性の両方に同じ処理を仕込むのは、少なくともIEでは両者同義であり、後者によって上書きされてしまっているので全く意味がありません。
bodyの方はブラウザによって挙動が違うことがあるので、window.onloadだけで十分と思います。

また、IDについては個別に振るべきですが、根本的な原因ではありません。

根本的な原因はタイマーによるループの多重動作です。
JavaScriptではタイマーは無数に並行で動かすことができ、setTimeout()setInterval()によって新たなタイマーが作動します。
これは明示的に止めてやらない限り途中でキャンセルされません。

現在の作りではリセットボタンを押すたびに点滅動作のループが新たに起動してしまい、2重、3重と延々と増えていくことになります。
それらが個別に点滅を指示するものですから、点滅間隔がおかしなことになります。
ですから愚直な対応方法としては新たにループを開始させようとするときは、以下のように動作中のタイマーを必ずキャンセルさせるようにします。

var blinkTimerId = null;
if (blinkTimerId) {
    clearTimeout(blinkTimerId);
}
blinkTimerId = setTimeout("blink1()", iv);

wordChange()の方も同様です。

なお、この方法はあくまで挙げられた問題を解決する為だけの部分に絞ったものであり、根本的な改善を求めるにはそもそも点滅処理を多重起動しようとしてしまう構造を見直すべき必要があると思います。
他にも文法エラー等が多数あり問題が多いですがここでは言及いたしません。

編集 履歴 (2)
  • 回答ありがとうございました。

    ご指摘通りにスクリプトとhtmlタグを変えてみましたが(タイマーのキャンセル部分の書き換えと、bodyタグ内の"onload"以下の削除)、"運"の点滅速度がおかしいです。

    『点滅処理の多重起動』に無理があるのですね。
    それならば、htmlの"marquee"を使って点滅させることになりますね。
    これも何か厄介ですので、何かいい方法ないでしょうか。
    -
  • 「点滅させたい」という目的に絞るならば、blinkかmarqueeといきたいところですが、HTML5以降はサポートされておらず、今後はごく一部のブラウザでしか使えません。
    賢明な代替方法としてはCSSのanimationプロパティを使うことです。こちらが参考になると思います。
    http://webkcampus.com/201406/561/
    -
  • 補足ですが、瞬間点滅させたい場合はkeyframesの設定を以下のようにします。
    @keyframes blink{
    0%,49.9% {opacity:0;}
    50%,100% {opacity:1;}
    }
    opacityはvisibility:visible/hiddenでも良いです。
    -
  • もう一つ補足ですが、onloadを複数設定したい場合はaddEventListenerを調べてみたください。 -
  • バッチリです。marqueeだと頻繁にズれますが、CSSでも点滅という『動作』もやれるのですね。おまけに、点滅速度も変えられるし、スタイルも設定できるし、これを参考にさせていただきます。ありがとうございました。文法エラーも指摘していただけたら、幸いです。 -
  • 現在の仕様ではHTML/CSS/JSは三位一体であり、結局HTMLページの装飾やアニメーションはすべてCSSで行われます。(SVGやCanvasなどは別ですが)JSはあくまでそれらを制御するだけというのを念頭に置いておいてください。
    文法エラーのひとつはダブルクォーテーションをダブルクォーテーションで囲んだときにエスケープされてない点です。その他はブラウザの『開発者ツール』で確認してみてください
    -
  • 確かに"運"をくくっている""は、&quot;になっていませんね。していたつもりですが。わかりました。『開発者ツール』でのミスの確認の仕方は、いまいち使い方が分からないのですが、勉強して見ます。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。