daisuke_nomura の日記

Android プログラマーな鉄道ファンのブログ

コミケ:『Windows Phoneでniconico風のコメントを表示する』

この記事は、2013年冬のコミックマーケットで、@toriimiyukkiApplestで頒布した冊子のデジタル版です。
誤字脱字の修正や、レイアウトの変更などを行っています。

1.はじめに

 @toriimiyukkiに、2013年夏のコミケに続いて、冬も原稿を頼まれました。

f:id:daisuke_nomula:20140420181004p:plain

 今回は、『Windows Phoneでniconico風のコメントを表示する』とのタイトルで、Windows Phoneでniconico風のコメントを表示する方法や工夫について解説します。ロジックはC#、UIはXAMLとなります。コードは切り貼りになりますが、サンプルをGithubにUPしているので、参考にしてください。URLは https://github.com/daisuke-nomura/comiket2013winter です。

2. niconicoのコメント

 niconicoのコメント*1は、画面の右端から左端に流れます。どのコメントも画面上に表示される時間は4秒間で、コメントの右端が画面の左端に行くとコメントは見えなくなります。各コメントは画面を流れる際にX座標*2のみ移動し、Y座標*3には移動しません。

f:id:daisuke_nomula:20140417205746j:plain

 今回は、この流れるコメントを、Windows Phoneで再現します。
 以下の順序で話を進めます。

  1. Windows Phoneでコメントを表示
  2. コメントに影をつける
  3. コメントをアニメーションさせる

 記事が長くなるため、動画の再生状況に合わせてコメントを表示する方法は載っていません。

3. Windows Phoneでコメントを表示する

 まず、Windows Phoneでコメント(テキストコントロール)を表示させてみましょう。

3.1 TextBlockオブジェクトを生成する

 Windows Phoneのテキストコントロールは、TextBlockです。TextBlockは一行のテキストを表示します。
 C#でTextBlockオブジェクトを生成するコードは以下となります。

niconico wp8 comment1

 このコードはTextBlockオブジェクトのインスタンスを生成後、当該インスタンスのプロパティに以下を設定します。

  1. テキストは「どーまんせーまん」
  2. フォントサイズが40
  3. フォントの色は黒
  4. フォントは太字
  5. 透明度は1.0
  6. テキストの周辺のサイズは全て0

 透明度が1.0ですので、透明な箇所は全くありません。

3.2 画面にオブジェクトを配置・表示する

 次に、先ほど生成したTextBlockオブジェクトを画面に表示します。
 TextBlockオブジェクトを配置したい画面のXAMLに、以下のコードを挿入します。*4

 XAMLで以下のコードを配置したい要素の中に記述します。
<Canvas x:Name="panel"/>

 そして、コードビハインドで、先ほどのコードの下部に以下のコードを続けます。Page.xamlなら、Page.xaml.csです。このコードは、XAMLのpanelという名前のCanvas内にTextBlockを配置します。
panel.Children.Add(textBlock);

 このコードを動かすと、以下のように表示されます。

f:id:daisuke_nomula:20140419191801p:plain

 ここまでで、一番の基本のテキストを表示することができました。

niconico wp8 comment1

 余談ですが、このコードでプロパティに設定している値を変えると、フォントサイズやテキスト、色などが変化します。
 Visual StudioではIntelliSenseが働きますので、IntelliSenseでサジェストされるコードに気軽に変えて試してみてください。

3.3 コメントに影をつける

 よく見ないと気付きにくいですが、niconicoのコメントは縁取りされています。

f:id:daisuke_nomula:20140419192121j:plain

 この縁取りをWindows Phoneでも再現したくても、TextBlockコントロールに縁取りのプロパティはありません。そのため、縁取りの代わりに影をつけます。
 縁取りの代わりに影をつける手法は、iOSniconicoアプリでも見られます。

f:id:daisuke_nomula:20140419192301p:plain

 3.2で画面に表示したTextBlockオブジェクトのMarginプロパティを変更します。右下に1ピクセルずれた箇所に、黒いコメントを表示します。
 そして、黒いコメントの上に白いコメントを重ねます。すると、黒いコメントは白いコメントの影に見えます。
 影を追加するためTextBlockの生成は2回行い、Canvasオブジェクトの中に設置します。黒いコメントのTextBlockオブジェクトのMarginプロパティに、右に1ピクセル、下に1ピクセルずれた値を設定します。

niconico wp8 comment2

 早速画面で表示しましょう。

f:id:daisuke_nomula:20140419192642p:plain

 影がついたでしょうか。
 もしも、黒いテキストの下に白いテキストが表示されていたら、白のTextBlockと黒のTextBlockの表示順序が逆になっているので、grid.Children.Addの行を逆にしたり、TextBlockオブジェクト生成時の値を変えてみてください。

3.4 コメントの距離・速度・時間

 niconicoのコメントの表示時間は、4秒(=4,000ミリ秒)間です。
 コメントが4秒間の内に移動する距離は、距離 = コメントの横幅 + 画面の横幅となります。距離が分かったので、速度 = 移動距離 / 400で計算すると、10ミリ秒毎*5の速度が分かります。
 タイマーで10ミリ秒単位で監視して、TextBlockオブジェクトのX座標を変更してアニメーションさせる場合は10ミリ秒毎の速度を意識する必要がありますが、今回のアニメーションでは不要です。そのため、TextBlockオブジェクトの横幅と、画面の横幅が分かってて移動距離さえ出せれば、後はWindows Phone内蔵のアニメーション機能が自動的に速度を計算してくれます。時間も4秒固定なので、意識する必要はありません。

f:id:daisuke_nomula:20140419233205p:plain

3.5 TextBlockのアニメーション

 TextBlockオブジェクトを、右端から画面左端までアニメーションさせます。動作イメージを先に示します。

f:id:daisuke_nomula:20140420134841p:plain

f:id:daisuke_nomula:20140420134852p:plain

f:id:daisuke_nomula:20140420134859p:plain

 Windows Phoneでコントロールをアニメーションさせるには、DoubleAnimationクラスとStoryboardクラスの2つを使用します。

niconico wp8 comment3

 都合上、画面の横幅をコードに直に記述しています。このコードは、TextBlockオブジェクトのインスタンスを生成して画面に配置します。その後、画面の右端768pxから、TextBlockオブジェクトの右端が画面左端に到達する0 - TextBlockオブジェクトの横幅まで、4,000ミリ秒間行うDoubleAnimationクラスのインスタンスを生成します。
 そして、X座標を移動させるアニメーションとして、TextBlockオブジェクトに適用し、実行しています。
 これだけで、画面右端からTextBlockオブジェクトの右端が画面左端に辿り着くまで4秒間アニメーションします。アニメーション完了後に発火するCompletedイベントでは、不要になったTextBlockオブジェクトを消しています。
 上のコードをコンストラクタ辺りに追記してください。画面が表示されたタイミングで画面右端から左端に対して、TextBlockオブジェクトがアニメーションします。

4. まとめ

 今回は、Windows Phoneでniconico風のコメントを表示する方法を紹介しました。前述したように、今回紹介したコードだけでは、動画の再生状態に合わせたコメント表示はできません。  動画の再生状態に合わせて表示させるとなると、以下のような機能が必要となります。

  1. 動画のコメントのリストを作る
  2. タイマーイベントで10ミリ秒ごと*6にコメントを表示するかチェックする
  3. コメントを表示するならコメントを配置・アニメーションさせる

 これらは比較的簡単にできると思いますので、是非試してみてください。

*1:中コメント

*2:横方向

*3:縦方向

*4:画面の隅っこに置いても見えないので、配置場所を考えること

*5:10ミリ秒単位なのは、niconicoのコメントは10ミリ秒単位でタイミングが設定されているため

*6:niconicoのコメントのvpos値由来