アイマス会話メーカーで使っている技術・テクニックまとめ

※アイマス会話メーカーの説明→おはなし・デレぽ作成ツール『アイマス会話メーカー』の紹介と使い方

※GitHub→https://github.com/YSRKEN/ohanashi

※Ver.1.XのURL→https://ohanashigen.firebaseapp.com

※Ver.2.X(開発中)のURL→https://imas-talk-maker.firebaseapp.com


ライブラリ・フレームワーク編


Angular

 Google製フルスタックWebフロントエンドフレームワーク(プロジェクトではAngular 6を採用)。

 コンポーネントがclassになっていて、ReactiveExtentionで繋ぎ合わせるデザイン設計といった印象。

 コンポーネント作成・CSS設定・ルーティング・DI・通信など様々なライブラリがひとまとめになっているため、Angular-CLIさえ入れれば細かいことを考えなくてもいいのが良さ。

 ただ、コンポーネントを作成して@Input@Outputを割り振って組み込む……といった処理が(Reactと比べて)面倒臭く、結局「おはなし」「デレぽ」のレンダリング部分が雑になってしまっていた。つまり、「外部からのフラグを@Inputから入力すると、CSSによってHTMLのタグブロックが表示/非表示になる」などといった力技である。

 また、秒でコンポーネントを作成できるReactと比べると、コマンドを打ってガッチリしたコンポーネント(の雛形)を作成するAngularの書き味は重いといった難点もある。このことから、Ver.2.X以降はReactで書く予定。


React

 Facebook製Webフロントエンドライブラリ。

 仮想DOM・コンポーネント志向・JSX記法を引っさげて登場し、瞬く間に大人気になったとされている。

 オブジェクト指向のお手本のようなAngularと比べて、関数型プログラミングで書くために生まれたかのような設計思想。

 それでいて、基本的にMVCで言うところのView用のライブラリなので、MとVをどうするかがしばしば問題になる。

 表示しかできないStateless Functional ComponentにHOCで状態を付与するのが基本テクニックだった。しかし、近頃はReact Hooksにより、「状態」や「初期化/更新/破棄時の動作」や「DI」といった操作をより簡単に行えるようになった。

 また、状態管理のテクニックとしてFlux(Redux)がよく知られているが、「規模が小さい」「理念は分かるがコーディング作法がよくわからない」といった理由により、Ver.2.Xでは採用していない。


Bootstrap

 Twitter製CSSフレームワーク(プロジェクトではBootstrap 4を採用)。

 手軽に整ったレイアウトを作成できる他、グリッドシステムにより凝ったレイアウトも作りやすいのが特徴。

 ただしJavaScriptで動きを制御する(省くと一部機能が使えなくなる)ことと、ライブラリ時代のサイズがそこそこ大きいことから、「あえてBootstrapじゃないCSSフレームワークにしようぜ!」といった動きもある。

 当プロジェクトでも採用しているが、Ver.2.XではCSSのみ採用し、JSが必要な部分は自前で書くことによって対処予定。


html2canvas

 HTML/CSSで描かれたDOMをcanvasとして描画し直してくれるライブラリ。

 これにより、構築したおはなし・デレぽのプレビューがcanvas化されるため、そのまま画像として保存可能になる。

 ただ、ライブラリがHTML/CSSを完璧に解釈してくれるわけではないため、レイアウト崩れが起きてしまうこともあるのが難点。


TypeScript

 トランスコンパイルしなくてもブラウザで動くようになってくんねーかな。

 型安全にできるので当プロジェクトでも当然採用。


ng-lazyload-image

 画像を遅延評価できる、Angular用のライブラリ。Ver.1.Xでは、キャラ選択機能と表情選択機能が分離されていないということもあり、通信量を節約するために採用していた。ただ、スクロールなどのイベントを拾わないと読み込みが始まらなかったりするクセがあるため、読み込み量を工夫して削減したVer.2.Xでは遅延読み込みを不採用予定。


小技編


おはなし/デレぽのレンダリング方法

 当初はCSSだけで全部レンダリングしていましたが、

後におはなしジェネレーターから背景素材を拝借して利用する形にしました。そうしないとhtml2canvasでのレンダリング結果の再現度が低くなるもの……orz

 また、「おはなし」および「デレぽ」部分は、大枠を「position:relative;」と指定し、その中の要素を「position:absolute;」とすることで組んでいます。つまり、大枠以外の要素は「大枠の左上座標」を基準にした相対座標で配置するわけですね。

 CSSのposition: absoluteとrelativeとは | UX MILK

 Ver.1.Xでは「おはなし」と「デレぽ」をpx指定で描いていました。しかし、レスポンシブ対応を考えると好ましいものではありません。そこでVer.2.Xでは、大枠以外を大枠に対する%指定で表現し、大枠に対してwidth/heightを独自に設定することで対処しました。ただ、


  • どうやって縦横比を保った状態でリサイズするのか

  • フォントサイズはどのように調整するのか

が課題でした。前者はCSSハックできそうでしたが可読性が悪化しそうであり、後者はfontサイズがwidthやheightとはまったく別の基準で決められているCSSのクソ仕様によりJavaScriptでの対策が急務でした。

 [CSS]フォントサイズの指定方法の基礎知識からレスポンシブに適した指定方法までやさしく解説

 そこで考えたのが、


  • 「おはなし」や「デレぽ」のコンポーネントの読み込み時に、HTMLElement.offsetWidthを読み取る(Xと置く)

  • コンポーネントの横幅および縦幅をX基準で決める。例えば「width=Xpx;height=calc(X*2/3)px;」など

  • フォントサイズもX基準にする。例えば「const Y = X / 10; font-size: Ypx;」など

といった戦法でした。別作品「シャニマス会話メーカー」ではこれをAngularで実装し、アイマス会話メーカーVer.2.XではReactで実装しています

 ちなみに、おはなしは「ファボるボタンとメッセージ欄の高さによって時刻欄の位置が変わる」といった仕様があることが発覚したので、これからそれを実装するところですorz


ツイートボタンの作成方法

 Angularのコンポーネントにツイートボタンを載せる - Qiitaを参考にしました。Reactの場合はどうするかって? 検討中です☆


水平切り替えボタン

 Ver.2.Xより実装。Bootstrapのボタングループ機能を参考に、「選択されている」ボタンのCSSのみ書き換えるような都合のいいコンポーネントをReactで作成することで対処しました。


横幅によって「アイマス会話メーカー」の文字の大きさを変える方法

 もちろんメディアクエリ……と言いたいところですが、Bootstrapの場合、「横幅によって対象の表示可否を切り替える」ためのCSSがありますのでそれを利用ししました。