2017年8月11日金曜日

JavaScript でGUI音遊びソフト作り(2) - 図形の描画と画面構成

前回けっこういいところまでいってたんですけど、いろいろあってイチから制作しなおしました。今はこんな感じになってます。



描画に p5.js 、体裁に Bootstrap(& jQuery)、音には Tone.js を使っています。: https://takasa5-orbit.herokuapp.com/
https://takasa5.github.io/orbit/ (2019年5月に移動しました)


1. p5.js と jCanvas の違い

図形の描画形式に限界を感じたため、 jCanvas (with jQuery) から p5.js へと乗り換えました。両者はどう違うのかメモしたいと思います。

1-1. jCanvasで円

jCanvas で円を描くときは以下のようにします。

$("canvas").drawEllipse({
  strokeStyle: "white", #線の色
  strokeWidth: 1, #線の太さ
 #fillStyleで中を埋めることができる
  x: mouseX, y: mouseY, #中心座標
  width: 100, height: 100, #幅と高さ(直径) 
  draggable: true, #ドラッグ可能か
  groups: ["グループ名"],
  dragGroups: ["ドラッググループ名"],
  name: ["名前"],
  click: function(){},
)
draggable 以下がとても優秀で、図形ごとにドラッグ可能判定をつけたり、グルーピングしたり、クリックやドラッグのイベントをバインドするのも簡単です。 jCanvas ではレイヤーを単位として扱うことができるため、まさにキャンバスにお絵かきするような感覚で書くことができました。

1-2. p5.js で円

p5.js で円を描くときは以下のようにします。
stroke("white"); #線の色
noFill(); #中身を埋めない 埋めるときはfill(色)
ellipse(x, y, r); #中心座標と半径を指定
えらい短いですね。 p5.js ではこうした短い記述でかける代わりに、図形ごとに個別にイベントバインディングをすることができません(多分)。ドラッグさせたいのであれば、いちいち当たり判定を出してやらなければいけないことになります。

1-3. なぜ p5.js を選んだか

その決定的なところはモーション描画です。ようは単品なら jCanvas の方が便利ですが、モーションを描こうとすると p5.js の方が優秀です。
jCanvas では、動画を描くための機能というものはないので、 javascript の setInterval() などを用いて数秒ごとの描画を繰り返すことになります。しかしちょっと調べてわかったのですが、javascript のタイミング調整のメソッドというのはあんまり精度がよくないようで、カクつかせずに動かすのはとても大変でした。
一方、 p5.js では Arduino みたいに最初に一回だけ実行される setup() と無限ループである draw() の二つを用いて進めていくので、一フレームごとの描画として直観的に書くことができ、よっぽど重い処理をしない限りカクつきません。
ただし、1-1, 1-2 で述べたように個別での管理をしていないため何か一つでも動くたびに全オブジェクトを描き直す必要があります。これは慣れればそう大変ではありませんでした。

2. Bootstrap Grid System で体裁を整える

これに結構な時間を費やしました。BootStrap Grid System は、画面サイズによってレイアウトを簡単に切り替えられるすごいやつなのですが、慣れるのに時間がかかってしまい……。
最初の画像で、PCで開いたときとスマホで開いたときの2枚を貼りました。同じレイアウトなら、スマホではボタンがもっと小さく表示されるはずですが、横幅いっぱいに大きく表示したかったためそこを努力しています。
調べれば解説をしてくれてるサイトがいっぱい出ますが、簡単に説明すると、Bootstrap Grid System は画面を縦に12分割したところに、一行ごとに12個パーツを並べていく感じです。
パーツ1個で複数スロットの占有もできるため、比率を変えた配置もできます(2つのボタンを2:1で配置するために12を8:4で埋めるなど)。
なかなかうまくいきませんでしたが、上で言ったようなことを実現するためには以下のステップでやるのがよさそうでした。
①画面幅100%のrowを用意する
②①内に、centerタグで囲ったうえでパーツを配置、12個のカラムを埋めるようにする
③①②をさらにrowで囲い、col-xs-autoクラスで囲う(①②を自動的に中央に配置する)。
正直書いててなんでうまくいったのかわかりませんが……難しい。

3. その他、スマホとPCで要素の大きさを変える

スマホ判定には以下。
if (navigator.userAgent.indexOf('iPhone') > 0 || navigator.userAgent.indexOf('Android') > 0){};
iPhone と Android ってなんかムズムズする場合分けなんですけどまあいいです。このif文の中でグローバル変数や初期設定を変えればいいと思います。
iOS での動作確認はまだしていませんが Android では無事動きました。


みたいな作業をしました。UI 調整と音の調整が待ってます……しんどいけれど楽しいとこですね。

0 件のコメント:

コメントを投稿