Folio
Folio プレートは、自然史博物館が標本を解説するのと同じように、アイデアを説明します。マウント上に1つの物体があり、その隣に番号付きのキー、そしてそれを見る方法を伝える壁テキストがあります。ここでの物体は、あなたが考案する機器(実験台、天秤、織機、蒸留器など)であり、その可動部分がアイデアを実行します。読者はそれを操作でき、その上のすべての読み取り値は計算されます。
3つの約束
- メカニズムであって、比喩ではない。 機器はアイデアを「実行」しなければならず、単に説明として横に立っているだけではいけません。描画する前に、次の一文を書いてください:「読者がXをすると、部品Yが動き、その動きはアイデアにおけるZである。」
- 数値の単一ソース。 小さな純粋なモデルが、針の角度、液面レベル、読み出し値、キー、テーブルなどすべてを計算します。ページはモデルが返すものだけを表示するため、2つの場所で矛盾が生じることはありません。
- ガイド付きの読解。 優れた描画にもガイドは必要です。各プレートには、キー、用語ごとの解説、完全な動作、そして簡略化された点についての正直な説明が付属しています。
はじめに
- 3つの参考プレートがリポジトリに付属しています。プレートI(
examples/attention/、アテンションを分析台として見立てたもの)は、離散的なステップと数式からなるアイデアのモデルです。プレートII(examples/heart/、人間の心臓を二重ポンプとして見立てたもの)は、時間経過とともに動作するもの(毎フレーム統合されるシミュレーション、連続フロー、フェーズ、各サイクル後に再描画されるチャート)のモデルです。プレートIII(examples/grid/、ミニチュアの電力網)は、電気、磁気、エネルギーフローのモデルであり、ベルトではなく独立した機械(タービン、回転子が回転する発電機、変圧器、鉄塔、町)から構築される実験台のモデルです。プレートIV(examples/hashmap/、ハッシュマップを仕分けオフィスとして見立てたもの)は、アルゴリズムとデータ構造のモデルであり、アイデアが一連の離散的操作(挿入、検索、リサイズ)であり、各操作がタイミングの取れた一連の動作(持ち上げる、運ぶ、比較のために浸す、すべてのカードを新しい場所へ飛ばす)に展開され、順番に再生されるため、読者はアルゴリズムの各ステップを観察できます。最初に最も近いプレートを開いてください。 - 最も速い開始方法は、参考プレートをコピーすることです:
node scripts/new-plate.mjs <name>を実行すると、プレートIからexamples/<name>/が作成されます。その後、モデル、シーン、テキストを置き換えてください。動作しているプレートから構築する方が、空白から始めるよりも迅速かつ安全です。 - 共有の展示スタイルは
kit/folio-page.cssにあります。プレートのpage.htmlでは、/*CSS*/を<style>タグ内に配置し、独自のルールのみを追加します。 node scripts/build-site.mjsは、すべてのプレートとカバーページ(site/index.html)をdocs/にビルドし、GitHub Pages 対応のウェブサイトを作成します。プレートを追加するには、その名前をPLATESに追加し、カバーにカードを追加します。- 任意のプレートを単一のスタンドアロンファイルにビルドするには、
node scripts/build.mjs examples/<name> dist/<name>.htmlを実行します。 - このファイルのみがインストールされている場合(リポジトリなし)、付録に描画ライブラリがあります。
folio-kit.jsとして保存してください。
プレートは5つのファイルで構成されます:
| ファイル | 役割 |
|---|---|
folio-kit.js | 描画ライブラリ(共有、プレートごとに編集しない) |
folio-live.js | 3つのビュー:ステージ、ライトレイヤー、オービット、ビュー切り替え(共有) |
model.js | 純粋なモデル。1つのオブジェクトを window に配置する |
plate.js | 機器:静的ジオメトリ、ライブスロット、入力 |
page.js | キー、コントロール、壁テキスト、台帳。プレートをリッスンする |
page.html | マウントとスタイル。/*KIT*/ /*MODEL*/ /*PLATE*/ /*PAGE*/ のプレースホルダーを含む |
フェーズA:概要(まだ描画しない)
A1. スコープ。 開始する前に、ユーザーに次のうちどれを提供するか、およびおおよその所要時間を伝えてください:
| スコープ | 内容 | 標準的な時間 |
|---|---|---|
| スケッチ | 機器 + キー + 読み出し値、壁テキストなし | 1時間未満 |
| プレート | 完全な展示ページ(「Xを説明する」のデフォルト) | 1.5〜3時間 |
| シリーズ | 1つの共有実験台上の複数のプレート、スケールとパレット | まずリストを合意し、その後1プレートずつ |
A2. モデル。 視覚的なものの前に model.js を書いてください。実際の数式、単位、および大きさを収集します。プレーンなオブジェクトを返します:入力を与え、ページが表示するすべての数量を出力します。Node で実行し、いくつかのケースを出力します。エッジケース(空のセット、マスクされた行、限界値)を今すぐ探します。おもりの重りやサンプルデータなど、何かが考案された場合は、壁テキスト「この標本について」にその旨を記載します。
A2b. 時間とともに実行されるモデル。 アイデアがプロセス(心拍、キューの排出、学習曲線)である場合、状態と step(s, dt) 関数、および表示されるすべてを返す read(s) として記述します。描画する前に、Plate II が安静時の成人(約115/80 mmHg、70 mL/拍、5 L/min)に対して行っているように、Node で既知の値に対してパラメータを調整します。シミュレーションは描画がオフスクリーンの間も実行し続け、描画のみをスキップします。そうしないと、ページの下の方でコントロールを変更すると数字がフリーズします。
A3. 機器とその対応表。 実験室、作業場、天文台、または印刷所の世界から機器を探します。次に、各用語を部品に結び付けるテーブルを作成します:
| アイデアの用語 | 機器の部品 | 読者が見ることができるもの |
|---|---|---|
| クエリ | 頭上レール上のキャリッジ | 質問している単語の上に停車する |
| スケーリングされたスコア | 単語ごとのダイヤル | 針の位置 |
| ソフトマックス | 1つの密閉されたリザーバー | カラムはそれが保持するものだけを分割できる |
| マスク | キャップ付きストップコック | 後の単語は遮断される |
| 重み付き和 | 層状堆積物のトレイ | 各層の長さが重みである |
すべての行に部品が必要であり、すべての主要な部品に行が必要です。信頼性の高いマッピングの例:固定された総和はリザーバー、財布、または重りの袋になります。比較はダイヤル、天秤、またはキャリパーになります。選択はバルブ、スイッチ、またはポイントレバーになります。累積は層、スタック、または集計になります。順序付けはレール、ラック、またはシュートになります。
フェーズB:実験台
B1. 目録。 配置する前に部品をリストアップします。30〜60を目指します。目的ごとにグループ化します:用語部品(テーブルから、アイテムごとに繰り返される)、支持部品(台座、脚、支柱、レール、カラー、ブラケット)、制御部品(セレクター、ローレットノブ、レバー)、およびマウント詳細(カタログプレート、刻印ラベル、スケールストリップ、ネジ)。アイデアが扱う数量のうち、正確に1つだけを赤色にします。
B2. バンド。 ワールド座標を使用し、x を実験台に沿って、y を視聴者に向かって、z を上向きにします。実験台を奥から手前までの奥行きバンドに分割し、各バンドに1種類の部品を割り当てます。プレートIでは、レール、カラム、ストップコック、マニホールド、ダイヤル、トレイと配置されます。バンド間にワールド単位でクリアランスを残します。ある部品が次のバンドに突き出ると、間違った順序で描画されるためです。バンド内では、遠くから近くへ描画します。カメラを設定し(長い実験台の場合は az を -24 近く、el を 30)、Folio.fit で角に合わせます。
B3. 静的文字列、ライブスロット。 バンドを一度走査し、SVG文字列を順序付きリストにプッシュします。何かが動く場所には、代わりに名前付きスロットをプッシュします。マウント時に、リストはスロットごとに空の <g> を持つ1つのSVGになります。各アニメーションフレームは、モデルのターゲットを追跡するイージングされた値から、スロットのみを再描画します。すべての値が到着すると描画は停止します。
B4. ピン。 アイデアを伝える部品の上に、6〜10個の番号付きピンを、初心者が見るべき順序で配置します。ピンは描画の上に配置される唯一のマークです。他のすべてのテキストは表面に刻印されます:パッド前面の名前、スケール上の数字、台座のカタログプレート。
フェーズC:マウント
ページは説明の一部です。次のブロックを上から下に構築します:
- マストヘッド。 左側にシリーズ名、中央にワードマーク、右側にプレート番号。
- タイトルブロック。 アイデアを機器として命名する見出し(「アテンション、分析台として。」)、何が起こるかを説明する3つの文、および小さなカタログリスト(オブジェクト、アイデア、モデル、カタログ)。
- マウントされたプレート。 ヘアラインの内側フレームを持つ紙のマウント。その角には、プレート番号、短いキャプション、インタラクションのヒント、およびライブの読み出し値が表示されます。
- キー。 ピンごとに1つのエントリがあり、部品の名前と、それが計算する内容を1行で示し、数式は等幅フォントで表示されます。エントリにホバーするとそのピンが強調表示され、ピンにホバーするとそのエントリが強調表示されます。
- 実験台で。 機器自身のノブと同じことを行う通常のボタンとスライダー。
- 壁テキストI:プレートを読む。 数式が書かれている順序で、用語ごとに1つのカラム:ローマ数字、動詞、用語、ピン番号で参照する2文、および現在の数値のボックス。
- 壁テキストII:台帳。 現在の状態に対する完全な動作。アイテムごとに1行。行をクリックするとそのアイテムが選択されます。
- 壁テキストIII:より広い視点。 機器が示すものの一部(完全な行列、全体のシーケンス、すべてのバケット)、およびセレクターが選択するバリアント。
- 壁テキストIV:この標本について。 3つの注釈:正確に計算されたもの、手動で選択されたもの、省略されたもの。常に含めてください。
- 奥付。 誰がプレートを作成し、どの書体を使用したか。
コントロールはポインターとキーボードの両方に応答します:ステーションをクリック、矢印でステップ、数字でバリアントを選択、角括弧でノブを回す、1文字でトグルを切り替え。誰も操作していないとき、プレートはゆっくりと自己デモを行います。ホバーまたはフォーカスで一時停止し、スクロールアウトすると休止し、動きの抑制設定では1つの静止フレームを表示します。読み出し値は aria-live を使用します。
フェーズC2:3つのビュー
すべてのプレートは、マウントの左上隅にある小さなスイッチ(SVG · WebGL · 3D)から選択できる、同じ機器を3つの方法で提供します。モデル、キー、および壁テキストはビュー間で変更されません。変更されるのは実験台の表示方法だけです。
SVG は、上記で説明した刻印図面です。これがデフォルトであり、常に動作する必要がある唯一のビューです。
WebGL は、図面を再描画せずにその上に光を配置します。光はSVGの上にあるキャンバス上に存在し、図面自体からレンダリングされたマスクを介して何が見えるかを認識します:light() はSVGをクローンし、役割ごとにすべての表面を再色付けし(床は赤、容器とパイプは緑、ガラスは青、その他は黒)、画家の順序を維持し、結果をテクスチャとしてアップロードします。図面が隠すものに光は触れることができないため、個別のオクルージョンロジックは必要ありません。各表面にクラス(台座には floor、隆起したレシーバーには pad、血管には pipe または血液クラス)で役割を与え、色のルールを maskCss として渡します。
シェーダー内で、onPlane(vb, z) はピクセルを水平面上のワールドポイントに戻し、project() は逆の方向に進み、fall() は部品を通る光が床のどこに落ちるかを見つけます(ランプは実験台の後ろにあるため、プールは部品の前、読者が見える場所に落ちます)。対象数量にのみ光を使用します:
- プレートI: 各カラムの液体はその重みで光り、波打つ光の筋が各カラムから実験台を横切って走り、パルスがマニホールドに沿って(重みがシフトしている間はより速く)走ります。
- プレートII: パルスはすべての血管を真の流れ(SVGの流れマークを動かすのと同じ累積体積)で伝わり、各チャンバーはその血液の色の光を放ち、心室は収縮時にフレアします。
光を事前乗算色(addLight)として蓄積し、テーマごとに色を選択します:紙の上では淡いハイライトと彩度の高いプール(通常のブレンド)、暗い地面ではより明るいグロー(スクリーンブレンド、--light-blend トークンで設定)。ビューがオンでプレートが画面に表示されている間のみレンダリングし、ピクセル比を1.5に制限し、動きの抑制設定では1つの静止フレームを描画します。
3D は実験台を完全に回転させます。シーン全体がカメラの関数であるため、stage.mount(az, el) は単に新しい角度から再構築します:すべての面はその向きによって再シェーディングされ、すべての丸い部品は再シルエット化され、すべてのハッチングは再配置され、すべての刻印ラベルは再投影されます。画家の順序はすべての側面から保持する必要があるため、「奥から手前」をハードコーディングしないでください:
- 各奥行きバンドを
{ y, draw }としてラップし、リストをapi.bands(list)に渡します。現在のカメラに対して遠くから近くにソートします。後ろからは、手前のバンドが最初に描画されます。 - バンド内、または別々の機械の実験台の場合は、各ユニットにワールド位置を与え、
api.units(list)を{ at: [x, y, z], draw }で使用します。プレートIIIは完全にこの方法で構築されています。 - 開放容器(トレイ、タンク)の壁は
api.backIsFarおよびapi.leftIsFarで順序付けられます。 - 台座の1つの面に取り付けられたもの(真鍮のカタログプレート、フロントパネル上のタイミングカム)は、その面が読者の方を向いている場合にのみ描画されます。最初に
cam.viewの符号を確認します。faceTextはすでに自動的にカリングされます。
orbit({ wrap: true }) はアジムスが360°を超えて実行できるようにし、stage は各角度でスケールを再調整し(orbitScale で上限が設定されるため、実験台のサイズが飛躍することはありません)、ダブルクリックでデフォルトビューに戻り、Shift + 矢印キーでキーボードから回転できます。2つの仰角で45°ごとの角度のグリッドで確認します。プレートIIの完全な再構築には約27ミリ秒かかります。これはドラッグするのに十分スムーズです。プレートがはるかに重い場合は、各スロットの最後の出力をメモ化し、変更されたものだけを再描画します(プレートIIIが行っているように)。
3Dを離れるとカメラはデフォルトビューに戻るため、WebGLライト(デフォルトビューを想定)は常に位置合わせされます。
フェーズC2b:内部の動き
プレートは、数字が横に並んだ静止画であってはなりません。実際に動く部品を見つけ、モデルから、目で追える速度で駆動します:
- 回転するもの。 サイトグラスのフローホイールは真の流れで回転し(プレートIのマニホールド)、タイミングカムはサイクルごとに1回転し、どのフェーズがアクティブかを示し(プレートII)、発電機の回転子、水車、調速機は機械の速度で回転します(プレートIII)。角度を時計からではなくモデルから累積します(
rot += ω·dt)。これにより、減速する機械がはっきりと見えるようになります。 - 移動するもの。 レベル、ピストン、弁尖、針、速度が上がると飛び出す調速機のボール、持ち上がる遮断機ブレード。
- 相互作用するもの。 一方の部品の動きがもう一方の部品をつかんだり、押したり、閉じたりする場合(例:カムがリフトする、ギアが噛み合う)。
これらの動きは step() または補間によって駆動されます。アニメーションに魔法の値は使用しないでください。モデルがすべてを指示します。
フェーズC3:1つのテーブル
ページのすべての数値テーブル(キー、壁テキストIの用語ボックス、壁テキストIIの台帳)は、model.js が返す単一のデータ配列によってバックアップされます。page.js はこれらのテーブルをレンダリングし、モデルが変更されるたびに再レンダリングします。数値が一致しないことはありません。
フェーズD:仕上げ
Folio.fontsを確認してください。プレートは等幅用にDM Mono、見出し用にSF Pro Displayを使用します。見つからない場合はフォールバックがあります。- 必要な
npm installはありません。ライブラリは自己完結型です。 page.htmlのプレースホルダーは、ビルドスクリプトによって自動的に入力されます。- アクセシビリティ:キーはキーボード操作可能、読み出し値は
aria-live、すべてのインタラクティブ要素にラベルが必要です。 - パフォーマンス:SVGは軽量に保ち、WebGLはピクセル比を制限し、3Dは再構築時にメモ化します。
トラブルシューティング
- SVGのパーツが表示されない: バンドの順序を確認してください。あるバンドが別のバンドを覆い隠していないか確認します。デバッグのために背景色を追加してみてください。
- WebGLの光が間違っている: マスクCSSの色が正しいか確認してください。
floor、pad、pipeのクラスがSVG要素に正しく適用されているか確認します。 - 3Dでパーツの順序が間違っている:
api.bands()とapi.units()を使用していることを確認してください。手動でのソートは行わないでください。 - アニメーションがぎくしゃくする:
step()が毎フレーム呼び出されているか確認してください。requestAnimationFrameループを確認します。
付録:folio-kit.js の保存
リポジトリなしでこのファイルだけを持っている場合、描画ライブラリは以下にあります(このファイルの末尾)。folio-kit.js として保存し、page.html から参照してください。