4. f3.jsレイアウトマネージャ

この記事を読み終えると、センサやアクチュエータの配置を簡単にできるようになります。

レイアウトマネージャ

f3.jsには、GUIのレイアウトマネージャに相当する機能が備わっています。センサやアクチュエータを等間隔に配置したり、一直線上や、円周上に沿わせたり、といったことが容易にできるようになっています。例えば、円周上にブザーモジュールを並べていくコードはレイアウトマネージャを使わないと次のようになります。

for (var i = 0; i < numBuzzers; i ++) {
    var buzzer = new upmBuzzer.Buzzer(inputs[i]);
    f3js.add(buzzer, {
      x: 65 + Math.cos(Math.PI * 2 * i / numBuzzers) * 80,
      y: 65 + Math.sin(Math.PI * 2 * i / numBuzzers) * 80,
      rotation: Math.PI * 2 * i / numBuzzers - 90
    });
}

角度計算が非常に面倒な上、コードを読んだ人が一見して何をしようとしているか理解しづらくなってしまいます。

これは、レイアウトマネージャを使うと次のように書けます。

var circle = f3js.drawCircle(65, 65, 80);
circle.layout = "distribute";

for (var i = 0; i < numBuzzers; i ++) {
    var buzzer = new upmBuzzer.Buzzer(inputs[i]);
    f3js.add(buzzer, circle);
}

ここで書いた円弧はプリントプレビューにも表示され、ブザーを円周上に設置しようとしていることが一目瞭然となります。

GUIレイアウトマネージャとの比較

よくあるGUIのレイアウトマネージャは次のように使います。レイアウトマネージャは、パネルやウィンドウといった矩形領域の中に、特定のルールに従ってコンポーネントを配置しやすくしてくれます。

var borderLayout = new BorderLayout();
panel.setLayout(borderLayout);
panel.add(button, BorderLayout.CENTER);

一方、物理的なインタフェースは、GUIとは異なった特徴を持っており、必ずしもGUIと同様のレイアウトマネージャではうまく設計を支援できません。

GUIはディスプレイの矩形領域を効率的に使い切ることを念頭に置いて設計されていますが、物理的なインタフェースは効率的にスペースを使い切ることは必ずしも要求されません。例えば、手で持ったとき指が届く範囲にボタン類を集中させる、両手で持てるように小さくしすぎない、などのケースが考えられます。

ただし、ボタンなどの配置がユーザにとって予測可能であることは重要で、例えば一直線上にボタンを並べておくといった配慮は必要でしょう。実際に物理的なインタフェースの実例を収集して分析したところ、ボタンやスライダーなどは、線や円といった特定のパス上に適切な間隔を開けて配置されることが多いことが分かりました。

そこで、f3.jsのレイアウトマネージャは矩形に割り当てるのではなく、線や円といったパスに割り当てるように設計されています。

var line = f3js.drawLine(10, 10, 100, 100);
line.layout = "distribute"; // 線上に等間隔に配置
f3js.add(button, line);
f3js.add(slider, line);
f3js.add(button2, line);
f3js.add(button3, line);

以降は使えるレイアウトマネージャを紹介します。

Distribute

円弧または線上にモジュールを等間隔で配置します。

// 線上に等間隔に配置
var line = f3js.drawLine(10, 10, 100, 100);
line.layout = "distribute";

// 線上に等間隔に配置 (上の行と同じ)
line.layout = { name: "distribute" };

// モジュールの大きさを計算しないで配置
// (モジュールの中心間の距離が等間隔になります。)
line.layout = { name: "distribute", size: false };

// モジュールを回転しないで配置 (線が斜めでもモジュールは元の向きのままになります)
line.layout = { name: "distribute", rotate: false };

// 円周上に等間隔に配置
var circle = f3js.drawCircle(55, 55, 30);
circle.layout = "distribute";

Align

円弧または線上にモジュールを指定した間隔を空けて配置します。

// 線上に3cm空けて配置
var line = f3js.drawLine(10, 10, 100, 100);
line.layout = { name: "align", padding: 30 };