anti scroll

ブラウザと小説の新しい関係を模索する

だれでも簡単にページ組版が扱えるウェブ・コンポーネント「nehan-player」を公開しました

nehanによるページ組版を簡単に扱えるウェブコンポーネントを作ってみました。

導入

テキストの内容を、サーバーからsrc属性で読み込む場合は、こんな感じになります。

<nehan-player writing-mode="horizontal-tb" width="responsive" src="/path/to/your-novel.html" height="500" font-size="16" layout="1x2">
</nehan-player>

<script src="https://cdn.jsdelivr.net/npm/nehan-player@0.0.2/dist/nehan-player.min.js"></script>
<script>
  NehanPlayer.initialize(); // 初期設定(オプションなし)
</script>

タグの中にそのまま内容を記述したい場合は、<div slot="content"> ~ </div>の中に本文を記述します。

<nehan-player writing-mode="horizontal-tb" width="responsive" height="500" font-size="16" layout="1x2">
  <div slot="content">
    <h1>はじめてのnehan-player</h1>
    <p>はじめてのテキスト</p>
  </div>
</nehan-player>
  
<script src="https://cdn.jsdelivr.net/npm/nehan-player@0.0.2/dist/nehan-player.min.js"></script>
<script>
  NehanPlayer.initialize(); // 初期設定(オプションなし)
</script>

ブログやホームページでも、本文にHTMLをそのまま打ち込める環境なら、問題なく導入できると思います。

はてなブログの場合は、管理画面から「デザイン設定」→「カスタマイズ」→「フッター」と進んで、<script> ~ </script>の部分をコピペしておくと、<nehan-player> ~ </nehan-player>の部分を入力するだけでOKです。ただHTMLをそのまま入力できるのはProプランのユーザーのみらしいですので、無料ユーザーはnehan-playerを記事中では使えないということになりますね…

ちなみにウェブコンポーネントということで、親ページからの影響を受けませんし、親ページに影響を与えることもありません。

完全に独立した表示要素として、安心して導入できます。

またレスポンシブにも対応しているので(nehan-playerタグのwidth属性を"responsive"にするだけ)、スマホ対応も簡単です。

なおnpmから使うときは、

npm install nehan-player --save

のようにインストールし、

import { NehanPlayer } from 'nehan-player';

NehanPlayer.initialize();  // 初期設定で使う(オプションなし)

で、呼び出せます。

initializeに与えるオプションついてはドキュメントを参照してください。

デモ

さて、ここで、はてなブログにウェブコンポーネントを貼り付けたかったのですが、どうやらHTMLをそのまま記述できるモードは、現在Proユーザーに限定されているようです。

なので、ちょっと裏技的ですが、はてなブログaboutページ(HTMLを入力できる)に、nehan-playerを貼り付けて見ました。

ひと手間が必要な場合

1. 配色を変えたい

一応、nehan-playerのページに、こちらで用意したテーマがありますので、利用するなり、編集するなりしてください。

使い方は、nehan-playerタグのtheme属性に、テーマファイルへのパスを記述するだけです。

<nehan-player (省略) theme="/path/to/your-theme.css"></nehan-player>

ただし、公式のテーマはどれも内部で、default-layout.cssっていう別のファイルを読み込んでいるので、テーマファイル単体だけじゃなく、default-layout.cssも忘れずにサーバーに設置してください。

2. 画面の左右をクリックしたらページ送りしたい

initializeを以下のように呼び出すと、画面の左右クリックでそれぞれのページに移動するようになります。

NehanPlayer.initialize({
  onClickLeftPage(player){
     player.gotoLeftPage();
  },
  onClickRightPage(player){
     player.gotoRightPage();
  }
});

3. 読み込んだテキストを、ちょっと編集したい

initializeonFetchContentを使います。

NehanPlayer.initialize({
     onFetchContent(src: string, content: string){
         if (src.endsWith(".txt")) {
            return content.replace(/^\n+/, "").replace(/\n/g, "<br>");
         }
         return content;
     }
});

4. Androidで縦書きを扱いたい

これはちょっと少し工夫が必要です。

というのも、Androidには縦書きに対応したフォントが入ってないこともあり、その場合は自分で提供しないといけないからです。

やることは2つで、

  • 縦書きに対応したフォント(例えばIPA明朝とか)をサーバーに置く
  • それを@font-faceで読み込むcssを「headタグ」に入れる(ウェブコンポーネントなのに)

です。

ちなみに2つ目で「cssをheadタグに入れる(ウェブコンポーネントなのに)」と書きましたが、どういうことでしょうか。

実はこのcss、本当はウェブコンポーネントの「内部」に入れないといけないのです(じゃないと外部のページに影響を与えないというウェブコンポーネントの趣旨と矛盾するから)。

が、どうも現状のブラウザは、どれもshadom DOMから@font-faceが読み込めないようなのですね。

上のリンクは2014年の議論ですが、どうやら技術的に、とても難しいことらしいのです。

で「ものすごい強い要請があるまでは、このままにしとこうや」って感じになってるみたいでして…

というわけで、これを回避するため、@font-faceを指定したファイルは、普通にHTMLのヘッダに読み込む必要があります。ようするに、

  • @font-faceを含まない普通のcss(テーマとか)は、ウェブコンポーネントの内部に読み込まないといけない(まあそうじゃないとウェブコンポーネントにする意味がないので、当たり前ですが)
  • けど、@font-faceを含むcssは例外。shadow DOMの外側(shadow host側って言うそうですが)じゃないと読み込めない。

ということです。