mcpField
I
illustration-ink-sketch

illustration-ink-sketch

github.com/mengtoクリエイティブ・メディア7.1k291 回インストール3 日前に更新
リポジトリ

illustration-ink-sketch について

デザインやコーディング向けのイラストスキルで、手描きのインク風カートゥーンを作成します。動物や物にコーディングの比喩を込め、揺らぎのある線やラフな色面、大きな目で表現します。

主な機能

  1. 01手描きブラシの輪郭
  2. 02ラフなマーカーの色面
  3. 03大きな目と表情の細部
  4. 04コーディングを題材にしたキャラクターと小物
  5. 05再現可能なSVG生成ツールキット

活用シーン

  1. 01ローディング画面のイラスト制作
  2. 02エラーや競合の表現
  3. 03製品の挨拶イラスト制作

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mengto/skills --skill illustration-ink-sketch

インストール後、Claude Code で/illustration-ink-sketchを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

style.json
agents/
openai.yaml
demo/
PROMPT.md
examples/
hello-world.svg
merge-conflict.svg
slow-build.svg
references/
craft.md
scripts/
ink-kit.mjs
lint.mjs
render.mjs

詳細

イラスト:インクスケッチ

ラフな手描きインクのカートゥーンです。大きな動く目をした生き物や物体(カタツムリ、2匹のミミズ、鉢植えのサボテンなど)が、体でコーディングの比喩を表現しています。ゆるく塗ったマーカーの色の上に、揺らぎのあるブラッシュペンで描きます。読み込み、エラー、挨拶、競合など、遊び心のあるプロダクトの場面に適しています。

境界線:人物に均一な約2 pxのインク線とベタ塗りを使う場合は、illustration-outlined-cartoon を使用します。黒いブラッシュマーカーとミント色の2色目で人物を描く場合は、illustration-two-colour-brush を使用します。粒子感のある柔らかな輪郭線なしの動物を描く場合は、illustration-grainy-gouache を使用します。

14種類のスタイルからなる42枚のオリジナルデザイン・コーディングカードのセットから抽出しました。examples/ にある3枚のカードは、このスタイルで公開されているカードです。

ひと言で表すと

すべての輪郭は、約1〜4.4 pxの幅で膨らみ、先端に向かって細くなる、塗りつぶされた黒いブラシのポリゴンです。色の塗りより2〜3.6 pxはみ出すように、数本の独立したストロークで描きます。暗い部分は塗りつぶさず、ハッチングで表現します。

パレット

作例から測定しました。各色系統はベース/ダーク/ライトで構成されます。ダークはまだら模様やマーカーのストロークに、ライトは光を受けた1本のストロークに使います。

役割Hex使う場所
カード背景#ffffff(描画なし)背景の矩形は描画しません。
インク#1d1a18すべての輪郭線、ハッチング線、髪、斑点、瞳、文字に使います。純粋な黒は使いません。
赤#f0563d / #b8311f / #ff8a6a、濃色 #9a2414殻、鉢、1匹のミミズ
黄#ffc83d / #ef9a24 / #fff1b0カタツムリの体、火花、花の中心。#fff1b0 は吹き出しの影にも使います。
緑#5cb946 / #2f8a38 / #a6dc62草地、サボテン
青#66cdea / #2a8fbf、しずく #bfe8f7スライム、マグカップ、進捗バーの塗り、汗のしずく
ティール#2fb5a7 / #167a71 / #8fe3d6、濃色 #0f5c55赤いキャラクターの隣に描く2人目のキャラクター
木#eaa85c / #b8722f / #f8d6a0、濃色 #8a5320机、テーブル
赤み#ff7f86(不透明度0.5〜0.75)、線 #d9434f または #c8303f3本の線が入った頬の丸い部分、舌
目の影#c9d6ea白目の内側の三日月形の部分
紙#fffaf0、折り目 #d9d2c4ステッカー、紙片、ラベル
単色口 #3b1f1a、花びら #ff8fa0、土 #5b3b2c、コーヒー #6b4330、柔らかな影 #7f97ab(不透明度0.22)個別のディテール
白#ffffff白目、光沢のストローク、吹き出し、ハイライト
  • 主役には2つの色系統を使い、地面には緑を使います(赤+黄色のカタツムリ、赤とティールのミミズ、緑のサボテン+赤い鉢+木の机)。3つ目の色系統は、小さな小道具にだけ使います。
  • グラデーションは使いません。不透明度を使うのは、まだら模様、ストローク、光沢、赤みだけです。瞳より大きな範囲を黒一色で塗りつぶすことはせず、ハッチングで表現します。

線と塗り

すべてのインク線はブラシ(キットの stroke())で描く塗りつぶされたポリゴンであり、SVG のストロークは使いません。サンプルには stroke 属性は一切含まれていません。

マーク幅 480 の場合の数値
輪郭OUT(centre):w 4.6、最大 4.4、最小 1.0、筆圧 0.4(波長 26)、ペン先 0.3、右下の影側を太くします(k 0.3~0.36)。テーパー t0/t1 は 3~30 px。形ごとに 3~6 本の独立したストロークを使い、明るい左上に 1 か所の隙間を設け、2~14 px のオーバーシュートを 1 か所加えます
補助線(縁、吹き出しのしっぽ、口)w 2.4~3.2、ペン先 0.45、筆圧 0.4、pf 8
ディテール(葉脈、しわ、木目)w 1.1~1.8、不透明度 0.55~0.85 で描画します
ハッチングw 1.0~1.15、間隔 2~3.2、角度 -48~-58 deg(右側が明るい形では -130 に反転)、端は縁の内側で揺らします
毛輪郭ストロークごとに 2~5 本、w 0.9~1.5、長さ 2.5~7、影側で外向きにします
点描カードごとに 9~11 個、サイズ 0.8~1.7、余白部分に配置します
塗りベースカラーを使い、輪郭から 2~3.6 px ずらして配置します(fillShape はオフ)。制御点を 1.2~1.6 揺らします
斑点すべての塗りの上に、斑点フィルターを通した不透明度 0.36~0.5 の暗色を重ねます
マーカーのかすれ暗色、w 4~16、不透明度 0.3~0.55、影側に沿って 1~3 本。形の内側でクリップします
光沢白、w 2.4~6、不透明度 0.85~0.95、丸い形の明るい左上に 1~2 本のストロークを入れます

各カードには 2 つのフィルターを使い、どちらにも接頭辞を付けます。rough(フラクタルノイズ 0.45、変位 0.7)はカード全体に適用し、すべての縁を揺らします。mottle(ノイズ 0.035 x 0.06、3 オクターブ、アルファ 2.6/-1.25)は水彩の斑点をマスクします。svgOut は両方を書き出します。

キャラクター

人物は登場しません。主役は生き物、または生きている物体です(カタツムリ、ミミズ、サボテンのほか、マグカップ、虫、ロボット掃除機など)。その体そのものがメタファーになります。殻はローディングスピナー、ミミズの細いしっぽはコミットの点が付いた Git ブランチ、鉢には </> のステッカーを貼ります。

  • 体: tube() を使い、背骨に沿って幅関数を適用したチューブにするか、12~24 個の制御点で閉じた塊を描きます。チューブの端では頭を膨らませます(胴体 40、頭 49)。モチーフの幅はカード幅の約 60~70% にします。
  • 目、特徴的な要素: 大きなギョロ目で、半径は 19~27.5(直径 40~55 px、頭の幅の 1/3~1/2)。通常は大きさを少し変えた一対を、接触または重ねて配置します。白い円盤に、右下へ #c9d6ea の陰影の三日月を入れます。縁は描き始めを膨らませてオーバーシュートさせます。瞳は半径の 0.5 倍で、見ている方向へ 4~10 px ずらします。大きなハイライトと小さなハイライトを 1 つずつ入れます。体の色(h 0.34~0.38)でまぶたを 17 deg 傾けて描くと、不機嫌な表情になります。
  • 顔: 8 x 4.6 の楕円形の頬紅に、短い赤い線を 3 本添えます。口は、両端に小さな線を添えた曲線 1 本の笑顔、ピンクの舌を入れた暗色の塗りつぶしの口(歓喜)、歯の線を 2 本入れた白い食いしばった歯(怒り)、または下唇を添えた下向きの線(ふくれ顔)にします。
  • 手(生き物に必要な場合): 手足と同じ色を使い、手のひらと 3 本の指、親指をカプセル形にします。指の関節は線をつなげずに描き、関節のしわと影側の暗い筋を加えます(キットの hand())。サボテンと同程度の大きさにし、スケール 1.25 で指の長さを 12~14.5 にします。親指は references/craft.md の利き手の表に従って配置します。
  • 触角、茎、しっぽ: 両側に輪郭を付けたテーパー状のチューブ、またはブラシストローク 1 本のらせんにします。棒状の脚を使う場合は、幅 2.4~3 のブラシストローク 1 本で描き、端に小さな塗りつぶしの楕円を付けます。
  • 短い脚と肉球(小型哺乳類): shadeTube と limbOutline({ under: bodyLoop }) で幅 9~14 の短いチューブを描き、花びら色の楕円(5.4 x 3.2)と短いインクの下線で終わらせます。体の奥側の脚を先に描き、手前側の脚を後から描きます。走っているように見えるよう、後ろ脚は腰の後ろへ、前脚は肩の前へ傾けます。
  • 力や感情を表すマーク: 汗、弓なりの括弧を 4 つ使った怒りマーク、動きの弧(幅 2.4 と 1.8 の同心ストローク 2 本をテーパーさせたもの)、湯気のカール。

飾りと小道具

  • 地面(どちらか1つを選択): x 52 から 428 に広がる、ぼさぼさの草地。上端は y 272 から 280、下端は両端が上向きに反り、ドライブラシの端、草の葉の跳ね、両端に1つか2つの高い草むらを加えます(grassPatch、tuft)。または、木目の線とハッチングした脚が1本ある、少し上から見た木製の机の天板。
  • 接地部分: 地面に接する各パーツのすぐ下にハッチングした楕円(幅 1.0、間隔 3 から 3.2、不透明度 0.85 から 0.9)を描き、胴体の付け根にさらに濃い筋を加えます。小道具は何かの上に置きます。看板は草地に立てた杭に、マグカップは机に置きます。浮かせてよいのは、吹き出し、飛んでいる紙片、マークだけです。
  • 小道具、1から3個: </> のコードステッカー、手描き文字を入れた吹き出し、コードの山かっこを描いた破れた紙片、湯気がくるくる立ちのぼるマグカップ、プログレスバー(白いトラック、ハッチングした青い塗り、手描きの %)、コミットを示す点、きらめく星形、花。
  • 文字: ブラシのストロークで手描きします(幅 2.4 から 2.6、字形の高さ 12 から 17 px)。フォントは使いません。
  • 禁止事項: ブラシの輪郭線がない整然とした幾何学的なベクター形状、グラデーション、ドロップシャドウ、黒一色の塗り、背景の風景、人。

構図

  • 背景の矩形は描きません。すべて x 36 から 444、y 40 から 340 の範囲に収めます。x 36 まで達してよいのは、地面のドライブラシの端だけです。
  • 主役は地面の中央下部に配置し、カード幅の約 60 から 70%、高さの約 60%を占めるようにします。目を上半分の焦点にします。空いている上部の隅を、吹き出し、紙片、マークのいずれかで埋めます。丸い、または背の高い主役(車輪、鉢など)は幅を約 50%にとどめ、幅を埋めるために、地面に接する小道具を横に1つ配置します。
  • このスキルに記載された数値はすべてカードサイズでの値です。拡大縮小するグループ内では、サイズを scale で割った値で描画します。また、接地部分(縁に乗せた足、机に置いた鉢など)は、まずカード座標で描画し、その後グループ内に変換します。const G = w => [B0[0] + (w[0] - B0[0]) / S, B0[1] + (w[1] - B0[1]) / S]。
  • 主役は、地面との接点を基準に <g transform="translate(cx gy) scale(1.12) translate(-cx -gy)"> 内でデザインサイズで描画し、setWScale(1/1.12) を設定して線幅を本来の値に保ちます。その後、setWScale(1) に戻します。
  • svgOut(file, {shift: [0, -8]}) を使うと、余白のバランスを整えるためにカード全体を移動できます。

テクニック

scripts/ink-kit.mjs は、3つの例の生成に使われたシード付きブラシライブラリです。元のライブラリの代わりにこれを使うと、Merge Conflict と Hello World のジェネレーターは、出荷されたカード上のすべてのマークを完全に再現します(違いは、以前のファイル書き込み処理が <defs> に残した余分なテキストノードだけです)。各マークにはそれぞれ独自の乱数ストリームを持つ文字列キーが割り当てられているため、マークを編集または追加しても、ほかのマークの配置は変わりません。キーを変更すると、特定のマークだけを再生成できます。

// card.mjs, next to a copy of ink-kit.mjs
import * as K from './ink-kit.mjs';
const { PAL, OUT } = K;
K.setPrefix('xx-');                                        // every id: filters and clip paths
K.grassPatch('grass', { x0: 60, x1: 420, top: 276, bot: 320 });
K.hatch('cast', K.arc(240, 286, 70, 6, 0, 360, 10), { ang: -58, sp: 3, w: 1.0, inset: 1.2, over: 0.4, op: 0.9 });
const ctrl = [];                                          // a round body: control points
for (let a = 0; a < 360; a += 30) ctrl.push([240 + 70 * Math.cos(a * K.deg), 220 + 62 * Math.sin(a * K.deg)]);
const loop = K.fillShape('body', ctrl, PAL.red.c, { off: [-3, 2], j: 1.4 });   // slipped fill
K.mottle(loop, PAL.red.d, 0.46);
K.clipOpen(loop);                                         // shading stays inside
K.stroke('streak', K.arc(240, 220, 60, 54, -10, 120, 6), { w: 13, t0: 20, t1: 25, wob: 1.5 }, PAL.red.d, 0.45);
K.stroke('gloss', K.arc(240, 220, 52, 48, 198, 236, 4), { w: 6, t0: 8, t1: 12 }, '#ffffff', 0.95);
K.clipClose();
const dl = K.resample(K.catmull(ctrl, true, 10), 1);      // outline in two strokes: gap top-left, overshoot
const o1 = K.stroke('o1', K.loopSlice(dl, 0.62, 1.18), { ...OUT([240, 220]), dense: true, t0: 12, t1: 10 });
K.stroke('o2', K.ext(K.loopSlice(dl, 0.2, 0.58), 3), { ...OUT([240, 220]), dense: true, t0: 8, t1: 6 });
K.hairs('hairs', o1.C, 4, { c: [240, 220] });
K.eye('eyeL', [216, 172], 21, [223, 176], 10.5);
K.eye('eyeR', [262, 168], 23, [269, 173], 11.5);
K.blush('blL', 206, 222); K.blush('blR', 280, 218);
[[96, 120, 1.5], [400, 96, 1.2], [420, 230, 1.1]].forEach((p, i) => K.fleck('fk' + i, ...p));
K.svgOut(new URL('./card.svg', import.meta.url).pathname, { label: 'Title, Ink sketch style' });   // next to card.mjs

キットに含まれるパーツ:stroke(ブラシ)、OUT(c)(輪郭線のプリセット)、hatch、fillShape、mottle、clipOpen/clipClose、hairs、fleck、dry、eye(lid を含む)、tube と across/acrossLine、shadeTube(手足または胴体の塗り、斑点、筋、光沢、リブ)、limbOutline(胴体の外に出ている手足の部分だけにインクを引く)、hand、grassPatch、blade/tuft、blush、sweatDrop、codeSticker、paperScrap(破れたメモ。書き込み位置として T(x, y) を返します)、fillRing(正面から見た車輪またはドーナツの表面。偶奇塗りつぶしと斑点を使用)、arc、loopSlice、ext、runsOutside、setWScale、svgOut。

無限大記号(幅 26 px のレムニスケート)のように、1本のブラシストロークで描く記号:

const inf = []; for (let t = 0; t <= 2 * Math.PI + 0.35; t += 0.07) { const s = Math.sin(t), c = Math.cos(t), d = 1 + s * s; inf.push([x + 13 * c / d, y + 13 * s * c / d]); }
K.stroke('inf', inf, { w: 3, t0: 3, t1: 5, nib: 0.45, press: 0.3, pf: 8 });

node scripts/ink-kit.mjs --demo $W/demo.svg を実行すると、デモカードが書き出され、wrote <path> 203.5KB 316 elements と表示されます。このカードには、草地の上で3本指の手を振る、目が飛び出した赤い blob が描かれ、ハッチング、コードステッカー、汗のしずく、細かな点が加わります。--prefix ikd- を指定すると、リンターを問題なく通過します。

失敗しやすいポイント

  • クリップアートのような線。 均一な太さの線や SVG の stroke 属性は、ベクター画像のように見えます。すべての線を、先細りと筆圧のあるブラシ形状にします。
  • 閉じた輪郭線。 形を一周する閉じた線は、なぞったように見えます。各輪郭線を 3~6 本に分け、光が当たる側に 1 つの隙間と、1 つのはみ出しを作ります。
  • 輪郭線にぴったり収まった塗り。 塗り絵のようなベクター画像に見えます。形ごとに塗りを 2~3.6 px ずらし、ずらす方向を変えます。
  • 平坦な色。 斑点や筋、光沢のない塗りは、印刷されたように見えます。すべての塗りに斑点を加え、丸みのある形には暗い筋を 1 本以上、光沢の線を 1 本以上入れます。
  • ベタ塗りの黒い影。 ハッチングを入れ、keep を使って光の方向に向かってハッチングの密度を下げます。
  • 生気のない目。 瞳が中央にあったり、ハイライトがなかったりすると、ぼんやりした目に見えます。瞳を動きのある方向へ 4~10 px ずらし、白い点を必ず 2 つ入れます。
  • 毛だらけ。 線 1 本につき 5 本を超える毛は、線が毛羽立って見えます。影側に 2~5 本加えます。
  • 宙に浮いた被写体。 ハッチングした接地楕円も、暗いベースの筋もないと、動物が草の上に浮いて見えます。
  • 拡大縮小されたグループ内で線幅がずれる。 setWScale(1/s) を忘れると、すべての線が 12% 太くなります。
  • 編集するたびにすべてが入れ替わる。 キーを再利用したり番号を振り直したりすると、マークが再生成されます。それぞれのマークに、安定した一意のキーを割り当てます。
  • 1 ページにある 2 枚のカードで同じフィルターを共有する。 カードごとに一意のプレフィックスを指定して setPrefix を呼び出し、--prefix で lint を実行します。
  • 活字のテキスト。 吹き出し内のフォントは手描きの雰囲気を損ないます。ブラシの線で文字を書き込むか、字形を描くのにジョークより時間がかかる場合は、記号(正の字の線、山形、シンボルなど)で表現します。
  • 小道具に顔がくっつきすぎている。 テストでは、ハムスターの鼻、口、前足が車輪の縁と一体化してしまいました。顔の周囲には 25 px の間隔を空け、手足の線を口の位置で終わらせないようにします。
  • 紙からはみ出したマーク。 正の字の点が切れ端の破れた縁からはみ出し、インクのしみのように見えてしまいました。マークは紙の縁から 4 px 内側に収めます。
  • 宙に浮いた看板。 被写体の横に空中で浮かぶメモは、配置ミスのように見えます。ハッチングした接地部分を作り、杭に立てます。

例

  • slow-build.svg(ビルドが遅い):進捗バーの 27% の位置で汗をかくカタツムリ。殻はハッチングした彗星の尾が付いた、らせん状のローディングスピナーです。眼柄、コードのステッカー、草むら、手描きの %、柔らかな接地影を表現しています。
  • merge-conflict.svg(マージコンフリクト):ブランチ線が交わる場所で、赤いミミズと青緑色のミミズが頭をぶつけています。節の輪がある筒状の体、不機嫌なまぶた、歯を食いしばった口とへの字口、コミットの点、火花、怒りのマーク、飛ばされた <<<< の紙切れを表現しています。
  • hello-world.svg(ハローワールド):鉢植えのサボテンが机の上で手を振り、コーヒーマグの横で「hello, world」と言っています。親指の位置が正しい 3 本指の手、鉢の縁に乗せた腕、棘の目盛りがある稜、木目、湯気の渦巻き、吹き出し内の手描き文字を表現しています。

ワークフロー

このスキルのフォルダーから実行します。render.mjs を使うには、playwright-core(または playwright)がこのフォルダー、現在のフォルダー、もしくはグローバルにインストールされていることと、Chromium が必要です。

  1. 概要。 題材とメタファーを決めます。どの生き物を描き、体のどの部分にアイデアを託すのかを決めます。480 px でそれを伝える表現(目、口、模様)を1つ書き留めます。
  2. 主役とポーズ。 シルエットを紙の上かコメントに描きます。背骨、目の位置、地面の線を示します。手ごとに、左右と手のひら側/手の甲側を craft.md に書き留めます。
  3. セットアップ: W=/tmp/ink-card; mkdir -p $W; cp scripts/ink-kit.mjs $W/ を実行し、Techniques のひな形を使って、一意のプレフィックスを付けた $W/card.mjs を作成します。
  4. ブロック: 地面、体の塗り、目だけを描きます。レンダリングしてサイズ、配置、1x での見え方を確認します。
  5. 描画: 影(まだら、筋、ハッチング、光沢)、別々の線で描く輪郭、毛、顔、小道具、文字、点描を加えます。
  6. レンダリング: node $W/card.mjs && node scripts/render.mjs $W/card.svg $W/card.png を実行します(card.mjs は同じフォルダーに card.svg を書き出します)。
  7. シート: node scripts/render.mjs --sheet $W/sheet.png examples/*.svg $W/card.svg を実行します。「同じ手で描かれているか、同じセットの一部に見えるか」を確認します。
  8. 拡大: 目、手、接地部分、文字を 6~8 倍で確認します。node scripts/render.mjs $W/card.svg $W/eyes.png --zoom x,y,w,h --scale 8
  9. references/craft.md の5つの基準と Verify のリストに沿って批評し、ジェネレーターを編集して修正します(SVG は決して編集しないでください)。繰り返します。3~4回の反復を見込んでください。
  10. Lint: node scripts/lint.mjs $W/card.svg --prefix xx- --palette style.json を実行します。すべての ERROR を修正します。各 WARN の色は、意図的に一度だけ使われている必要があります。

確認項目

  • stroke= 属性がどこにもないこと。すべての線が #1d1a18 の塗りつぶされたブラシ形状であること。
  • 輪郭が太くなったり細くなったりしていること(細い部分は約1 px、太い部分は約4.4 px)。各形状の輪郭に隙間と行き過ぎがあること。
  • すべての塗りが、線から2~3.6 px はみ出していること。
  • すべての塗りにまだら模様があること。丸い形状には暗い筋と白い光沢の筆跡があること。
  • 影と暗い領域に、-48~-58 度、間隔2~3.2のハッチングがあること。ベタ塗りの黒い領域がないこと。
  • 動眼は直径40~55 px で、瞳が動きの方向に寄り、それぞれに反射光が2つあり、内側に陰影の三日月形があること。
  • 輪郭の線ごとに毛が2~5本あること。余白に点描が9~11個あること。
  • 主役が草地または机の上にあり、接地影にハッチングがあること。意図せず浮いているものがないこと。
  • 主役に2つの色系統があり、地面には緑または木の色を使っていること。パレットの16進カラーコードのみを使うこと。
  • カード全体がプレフィックス付きの rough フィルターで囲まれていること。すべての id にプレフィックスが付いていること。
  • 文字がフォントではなく、ブラシで描かれていること。
  • タイトルがなくても、1x でメタファーが伝わること。

コメント