- ベストアンサー
一文字ずつ表示するパフォーマンスを改善する方法
- ブラウザによって表示にかかる時間が異なるため、一文字ずつ表示するスクリプトのパフォーマンスを改善したいです。
- ブラウザの描画性能にも影響されるため、より軽く動作する方法を探しています。
- 一文字ずつ表示する際の処理時間を最適化することで、表示のスムーズさを向上させたいです。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
なにかの、さんこうになるかな? げんじょうのじょうたいでうごかすと <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <title>TEST</title> <body> <div id="CONTENT"> </div> <script type="text/javascript"><!-- var D = document, o = D.getElementById("CONTENT"), t = 'ああああああああああ'.split(''), c = 0; var len = t.length, tmId = setInterval( Insert , 100 ) ; function Insert ( ) { if( c === len && tmId ) { clearInterval(tmId); tmId=0; return; } o.firstChild.nodeValue += t[c++]; } //--> </script> //============ まず len をつかわないようにする はいれつ t[c++] が null を、かえすとおわるようにする いっそうのこと、setTimeout をりようすると tmId もひつようなくなる。 Dはいちどしかつかわないのではぶく o には、firstChildをつけておく var o = document.getElementById("CONTENT").firstChild, t = 'ああああああああああ'.split(''), c = 0; function Insert ( ) { var ch = t[c++]; if( ch ) { o.nodeValue += ch; setTimeout( Insert , 100 ); } } Insert ( ); //============ かんすう Insert をていぎして、よびだすくらいなら、なまえをはぶいてみる。 arguments.callee は、そのかんすうそのものをさす var o = document.getElementById("CONTENT").firstChild, t = 'ああああああああああ'.split(''), c = 0; (function ( ) { var ch; if( ch = t[c++] ) { o.nodeValue += ch; setTimeout( arguments.callee , 100 ); } })(); //============ へんすう o t c をおぶじぇくとにする var obj = { 'e': document.getElementById("CONTENT").firstChild, 't': 'ああああああああああ'.split(''), 'c': 0 }; (function ( ) { var ch; if( ch = obj.t[obj.c++] ) { obj.e.nodeValue += ch; setTimeout( arguments.callee , 100 ); } })(); //============ objがぐろーばるへんすうなので、むめいかんすうのぱらめーたとしてわたす。 (function ( obj ) { var ch; if( ch = obj.t[obj.c++] ) { obj.e.nodeValue += ch; setTimeout( arguments.callee , 100 ); } })( { 'e': document.getElementById("CONTENT").firstChild, 't': 'ああああああああああ'.split(''), 'c': 0 } ); しかし、うえのぷろぐらむはうごかない arguments.calleeで、じぶんじしんをよびだすときに ひきすうとして obj をわたしていないから そこで、むめいかんすうにしたように、よびだすかんすうも、むめいかんすうのひきすうとして objと、いっしょにわたす (function ( obj ) { var ch; if( ch = obj.t[obj.c++] ) { obj.e.nodeValue += ch; setTimeout( (function ( cb, obj2 ) { return function() { cb( obj2 ); };})( arguments.callee, obj), 100 ); } })( { 'e': document.getElementById("CONTENT").firstChild, 't': 'ああああああああああ'.split(''), 'c': 0 } );
その他の回答 (4)
- fujillin
- ベストアンサー率61% (1594/2576)
質問の回答にはなっていないけれど… 表示を制御したいのだと解釈して、違う発想でのサンプル。 (一文字ずつの表示じゃなくて、連続的にしちゃったけど…) <html> <head> <style type="text/css"> div.box { position:relative; } div.box #text1 { position:absolute; white-space:nowrap; overflow:hidden; } </style> <script type="text/javascript"> window.onload = function() { var e = document.getElementById('text1'); clip(0, e.offsetWidth); } function clip(p ,endp) { var e = document.getElementById('text1'); e.style.clip = 'rect(auto ' + p + 'px auto auto)'; p += 3; if (p < endp) { setTimeout('clip(' + p + ',' + endp + ')', 100); } else { e.style.clip = 'auto'; } } </script> </head> <body> <div class="box"> <span id="text1">0123あいう4566789</span> </div> </body> </html>
お礼
fujillinさん回答ありがとうございます。 visibilityをいじったりしてみたこともあったのですが、clipという発想はありませんでした。しかも速かったです! たしかにメインの内容とは違うのですが、別の部分でぜひ使わせてもらいたいと思います。
- babu_baboo
- ベストアンサー率51% (268/525)
かうんた~じゃなかったんだね。ちゃんとみてなかった。ごめん。 おなじ、た~げっとを、していすると、おかしくなるけど こういうのは、どうでしょう。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <title>TEST</title> <body> <div id="a"> </div> <div id="b"> </div> <script type="text/javascript"><!-- var substrTimer = (function ( ) { return function ( target, str, interval ) { var doc = document; var obj = { 'substr' : str.split( '' ), 'count' : 0, 'timerId': null }; var node = doc.getElementById( target ); if( node ) { while( node.hasChildNodes( ) ) node.removeChild( node.lastChild ); obj.target = doc.createTextNode( '' ); node.appendChild( obj.target ); obj.timerId = setInterval( (function ( _obj ) { return function ( ) { var character = _obj.substr[ _obj.count ]; _obj.count += 1; if( character ) _obj.target.nodeValue += character; else clearInterval( _obj.timerId ); }; } )( obj ), interval ); } }; })(); substrTimer( 'a', 'きょうのてんきは、はれのちくもりのちあめのちゆき。', 100 ); substrTimer( 'b', 'けいほうは、ありません。', 200 ); </script>
- babu_baboo
- ベストアンサー率51% (268/525)
createTextNode(text[count++])で、てきすとを ついかしつづけることになるよ。 いちど、のーどをくっつけたら、そののーどのあたいを かえるだけでいいじょ。 obj = _d.getElementById("CONTENT") こののーどには、おそらく、子のーどがあり、なおかつさいしょの子が てきすとのーどだとすると obj = _d.getElementById("CONTENT").firstChild で、そのあたいをいじりたいなら obj.nodeValue = text[count++]; になるよ ちなみに、めんどうくさくながいやつ(こーど)は、さいきんここにも あらわれる(こうりん?)、ものすご~~~いとおもわれるかたに、 (というか、くものうえのそんざいのようなひとに) おしえていただきました。 とにかく、きのうべつに、さいぶんかし、それをこうちくするような かんがえかたは、いまのじぶんには、まだまだで。。。。 きっと「タイマーもぶんりできるだろう!」っていわれそうです。 「オブジェクト指向」になってるのだろうか?
- babu_baboo
- ベストアンサー率51% (268/525)
document.bodyをinnerHTMLでかきかえるのは、いろいろないみで まずい(おそい)とおもう。 どこぞにちいさいりょういきをもうけて、そこだけかきjかえては どうでしょう? text = "01234566789".split(''); みたいにはいれつにして text[++count] するとか。 できるだけ、ぐろーばるへんすうをつかわないとか・・・ むだに、ながくかいてみました。 ぜんかくは、はんかくにしてね。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <title>test</title> <body> <div id="a"> </div> <div id="b"> </div> <script type="text/javascript"><!-- var Display = function ( num ) { return this.nodeValue = num + ''; }; var CountUpTimer = function ( ) { this.init.apply( this, arguments ); }; CountUpTimer.prototype.init = (function ( ) { return function ( target, max, interval, endFunc ) { var e, p; this.cnt = 0; this.max = max; this.interval = interval; this.endFunc = 'function' === typeof endFunc ? endFunc: null; if( 'string' == typeof target ) e = document.getElementById( target ); else e = target; p = e; if( e.hasChildNodes() ) e = e.firstChild; while( e && 3 !== e.nodeType ) e = e.nextSibiling; if( !e ) { e = document.cteateTextNode( this.count ); p.appendChild( e ); } this.target = e; this.timerId = null; return true; }; })(); CountUpTimer.prototype.start = (function ( ) { return function ( ) { if( this.timerId ) this.stop( ); Display.call( this.target, this.cnt ); return this.timerId = setInterval( (function ( that ) { return function() { that.count( ); }; })( this ), this.interval); }; })(); CountUpTimer.prototype.stop = (function ( ) { return function ( ) { return clearInterval( this.timerId ); }; })(); CountUpTimer.prototype.count = (function ( ) { return function ( ) { this.cnt += 1; Display.call( this.target, this.cnt ); if( this.cnt === this.max ) { this.stop( ); this.endFunc && this.endFunc.call( this ); } return this.cnt; }; })(); var counter1 = new CountUpTimer( 'a', 10, 1000); var counter2 = new CountUpTimer( 'b', 100, 100); counter1.start(); counter2.start(); //--> </script>
お礼
すみません、babu_babooさんに書いていただいたコードが今の自分ではわからない部分も多いため、今調べています。 innerHTMLで書き換えるのはコストが大きすぎるようなので、とりあえずappendChildを利用して書き換えました。 それとsetintervalの数値を小さく、文字列を多くして結果をわかりやすくしました。 <body> <div id="CONTENT"></div> <script type="text/javascript"> var _d = document, obj = _d.getElementById("CONTENT") , text = "あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ" , count = 0, len = text.length; text = text.split(""); InsertTimer = setInterval( Insert , 1 ) ; function Insert (){ if(count===len&&InsertTimer) { clearInterval(InsertTimer); InsertTimer=0; return; } obj.appendChild(_d.createTextNode(text[count++])); } </script> </body> なぜかchromeで一文字のテキストノードをappendchildで挿入すると、2行目からの動作が変になので対応を考えています(汗
お礼
お礼が遅れてしまって申し訳ありませんでした。 とても参考になっています。 現状では2で挙げていただいた部分を修正した状態だったのですが、IEで速度が向上しFirefoxでのパフォーマンスが他のブラウザに比べて圧倒的に悪い状態でした。 Firefoxはグローバル変数の参照と書き換えが以上に遅いようなので使う回数を減らしたかったのですがやり方がわからず・・・(というか1の回答でさえ理解できていませんでした) ですがパラメーターの利用・自身にパラメーターをつけて呼び出すという方法は非常に使えそうです。これでモダンブラウザ上でなら40ms以上であれば動作を統一できるくらいまで速くなりました。 改善の方向と自分の理解できていない部分が少しずつ見えてきた気がします。今回はちょっと自分の知識が足りなさ過ぎるため、このあたりで一度回答を締め切り勉強しなおしてみようと思います。 babu_babooさんありがとうございました!