JavaScriptを使って記事本文のボリュームを画面数で表示する

本文は何画面分の量があるのか?
本文は何画面分の量があるのか?

あまり実用的ではないと思いますが、「いったいこのページの本文はあとどれくらいあるのだろう」という情報を、「◯分で読めます」以外の形で実装することを検討した記事です。

よくよく考えると不要なのではと思える要素ではありますが、物は試しということで。

構築環境
JavaScriptpure JavaScript

実現したいこと

実現したいことは以下の通りです。

  • 閲覧しているディスプレイ(ブラウザのウィンドウ)を基準に、「本文は画面分あるのか」を表示させる
  • ライブラリは使わない

スマホなどの小さな画面で閲覧する際に、「アクセスしたページのボリュームがどれくらいあるのか」という点は、案外無意識に気にしているものではないでしょうか?

当記事では、この点に対しての要望を満たす情報提示を目的としています。

完成予想図は以下のとおりです。

本文は何画面分あるのかを表示する
本文は何画面分あるのかを表示する

上図は以降に掲載するコードからさらに手を加えていますので、当記事のコードそのままでこうなるということではなく、その点は予めご了承下さい。

コード1:onloadを使う

先に前提となるHTMLの状態を提示します。
HTML部分に手を加えることなく導入可能なので、簡便さと言う意味では適しているかもしれません。


<body>
 <div id="page">
  <div id="main">
   メインコンテンツで、画面数取得の対象となる部分
  </div>
  <div id="sub">
   サイドバーやサブコンテンツなどメインコンテンツ以外の部分
  </div>
 </div>
</body>

上記の#mainの高さが閲覧中の画面サイズで何画面分あるのかを算出し、その値を#mainの最初の子要素として出力する、という前提のコードが下記のものです。


window.onload = function(){
  //コンテンツを包含する、idがmainの要素を取得
  var box = document.getElementById( "main" ) ;
  //idがmainの要素の高さを取得
  var cH  = box.clientHeight ;
  //画面の高さを取得
  var iH  = window.innerHeight ;
  //idがmainの要素が何画面分かを算出し、四捨五入で小数点第1位まで
  var num = cH / iH ;
 //divを生成
  var obj = document.createElement('div') ;
 //cssを当てる用にidを設定
  obj.id  = 'how-many-screens' ;
  //表示させる文言
  obj.innerHTML = "本文ボリューム: " + num + "画面分" ;
  //idがmainの要素の最初の子要素として挿入
  box.insertBefore( obj, box.firstChild ) ;
}

onloadを使い、要素が全てそろってからJavaScriptで高さを取得し、必要なパーツの作成や入れ込みを行う場合のコードです。

画像が多いサイトの場合は、こちらのonloadを使う方が正確な値が出せるでしょう。

コード2:DOMContentLoadedを使う

[2017.1.30追記]

記事公開後、q-azというサイトを運営されているzzさんに以下のような助言をいただきました。

DOMContentLoadedに関しては以下のページなどをどうぞ。

今回重要になる部分を上記ページより引用します。

DOMContentLoaded イベントは、最初のHTMLドキュメントの読み込みと解析が完了した時に発火し、 スタイルシートや画像、サブフレームの読み込みが終わるのを待ちません。

前項のコード1はonloadを使っており、全ての要素が表示されてからの高さが取得可能なのですが、その分表示が遅くなります。

対して、DOMContentLoadedは画像などの一部要素が表示される前に発火可能なトリガーであり、onloadより早いタイミングで高さの取得を開始させることができます。

ただし画像サイズ分の誤差が発生してしまいます。

従って多少の誤差を許容する前提であれば、画像があまりないサイトにはDOMContentLoadedを使う方法がよいかもしれません。

書き換える場合、以下のようになります。


document.addEventListener("DOMContentLoaded", function() {
  //コンテンツを包含する、idがmainの要素を取得
  var box = document.getElementById( "main" ) ;
  //idがmainの要素の高さを取得
  var cH  = box.clientHeight ;
  //画面の高さを取得
  var iH  = window.innerHeight ;
  //idがmainの要素が何画面分かを算出し、四捨五入で小数点第1位まで
  var num = cH / iH ;
 //divを生成
  var obj = document.createElement('div') ;
 //cssを当てる用にidを設定
  obj.id  = 'how-many-screens' ;
  //表示させる文言
  obj.innerHTML = "本文ボリューム: " + num + "画面分" ;
  //idがmainの要素の最初の子要素として挿入
  box.insertBefore( obj, box.firstChild ) ;
});

DOMContentLoadedのタイミングと画像状態

DOMContentLoadedを使う場合、imgの中身自体は表示されないタイミングであり、その結果imgの高さは0のはずでした。

しかし、ChromeのWaterfallで何度も計測したところ、珍しくない頻度で画像の一部が表示された状態での計測になっているらしいとわかりました。

実際にconsole.log()でページ上部の画像の高さを取得したところ、たまに値がとれていましたので、必ず画像なしの画面数を表示できるわけではないと言えそうです。

なお、DOMContentLoaded自体に問題があるわけではなく、実装したコードの関係などで、イベントの発火から実際の計測に移るまでの間のタイムラグが原因だと思われます。

関連する事項の検討

今回の機能に関連して考えていた事項がいくつかありますしたので、以下に記載します。

「◯分で読めます」との比較に関して

たまに見かける「◯分で読めます」というのは、記事の分量を知りたいという要求に対し、本文の文字数というストレートすぎる要素から算出された情報(ではなかったらごめんなさい)です。

どの環境でも変わらない数値という普遍性はありますが、画面サイズなどの閲覧環境が考慮されていない情報でもあり、個別の状況下では目安としてあまり役に立たないように思えます。

そこで、「なぜ分量を知りたいのか?」という点から考え、より良い判断材料として「後何画面スクロールすれば本文全てが読めるのか」という情報の提示を考えました。

この部分を書くと長くなるので、興味のある方は以下のページをご覧下さい。

画面数の数値に関して

前出のコードでは、画面数を整数のみで表示させています。

今回必要としていたのは、読むべきかどうかを判断できる程度の目安なので、概算のような大雑把さが適しいる考えたためです。

特にスマホのような小さな画面で「4.2画面分」などと書かれると、むしろ判断しがたいのではないでしょうか?

なお、当サイトではPCディスプレイ程度の大きさの場合は、以下の理由により小数点第一位(二位を四捨五入)まで表示する形で実装しています。

  • 小数点まで付けても問題が無い(PCではそれほど目に入らないと思われるため、メリットデメリットも薄い)
  • PCの画面はスマホよりも縦幅が長いため、整数値ではさすがに大雑把すぎる

とはいえスマホに比べて目立たない上に重要性も低いため、表示する必要性自体もあまりありませんが。

要素の挿入に関して

掲載のコードはHTMLを触らずに要素を入れ込めるので便利な反面、パーツ挿入のタイミングで、挿入位置以下の要素が下にずれ、見映えもあまりよろしくありません。

position:absolute;などで他の要素に影響を与えない形で挿入し、必要な隙間は予め作っておくことで対応は可能ですが、それもまた面倒ではあります。

そのため現在実験的に設置している当サイトでは、HTMLを触る手間のある以下の形にしています。

  • あらかじめ、画面数以外のHTML要素を挿入予定の箇所に作成
  • JavaScriptで挿入するのは画面数のみ

実装に関してはいくつも方法があると思いますので、サイトにあわせて最適と思われる形を探すことになるでしょう。

なお、当サイトの表示でも突然画面数が挿入されるためピョコッと左に動く部分は残ります(※現在はDOMContentLoadedの方を使っているので目立たないレベルのはずです)。

人によっては不快な動作に感じる可能性もありますが、個人的にはこういう動作自体が視線を集めるフックになると思っていますので、現状でも許容範囲の状態かなと考えています。

結び

考えていたことを実際に形にして、現在は当サイトに設置しています。

仕組みは簡単ですし、それなりに筋の通った理屈もあるかと思いますので、最終的にはそれなりの形にまとまったかなとは思います。

懸念事項

実際に付けてみたところ、スマホ閲覧時に表示される画面数が思いのほかインパクトのある数値でした。

長めの記事を選んで表示すると50画面を越えています。

記事冒頭で「このページは50画面以上あります!」と知らされた場合、ユーザーのモチベーションに悪影響がでて直帰が増えるのではと懸念しています。

ページ数表示の付近に後で読む系のボタンをつけると多少はフォローできるかとは思い、Pocketボタンも付けました。

しかしながら、どちらにせよページから離脱する行為に近いので、数値的には意味がないかもしれません。

こうして記事にしておいてなんですが、あまりお勧めできないパーツかなと思っています。

1人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄