48
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ゆるふわチャット小説をGitHubで構築しましたので╭( ・ㅂ・)و ̑ 〜初めてのフロントエンド編〜

Last updated at Posted at 2017-07-20

アッオー! 皆様、チャットしてますかっ。
そうですね。私は、ChatWorkでAPI投稿される売上レポートを眺めたり、SlackでHubotからミーティングの司会を指名されたり、LINEでりんなにちょっかい出したりする愉快な日々です。
うわっ…私のチャット相手、ボットすぎ…?

ai_mail_woman-compressor.png

ともかく、みんなが慣れ親しんでいるインターフェースは強いわけです。
というわけで、チャットっぽく読める小説サイトをつくってみました。こういうの。

chapter-01-compressor.png

深層の令妹 ζ(*゚w゚)ζ 〜ゆるふわチャット小説〜

あとはもう実際に、会話で紡がれる物語がどういうものか読んでみてほしいのですがっ。

サイト作るにあたって初めてのフロントエンドで色々と泣きそうになったので、諸々メモしておこうと思います。
もしも表示崩れ起こす環境あったら、ごめんネ。。。

GitHub Pages

題名のとおり、サイトの公開はGitHub Pagesで行っています。

https://github.com/piyo7/deep-sister/tree/master/docs

にHTMLやCSSを git push すれば、あら不思議、

https://piyo7.github.io/deep-sister/

が自動更新されます。これはもうホント神機能ですね。

そしてGitは、コードだけでなく小説とも相性いいです。
加筆修正の差分も、どこまで公開したかも一目瞭然です。うっかり設定矛盾を起こしてしまっても、すぐ巻き戻せますしね。

github_diff-compressor.png

なお、GitHub Pagesで一つだけハマったのが、「404 File not found」のキャッシュです。
新規ページをプッシュしたつもりでURL確認して404なことに気づき、その後プッシュしても1時間くらい404のままなことがありました。ところが、海外のバリデーションサイトからはすぐにページ確認できていたので、エッジサーバのキャッシュが効いていたようです。焦らず待ちましょう。

github_404-compressor.png

ちなみにHTMLは、Scalaで書いた自作ツールで生成しています。
独自記法で執筆していて、そのテキストをパースしてテンプレートに流しこんでいるのですが、詳しくは別記事を起こすかもです╭( ・ㅂ・)و ̑

吹き出し表現

LINE風の吹き出しも、チャットによって色々とバリエーションがあります。
いくつか試してみたのですが、小説なので文字の表示領域はできるだけ大きくしたく、アイコンもトゲもない三隅を角丸にするだけのシンプルな形式に落ちつきました。

.voice-left, .voice-right {
  border-radius: 1em;
}

.voice-left {
  border-top-left-radius: 0;
}

.voice-right {
  border-top-right-radius: 0;
}
chapter-06-compressor.png

行あたりの全角文字数は、各チャットアプリをiPhone 6Sで確認したところ、ChatWork 19文字、Slack 19文字、LINE 13文字、という感じで悩んだのですが、18文字にしました。

なお、電話などの生音声じゃないセリフは、枠付きにしています。

.telephone {
  border: 2px solid #808080;
  border-radius: 0;
}
chapter-02-compressor.png

さて、セリフの背景色がそれぞれ異なりますが、これは発言したキャラクターのイメージカラーです。
色相環と睨めっこしながら、輝度を統一して設定しました。

.char05 { background-color: hsl(330, 100%, 85%); }
.char06 { background-color: hsl(210,  50%, 85%); }
.char07 { background-color: hsl(  0, 100%, 85%); }
.char08 { background-color: hsl(255,  75%, 85%); }
.char09 { background-color: hsl( 90, 100%, 85%); }

ちなみに、この小説『深層の令妹 ζ(*゚w゚)ζ』は、カクヨム小説家になろうにも投稿しているのですが、そちらにはない情報がこの色彩なのですね。

ほぼセリフだけの小説なので、なるべく早めにキャラクターを特定できるよう工夫はしているのですが、厄介なことに主人公の妹がころころ口調を変える設定なため、「新しい口調のキャラが登場するたび、まず妹の可能性を疑わないといけない」との感想がありました。ナンテコッタイ。

interlude-01-compressor.png

背景色があると、色んな口調のセリフが入り混じっていても、妹の一人会議シーンなのだということが一目で分かりますね!

フォント

フォントの設定にはだいぶ悩まされました。
font-family で検索したところ、201x年はこの設定!みたいな記事がいくつも出てきてオッと思ったのですが、ユーザ環境に何のフォントがインストールされているか分からないという状況が、かくも混沌を生むものとは……。

font-family: sans-serif;

として、環境ごとのデフォルトフォントに委ねるのが正義のような気もしましたが、それが小説として読みやすいフォントかというとそうでもなく。いきおいGoogle Fontsの「M+ 1p」を導入することにしました。

まだ早期アクセスということですが、今回の用途では充分に実用的です。
ただし font-feature-settings: "palt" は効かないみたいなので、カーニングしたい人は気をつけてください。

font-family: arial, "Mplus 1p", sans-serif;

これに加えて、Font AwesomeのCSSを読んだものが、採用したフォント設定です。
Arialを先頭にしているのは、もちろん英数フォントをArialにしたかったこともあるのですが、これを指定しておかないと和文であってもルビが浮いてしまうということがありました。

chapter-03-b-compressor.png

上図がArial指定なしで、下図がArial指定ありです。
どうしてこうなるかは分かりませんでした。。。

chapter-03-a-compressor.png

なおユーザ環境に依存しないウェブフォントの弱点は、ダウンロードが終わるまで適切にテキストが表示できないことです。
「M+ 1p」は、フォントの太さごとにWOFFファイルが分かれているため、 font-weight: 400のものだけ使うようにして、ダウンロードサイズを抑えています。
Chromeのデペロッパーツールなどで確認しておくと安心ですね。

chrome_developer_tool-compressor.png

とはいえ、回線状況によってはダウンロードに数秒かかることもあり、その間はブラウザによってテキストが空白にされたり別のフォントに置き換えられたりします。
この挙動は制御可能なのですが、Font Loading APIは未対応ブラウザがあり、JavaScriptライブラリを使うのはオーバーヘッドを増やすことになるので、見送りました。このあたりの事情は「ウェブフォントの最適化 | Google Developers」が詳しいです。

<追記>WindowsのChromeで「M+ 1p」がガタガタに表示されることがあったので、結局メイリオを追加しましたorz

font-family: arial, メイリオ, "Mplus 1p", sans-serif;

hoverアニメーション

フォント以上に悩んだのが、hoverの制御です。
たとえば目次ページでは、『灼け焦がれた涙』という章題にhoverが効くと、登場キャラクターを表すバッジが下線になるアニメーションを仕掛けています。

index-compressor.png

CSSの擬似クラス :hover は、名のとおりPCではマウスをかざした時に発火するのですが、スマホだとタップの指を話した時に発火したりします。これが直感と反しているのですね。
私の意図としては、ページ遷移の予兆として発火してほしくて、ページ遷移が確定したら解除されないでほしいのですが、違和感なく実現するのに試行錯誤しました。

最終的には、hoverを効かせたい要素に hoverable というクラスを付与しておいて、それを対象にjQueryを仕掛けました。スマホの場合、タッチされると発火して、他の要素で発火するかスクロールすると解除されるようにしています。

<div class="chapter hoverable">
  <div class="badges">
    <div class="badge char06"></div>
    <div class="badge char01"></div>
    <div class="badge char05"></div>
    <div class="badge char02"></div>
    <div class="badge char07"></div>
  </div>
  <p><a href="chapter-02">灼け焦がれた涙</a></p>
</div>
$('.hoverable').on('mouseenter', function () {
  $(this).addClass('hover');
}).on('mouseleave', function () {
  $(this).removeClass('hover');
}).on('touchstart', function () {
  $(this).addClass('hover');
  $('.hoverable').not(this).removeClass('hover');
});
$(window).on('scroll', function () {
  $('.hoverable').removeClass('hover');
});

シェアボタン

ソーシャルからは逃れられない時代なので、シェアボタンをフッターに設置しました。
公式のものを使いたかったのですが、それぞれサイズが異なっていて綺麗に並べられなかったので、下記サイトを参考にCSS組みました。

おしゃれなシェアボタンをCSS&Webフォントで作ってみた【はてなブログのPC&スマホ用】

sns_share-compressor.png

せっかく設置したので、どなたか動作確認してもらえると><

HTML全般

ついでにメディアクエリも、横幅の閾値どうするのが適切かよく分かりませんでしたが、端末によらず1カラムでチャット表示できればいいので、viewport固定して事なきをえました。たぶん……!

<meta name="viewport" content="width=480">

画像の圧縮

1200x630のシェア画像を、Compressor.ioに食わせたところ、259KBを55KBに圧縮するすごいやつでした。
非可逆圧縮ですが、私には違いが分からなかったです。

バリデーション

バリデーションには下記サイトを利用しました。おおむね大丈夫そう。

感想

それよりは、せっかく会話小説なので、いずれLINE風だったりTwitter風の見せ方をしてみたいです。

Visual Studio Codeの拡張機能を自作して、理想の執筆環境を手に入れた 〆(゚_゚*)

という前回の心残りが実現できて良かったです。
やはり見せ方は重要ですね。この小説本来の表現形式をようやく手に入れられたような気がしています。

あとは、チャットの背景にパーティクルシステムを仕込めればなぁと夢見ています。
シーンによって、雨を降らしたり、桜吹雪を舞わせたり、してみたいです。地の文ない代わりに情景描写ができれば、と。
ParticleJSで実験しているのですが、ここのところ肝心の執筆を滞らせてしまっているため、開発は一段落つけようと思っています。

そろそろ物語も中盤戦。妹がXXX化する頃ですしね╭( ・ㅂ・)و ̑

48
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?