Web開発
Drawably: 手書き風UIコントロール
Drawably: Hand-Drawn UI Controls (github.com)
要約
Drawablyは、手書き風のUIコントロールを提供するJavaScriptライブラリです。各コントロールは、シード値に基づいたランダムなスケッチを生成し、アニメーションするような描画が特徴です。依存関係が少なく軽量で、ボタン、チェックボックス、入力フィールドなど、様々なUI要素に対応しています。また、React用のラッパーも提供されています。
全文翻訳
drawably 手書き風UIコントロール。マウントごとに、シード付きランダム性から新しいペン画が生成され、ストロークはアニメーションするような落書きのように揺らめきます。依存関係はゼロで、gzip圧縮で約9KBのJS(Reactラッパーは1KB未満を追加)と3KBのスタイルシートです。オプションのペンフォントは別途31KBです。
インストール
npm i drawably
クイックスタート
import { drawablyButton } from "drawably";
import "drawably/style.css";
drawablyButton(document.querySelector("#done"), { variant: "solid" });
React:
import { DrawablyButton } from "drawably/react";
import "drawably/style.css";
<DrawablyButton variant="solid" onClick={submit}>Done</DrawablyButton>
各アタッチコールはスケッチハンドルを返します:
const sketch = drawablyButton(el);
sketch.resketch(); // 新しいランダムシードで再描画
sketch.resketch(42); // 特定のシードで再描画
sketch.destroy(); // SVGとすべてのリスナーを削除
ボタン
3つのバリアントがあります: outline (デフォルト)、solid、scribble。
ボタンは非同期処理のためのステートマシンも備えています:
const button = drawablyButton(el);
button.setState("loading"); // ボタンを暗くし、速く揺らめかせる
button.setState("error"); // 赤で再描画
button.setState("success"); // 緑で再描画
button.setState("idle");
Reactでは、stateプロップを渡します。スケッチはそのまま残り、状態のみが変更されます:
<DrawablyButton state={saving ? "loading" : "idle"}>Save</DrawablyButton>
状態の色は --drawably-error および --drawably-success でオーバーライドできます。
二次または破壊的なアクションには、tone を "neutral" (ウォームグレー) または "danger" (赤) に設定します。
コントロール
関数
要素
期待するもの
drawablyButton(el, opts)
<button>
drawablyCheckbox(el, opts)
<input type="checkbox"> を含むラッパー
drawablyRadio(el, opts)
<input type="radio"> を含むラッパー
drawablyToggle(el, opts)
<input type="checkbox"> を含むラッパー
drawablyInput(el, opts)
<input> を含むラッパー
drawablyTextarea(el, opts)
<textarea> を含むラッパー
drawablySelect(el, opts)
<select> を含むラッパー
drawablyDivider(el, opts)
<hr> または div
drawablyCard(el, opts)
任意のブロック要素
drawablyBadge(el, opts)
任意のインライン要素
drawablyList(el, opts)
<ul> または <ol>。各<li>にはスケッチされたマーカーが付きます
バッジは variant: "outline" | "scribble" を受け取り、リストは marker: "dash" | "check" を受け取ります。
Selectは最も幅の広いオプションの幅を確保するため、選択してもレイアウトがシフトすることはありません。Chromiumではオプションリストにスケッチされたフレームとペンチェック (appearance: base-select) が表示され、SafariとFirefoxはOSのポップアップを維持します。
実際の入力要素はDOMに残るため、キーボード、フォーム、ラベル、スクリーンリーダーは通常通り機能します。スケッチは、その下にレイヤー化された aria-hidden SVGです。
すべてのコントロールには、drawably/react に対応するReactコンポーネントがあります: DrawablyButton, DrawablyCheckbox, DrawablyRadio, DrawablyToggle, DrawablyInput, DrawablyTextarea, DrawablySelect, DrawablyDivider, DrawablyCard, DrawablyBadge, DrawablyList。
テキスト装飾
コピーをペンで注釈付けするかのようになります。各要素はインライン要素にアタッチされ、レイアウトを変更しません。単語や短いフレーズに使用します。
関数
描画するもの
drawablyUnderline(el, opts)
テキストの下にラフな線を描画し、ホバー時に再スケッチします
drawablyHighlight(el, opts)
テキストの後ろにマーカーのウォッシュを描画します
drawablyCircle(el, opts)
テキストの周りをループする手書き風の楕円を描画します
drawablyArrow(from, to, opts)
ある要素から別の要素への矢印を描画します
import { DrawablyUnderline, DrawablyHighlight, DrawablyCircle, DrawablyArrow } from "drawably/react";
<p>
<DrawablyUnderline>Hand-drawn</DrawablyUnderline> UI, a{" "}
<DrawablyHighlight>fresh sketch</DrawablyHighlight> on{" "}
<DrawablyCircle>every mount</DrawablyCircle>.
</p>
<DrawablyArrow from={noteRef} to={buttonRef} />
複数行にまたがる装飾は、行ごとに1つの描画が生成されます。矢印のSVGはドキュメント座標で<body>に追加され、リサイズ時に再描画されます。スクロールコンテナ内のアンカーは、スクロールするとずれます。
コンポジット
上記のコントロールから構築されたピース。1つのシードですべてのストロークが再現され、destroy()ですべて破棄されます。
関数
マークアップ
描画するもの
drawablyChip(el, opts)
<label><span><input type="checkbox"></span> text</label>
チップの周りのバッジ、入力ラッパーのスケッチされたボックス
drawablyTabs(el, opts)
子要素はタブ
アクティブなタブの下線。アクティブなインデックスまたは aria-selected="true"。setActive(i)
drawablyTooltip(tip, target, opts)
2つの要素
チップの周りのカード、ターゲットへの矢印
drawablyAlert(el, opts)
オプションの [data-tag] 子要素
アラートの周りのカード、タグのバッジ
drawablySteps(el, opts)
<ol>
チェックマーク付きリスト
drawablyKbd(el, opts)
<kbd>
より安定した手書き風のバッジ
drawablyQuote(el, opts)
最初の要素の子、オプションの <footer>
行のハイライト、フッターの区切り線
drawablyPager(el, opts)
子 <button>s
アウトライン付きページ、ソリッドカレント。アクティブなインデックスまたは aria-current。setPage(i)
import { DrawablyChip, DrawablyTabs, DrawablyTooltip, DrawablyAlert, DrawablySteps, DrawablyKbd, DrawablyQuote, DrawablyPager } from "drawably/react";
<DrawablyChip defaultChecked>pen</DrawablyChip>
<DrawablyTabs active={tab}><span>a</span><span>b</span></DrawablyTabs>
<DrawablyTooltip to={buttonRef}>undo</DrawablyTooltip>
<DrawablyAlert><span data-tag>new</span> Import from Attio lands Friday</DrawablyAlert>
<DrawablySteps><li>record</li><li>label</li></DrawablySteps>
<DrawablyKbd>⌘K</DrawablyKbd>
<DrawablyQuote><span>less, but better</span><footer>Rams</footer></DrawablyQuote>
<DrawablyPager active={page}><button>‹</button><button>1</button><button>›</button></DrawablyPager>
オプション
すべてのコントロールは同じ基本オプションを受け取ります:
オプション
デフォルト
説明
seed
ランダム
マウントごとにユニークなスケッチを生成します。数値を渡すと再現可能なスケッチになります。
roughness
1
ベーススケッチの揺らぎ。
boil
0.3
フレーム間のちらつきのピクセル数。0は単一の静的なパスを描画します。
stroke, fill, paper
pen blue / white
色。--drawably-* カスタムプロパティとして設定します。
width
2
ストロークの幅(px)。
色はプレーンなCSSカスタムプロパティなので、テーマで一度に設定できます:
:root {
--drawably-stroke: #1a1a1a;
--drawably-fill: #1a1a1a;
}
タイプは、ページにロードされている場合はInterになり、システムUIにフォールバックします。ライブラリは、以下のフォントをオプトインしない限り、フォントをロードしません。
モーション
ストロークは穏やかに揺らめきます。同じスケッチの3つのフレームが、共有ベースを中心にマイクロ揺らぎし、純粋なCSSで1200msごとにサイクルされます。ホバーまたはプレスは、ボタン、チェックボックス、ラジオ、トグル、下線、円を再スケッチします。ボタンはホバー時に上がり、プレス時に沈みます。
prefers-reduced-motion は、上記デモ画像を含むすべてを単一の静的なスケッチにフリーズします。
フォント (オプション)
Drawably Penは、タイプフェイスと同じストロークです。a–z、A–Z、数字、句読点が、ライブラリ自身のペンコード (font/) によって31KBのTrueTypeフォントとして構築されています。style.cssではロードされず、ライブラリのどの部分もそれを必要としません。クロムと同じ手書き風のラベルが必要な場合:
import "drawably/font.css";
.drawably-button {
font-family: "Drawably Pen", Inter, sans-serif;
}
独自の形状を作成する
ラフレンダラーがエクスポートされています。各関数はSVGパス文字列を返し、variantsは揺らぎフレームを生成します:
import { roughRoundedRect, roughLine, roughCircle, variants } from "drawably";
const frames = variants( (o) => roughRoundedRect(0, 0, 200, 100, 12, o),
{ seed: 7, roughness: 1, boil: 0.3 },
);
// 3つのパス文字列 — それらをレンダリングしてサイクルします
また、roughEllipse、roughArrow、roughCheckmark、scribbleFill、およびシード付きPRNG mulberry32 with randomSeed もエクスポートされています。
ライセンス
MIT。