質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

setTimeout()で一瞬だけ文字を表示したい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,741

hinata_t

score 8

 前提・実現したいこと

Knockout.jsを使用して、サイトを作っています。
一瞬だけ文字を表示する機能を作成したいのですが、
EdgeやFirefoxで表示されないときがあります。
Chromeでは問題なく表示できます。

 該当のソースコード

<div class="hide" deta-bind="css:{'hide': !visible()}">
    <span>hoge</span>
</div>

<style>
    .hide {
        display:none;
    }
</style>
this.visible(true);       // 表示!!
setTimeout(function () {
    _this.visible(false); // 非表示!!
}, 1);

 質問

  1. ブラウザやバージョンによって、
    display:noneが適用されなくなる(hogeが表示される)までの時間に差があるのでしょうか?
    ※表示しようとしたときに、時間が来て「非表示」の処理が走っているのではないかと予想しています。
  2. EdgeやFirefoxでも、hogeを確実に表示することは可能でしょうか?
    ※ただし、表示する時間は0.001秒としたい。

上記ご教示いただけると助かります。
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+4

Knockout.js 日本語ドキュメント
"visible" バインディングによると、
HTMLのstyle属性でdisplay: noneを設定しているだけらしいので同期的な処理に思われます。

GitHubのリポジトリに全ソースコードが上がってるようなので、落として全文検索していけば見つかると思います。


表示する時間は0.001秒としたい。

パソコンやディスプレイ、人間の構造上のスペックの問題で不可能です。
結論はsetTimeoutじゃなくてrequestAnimationFrame使えなんですがその理由を説明していきます。

そもそも0.001秒という数字が出る時点で、今から解説する内容は一部既知であっても何故関係あるかの紐づけまで至ってないと思うので、根本から解説していきます。

まず機械の話をしていきます。
映像を表示するのは光ですが、映画館の映写機のようなもので似たような画像を1秒間に何十回もの間隔でカシャカシャ切り替えて実現しています。
機械版のパラパラ漫画ですね。
パソコンのディスプレイの主流は液晶ディスプレイですが、映写機と同じく「即興のフィルムを作ってカシャカシャ切り替える」事を実現する為の装置です。

このカシャカシャは一般的にフレームと呼ばれ、カシャカシャタイミングがフレームレートと呼ばれています。
格闘ゲームの波動拳は全体40フレーム(40f/60秒=0.67秒)みたいな感じで親しまれています。

このフレームレートですが、一般的にテレビ放送は秒間30フレーム、ゲームやパソコン等の能動的な操作を伴うものは秒間60フレームがベースになります。
秒間60フレームのルールは多くの場所で採用されており、例えば多くの液晶ディスプレイのリフレッシュレート(更新間隔)は60Hz(秒間60回書き換え)ですし、
Chromeを始めとする多くのブラウザのフレームレートは60FPS(秒間60回書き換え)です。

この秒間60回書き換えをミリ秒に換算すると、16.67msのタイミングで1度書き換える計算となります。
つまり、0.001秒という一瞬だけ表示させようとした場合、液晶ディスプレイやChromeの画面更新間隔は約0.017秒ですので、16/17の確率で何も表示されないことになります。

また、JavaScriptのsetTimeoutの仕様の問題もあります。
そもそもイベントとして登録された関数は条件を満たした時にフラグが立つだけで、実際に実行されるのは次回のイベントループで回ってきたタイミングであり、若干のタイムラグが発生します。
setTimeoutに関してもブラウザ毎に最小値が異なるようで、10ms以下を設定しても意味が無いケースが多いようです。

また、人間の一瞬に関しても定義が必要です。
人間の脳はアスリートクラスでも認知するまでに0.1秒が必要で、そこから行動速度で競う形になります。
参考サイト: https://games.yahoo.co.jp/qa/detail?qid=13115770323

従って、0.001秒にこだわる必要は一切なく、100msくらい表示してから逃げれば人の脳は目にも止まらない一瞬の速度で消えたと判断することでしょう。
フレーム数でいえば6〜7Fで、その程度を目安にしてやれば十分といえます。

とはいえ、0.001秒としたと言うことは出来るだけ小さい時間だけ表示させたいという技術的挑戦だと思いますので、
requestAnimationFrameを紹介して締めます。
Chromeなどのブラウザは約60FPSで駆動しているらしいのですが、常にではなく負荷を検知して勝手に30FPSに落としたり、バックグラウンド動作させた場合は勝手に1FPSに落としたりするようです。
つまり、何時画面が更新するかは誰にもわかりません。

JSはゲームやアニメーションにも使われる言語ですから、画面の更新タイミングがわからずアニメーションがカクカクしては意味がないわけですね。
その問題への回答としてrequestAnimationFrameが用意されています。
Chromeの画面更新が終わったと同時にこれで登録したイベントが確実に発火しますので、
次の更新までに終わるような処理を組み込む事で確実に等間隔で描画することが可能です。
1フレーム目で削除する事で最速で消すという事も実現出来るでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/05 22:51 編集

    丁寧な回答、ありがとうございました。m(_ _)m
    結局、1ミリ秒ではなく、もっと長い秒数で実装することにしましたが、
    機会があれば、requestAnimationFrameについても勉強してみたいと思います。

    キャンセル

  • 2018/09/06 01:14

    requestAnimationFrameを使っても1フレームの描画はできませんよ。
    ブラウザの描画が負荷で30FPSになったりするのは何を使っても変わりません。

    キャンセル

  • 2018/09/06 12:38

    30FPSになっても1フレームは1フレームかつ、最小の単位だと思いますが、
    Chromeが30FPSに制限しているのに、16.7msだけ表示する事が可能であるという指摘でしょうか?

    キャンセル

  • 2018/09/06 21:50

    > 30FPSになっても1フレームは1フレーム
    なるほどそういう意味でしたか。1フレームというのはディスプレイにおけるフレームのことを指して言っているのかと思った次第です。

    キャンセル

+3

[1について]
タイマーの最小解像度の問題で、多少の差はでるようです。
JavaScriptの1msは4ms(Qiita)

また、当然ですが、ブラウザやOSが過剰に処理を抱えている場合はsetTimeout の処理は後回しにされるかもしれません。

そもそも、最小の時間単位だとモニタのリフレッシュレートの関係で描画される間もなく……ということはよくあると思います。

そのほか、あなたの体調次第では、視認できないレベルの短さに見えます。

[2について]
おそらく1/1000秒で確実に描画する方法はないと思います。というかそんなの描画されていても視認すできないのでは……?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

※ただし、表示する時間は0.001秒としたい。

普通のOSとブラウザ環境では無理です。そもそも、モニターのリフレッシュレート(画面更新タイミング)自体が60Hzとか120Hzなので、1ミリ秒単位で表示を切り替えることができません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る