anti scroll

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

nehan-player v0.1.1を公開しました

nehan-playerの0.1.1を公開しました。

tategakibunko.github.io

変更点

  • NehanPlayer.initializeにて、cssTextオプションを指定できるようになりました。
  • ページ番号(ノンブル)の表示位置が、ページ送りメニューバーの中ではなく、本文画面の中に表示されるようになりました。

cssTextオプションについて

nehan-player要素のスタイルはcssFilesオプションで読み込むスタイルシート群を指定できるのですが…

NehanPlayer.initialize({
  cssFiles: ['path/to/my-style.css']
});

しかし、外部ファイルをわざわざ用意したくない場合は、cssTextオプションが便利です。

NehanPlayer.initialize({
  // メニューバーは非表示
  cssText: "#menu { display: none }"
});

ページ番号の表示位置の変更

これまでのページ番号は、ページ送りボタンと一緒にメニューバー内に表示されていました。

しかしこれを、本文画面の要素として表示させることにしました。

f:id:convertical:20210417152803p:plain
本文画面にページ番号を表示

このデザイン変更により「メニューバーは必要ないかな」というときに、安心して(スタイル定義で)消去できるようになりました。

f:id:convertical:20210417152831p:plain
メニューバーを消したデザイン

縦書き文庫のビューアーをリニューアルしました

縦書き文庫のビューアーを久しぶりにリニューアルしました。

いくつかあった不満点を、それなりに改善できたと思います。

旧ビューアーの不満点

  • 目次、登場人物、コメントなどの各種情報が確認しにくかった(下方向へのスクロールが必要だった)
  • 解像度の大きいPCで横幅が余ってしまっていた
  • 横書きが読みにくかった(縦書きを初期設定にしているので、横幅がでかくて読みにくかった)
  • 表示設定を変えると、先頭ページに戻されてしまっていた

新しいビューアーの改善点

  • 目次、登場人物、読者分析、コメント、お気に入りユーザー、しおりなどの情報が、上部のタブから簡単に確認できるようになりました。

f:id:convertical:20210328222945p:plain
上部のタブから各種情報が確認できるように

  • 見開きに対応したので、横書きが読みやすくなりました。

f:id:convertical:20210329063153p:plain
見開きで横書きも読みやすく

  • 目次の情報が作品の左上に表示されるようになりました。

f:id:convertical:20210328223030p:plain
目次の情報が左上に表示されるように

  • 画面サイズに合わせて、ビューアーの幅が勝手に伸張するようになった(レスポンシブになった)ので、解像度の大きいPCでも横幅が有効に使えるようになりました。
  • 表示設定を変えても、先に見ていた内容のページ(になるべく近いところ)に戻れるようになりました。
  • ページ送りボタンのUIを削除したので、縦幅を増やすことができました。
  • UIをマテリアルデザインに統一したので、スマホでの操作がより直感的になりました。

とまあ、こんな感じです。

その他、注意点

  • 新しいビューアーの表示設定は、右上の歯車アイコンから行います。

f:id:convertical:20210329092856p:plain
表示設定の変更

  • ビューアーを新しくした影響で、エディタ画面での「プレビュー」機能が(現在のところ)使えなくなっています。

プレビューは、いずれ復活させたいのですが、対応時期は未定です。

だれでも簡単にページ組版が扱えるウェブ・コンポーネント「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の部分(下4行の部分)をコピペしておくと、記事中ではnehan-playerの部分だけ入力するだけで良いです。ただ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側って言うそうですが)じゃないと読み込めない。

ということです。

数式の表示とプログラムの色付け表示に対応しました

縦書き文庫で数式とプログラムの自動色付け表示ができるようになりました。

数式

数式は文の途中に差し込む場合(インライン表示)と、行全体を使って表示する場合(ブロック形式)のそれぞれで書き方が異なります。

文の途中に差し込む場合は、次のように書きます。

[math $sin$theta]は、日本語で「正弦」といいます。

書き方は[math 数式]です。

実際に表示するとこんな感じになります。

f:id:convertical:20210226170956p:plain

行全体を使って表示する場合はmathタグを使います。

<math>
c = $pm$sqrt{a^2 + b^2}
</math>

実際に表示するとこんな感じになります。

f:id:convertical:20210226171033p:plain

色々な数式の記述についてはKaTexのサイトを参照してください。

ちなみにKaTexでは\(バックスラッシュ)で書く記号を、縦書き文庫では$(ドルマーク)で書くことに注意してください。

プログラムの色付け表示

こんな感じでプログラムを書くと、言語(下の場合は javascript)に応じた色付けがされます。

<pre><code class="lang-javascript">
let a = "foo";
console.log("a is %s", a);
</code</pre>

もちろん javascript の部分は、プログラムの中身がhtmlなら htmlcssなら css などと書き換えてください。

実際に表示させると、こんな感じになります。

f:id:convertical:20210226171256p:plain

ちなみに投稿フォームにて、入力フォーマットの項目を「マークダウン記法」にすると、もう少し簡単に書けます。

```javascript
let a = "foo";
console.log("a is %s", a);
```

またプログラムについて別のページから参照させたい場合は、id属性をつけて、別ページからアンカーリンクを貼ると便利ですが、次のように書くとプログラムにid属性を与えることができます。

```javascript#program1
let a = "foo";
console.log("a is %s", a);
```

上の例ではprogram1というid属性を与えています。

まとめ

小説投稿サイトで数式やプログラムを記述することは多分ないでしょうが、技術的な内容や学術的な内容も書けるようになると面白いかなあと思って、対応してみました。

なお数式についてはKaTex、プログラムの色付けについてはhighlight.jsを利用しました。

どちらも素晴らしく使いやすいライブラリで、作者様には感謝の気持ちでいっぱいです。

アンカーリンクと、リンク先のプレビューに対応しました

アンカーリンクと、リンク先のプレビューに対応しました。

アンカーリンクとは

id属性を付けた要素に対して、<a href="#そのidの値">...</a>のように宣言したリンクのことを、アンカーリンクといいます。

リンクのhref属性の値が #(シャープ)から始まっていることに注意してください。

こうして作成したリンクは、

  1. クリックすると、リンク先の要素が記述されたページに移動できます。
  2. マウスを乗せると、リンク先の要素がプレビューで確認できます。

記述例1

<blockquote id="bq1">「強い者が勝つのではない。勝った者が強いのだ」</blockquote>
[page-break]
この<a href="#bq1">発言</a>は、ドイツの皇帝と呼ばれた「ベッケンバウアー」によるものです。

f:id:convertical:20210220100100p:plain
マウスを乗せるとアンカーリンク先のプレビューが表示される

ここではblockquoteタグに使っていますが、imgタグなどに使っても便利だと思います。

記述例2

他にも、先頭ページに空のaタグをid="top"のような属性で宣言しておいて、最終ページから「先頭ページに戻る」みたいなリンクを貼ることもできます。

<a id="top"></a>
冒頭の文章
[page-break]
最終ページの文章
<a href="#top">トップページに戻る</a>

この場合、リンク先の中身は空なので、マウスを乗せてもプレビューは表示されません。

記述例3

アンカーリンクを利用して、ちょっとしたゲームブックを作成することもできます。

その他

VirtualBox(v6.1)に付属のVBoxGuestAdditions-5.2.44にて、Centos8が起動しなくなった件について(解決)

原因はGuestAdditionが作成するvboxsf.koが、/lib/modules/4.18.0-193.28.1.el8_2.x86_64/misc/にコピーされていなかったからのようです。

解決方法

まず、最新カーネルイメージは正常起動せず、emergency modeで起動するため、一つ前の世代のイメージからOSを起動します。

一応、以下に手順。

  • VirtualBoxのUIからOSを通常起動します。
  • Grubカーネルイメージを選択する画面で、F12を押します。準備してないと遅れるので注意。
  • 並んでいる項目の一番上のカーネルイメージが最新ですが、それは起動しないので、上から二番目のやつを選択します。
  • たぶん普通に起動するので、あとはsshで入るなりして、以下の作業をしましょう。
cd /opt/VBoxGuestAdditions-5.2.44/src/
sudo make
sudo make install # ここでvboxsf.koがコピーされていない
sudo cp vboxsf.ko /lib/modules/4.18.0-193.28.1.el8_2.x86_64/misc/

# 念の為、再度、最新のカーネルイメージをインストール
sudo dnf -y reinstall kernel-core.x86_64

これで最新のカーネルイメージが起動するようになりました。

参考:ubuntuをWindowsOS上で動作させる - Guest Additionsインストールのエラーvboxsfがmodprobeできない対処

各種機能を改善しました

縦書き文庫の各種機能を改善しました。

作品一覧にてタグが表示されるように

作品の一覧にて、タグが表示されるようになりました。

f:id:convertical:20201113125300p:plain
タグの表示

これによって、同じ系統の作品にアクセスしやすくなりました。

シリーズに追加できる作品数を20から50に増やしました

大菩薩峠(41作品)のように大きなシリーズもあるので、シリーズあたりの作品数を20から50に拡張しました。

ゲームパッドの操作を記述する言語「combo-script」と、その再生アプリ「combo-player」を作りました

きっかけ

作ったきっかけは、最近買ったウイイレ2020の操作が、ちっとも頭に入らなかったからです。。。

一応ゲーム内にマニュアルがあるんですけど、文字とか矢印で説明されても、ピンと来ないんですよね。。。

そこで思いついたのが「ゲームの操作をぱぱっと記述したら、パッド上の動きをアニメーションを再生しつつ、操作ログも出してくれる」みたいなものがあったら、理解が捗るかなあ〜?ということです。

というわけで作ったのが、combo-scriptと、combo-playerです。

例えばcombo-scriptで昇龍拳を記述して、combo-playerで再生するとこんな感じになります。

f:id:convertical:20200811165349g:plain
昇龍拳

その他、色々なコマンドについては、デモサイトを見てください。

tategakibunko.github.io

上のデモサイトでは、ウイイレの他に、スト5とか鉄拳のコマンドとかも追加しておきました。

メニューの「Games」から選択できます。

コマンド部分は編集可能になっているので、色々と書き換えて遊んでみてください。

f:id:convertical:20200811165922p:plain
コマンド部分(編集可能)

combo-script

combo-scriptは、ゲーム操作を記述するための言語です。こんな風に記述します。

コナミコマンド

up, up, down, down, left, right, left, right, A, B

昇龍拳十字キー操作で記述)

right, down, (right, down), punch

(right, down)は右と左を同時押し(つまり右下)という意味です。

一般にボタンの同時押しは(X, Y, Z...)のように記述します。

昇龍拳(スティック操作で記述)

setL(0), moveL(0, 90), rotateL(90, 45), punch

これは左スティックを0度(真右)に方向け、そこから真下に動かし、更にそこから45度(右斜め下)の位置まで回転させ、最後にパンチボタンを押す、という意味です。

setL, moveL, rotateLの引数は、傾ける先の角度ですが、この角度は時計回りであることに注意してください。時計回りなので、90度は真上ではなく、真下です。

ウイイレ、コントロールシュート

R2 { square }

上の構文はHolding Syntaxと言って、X { Y, Z, ... } などと書くと「Xの操作をしながらY,Z」という意味になります。

なので上のコマンドは

  • R2を押しながら□ボタン
  • 終わったらR2を離す

という意味になります。

combo-script(言語仕様)

詳しくは公式サイトを見てほしいのですが、大雑把に説明すると、

  • ボタンの押下、押しっぱなし、同時押し、各種スティック操作などを抽象化した言語です。
  • 特別なプログラミング知識がいらないので、誰でもコマンド部分を記述できます。
  • 矛盾した操作はコンパイル時にエラーが出ます(押し込んでいる最中のボタンを再び押すとか、左と右を同時に押すとか、色々)。
  • 押下についてはpushDown, pushUpを個別に扱う方法もあります。
  • プラグインで拡張することができます。
  • 定義済みの関数(rotateLとかmoveLとか色々)以外のシンボル名は、ユーザー定義のボタン名、もしくはユーザー定義のプラグイン関数として解釈されます。
  • 例えばpunchと書いたら、ユーザー定義のpunchボタンがあって、それを押して離す、という一連の動作として解釈されます。つまり、punchという名前のボタンをどう解釈するかは、combo-scriptを組み込む実装者に任されます。
  • 関数も同様です。例えばfoo(1,2)と書いた場合、そういう定義済みの関数はないので、ユーザー定義のプラグイン関数とみなされます。そして、実際の動作はcombo-scriptを組み込む実装者に任されます。
  • つまりボタン名も関数名も、それを解釈するのはプレイヤー側の仕事で、combo-script側は名前にルールや制限を設けません。コンパイラ側が判断するのは、それがボタンか、関数か、そしてそれらの動作は、どういう文脈で押されたか、ということだけです(通常押し、同時押し、押しっぱなしなど)。
  • というわけで、例えばパッド右側にある4つのボタンなどは、プレステ風にtriangle/circle/cross/squareと定義してもいいし、Xbox風にY,B,A,Xと定義してもいいです。
  • ただしボタン名を数字から始めることはできません。つまりbutton1はいいけど、1buttonは駄目。
  • ちなみに、combo-scriptは大文字と小文字を区別しません。だからupと書いてもUPと書いても同じです。これは関数も同じ。
  • あとボタン名については英数じゃなくてもいいです。例えば日本語で強パンチとか書いても問題ありません。

コンパイルの仕方とか、それをどうやって自分のプレイヤーアプリに組み込むか、みたいなことは公式サイトを確認してください。

感想

  • ウイイレ2020は難しい。
  • 昇龍拳のコマンドを初めて知った。
  • 鉄拳のコマンドを思い出すことが出来た。