mcpField
H
hand-drawn-cartoon

hand-drawn-cartoon

github.com/phantomtonytクリエイティブ・メディア2152 回インストール3 週間前に更新
リポジトリ

hand-drawn-cartoon について

HyperFramesで手描き風の短いカートゥーン動画を企画・制作するためのスキルです。構成、動き、描画スタイル、レンダリングと確認の手順をまとめています。

主な機能

  1. 01ブリーフとビートの設計
  2. 02画面比率・長さ・トーンの設定
  3. 03SVGとGSAPによる作画ガイド
  4. 04文字の可読性と動きのタイミング
  5. 05スナップショット確認とレンダリング手順

活用シーン

  1. 01一つのジョークやアイデアを短編化
  2. 02ブランド指定に合わせた配色調整
  3. 03ビートと画面テキストの計画
  4. 04ループアニメーションの確認と出力

インストール

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

$npx skills add https://github.com/phantomtonyt/motion-design-skills --skill hand-drawn-cartoon

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

詳細

手描きカートゥーン

小さなキャラクターが、紙の舞台でひとつのアイデアを演じます。線はインクで描かれ、数フレームごとに描き直されているかのように、かすかに動きます。動く絵本のページのように、手作りの温かさとユーモアが感じられる仕上がりにします。

オプション

オプションデフォルト備考
フォーマット縦型 1080×1920または横型 1920×1080、正方形 1080×1080
長さ15 s10〜45 s が最適です
トーン遊び心のある雰囲気calm(長めの間、穏やかなイージング)、playful(デフォルト)、slapstick(大きなスクワッシュ、テンポの速いギャグ、多めのカット)
キャラクターシンプルで丸いキャラクターまたはユーザー独自のキャラクター(シルエットと色を合わせます)

ユーザーは「縦型、20秒、ドタバタ調」のように、普通の言葉で指定できます。

概要(計画前に回答)

  1. アイデアやジョークの核は何ですか?一文で答えてください。
  2. キャラクターは誰で、何を望んでいますか?
  3. 最初に何がうまくいかず、どんでん返しやオチは何ですか?
  4. 最初の1秒で画面に何を映しますか?(フック)
  5. 動画を締めくくるセリフやタイトルは何ですか?

次に、ビートリストを作成します。時間、見えるもの、キャラクターの動き、テキスト、音を書きます。各時間の合計を目標の長さに合わせます。基本の構成は、フック(1.5 s)、挑戦と失敗、アイデア、試み、オチ、エンドカードです。

読み取りシート(ビートリストと一緒に作成)

各ビートについて、視聴者が理解すべきことをひとつ(「ロボットは飛べない」「キャッシュがヒットしなかった」など)書き、それが読み取れる状態で表示される時間も記載します。テキストは一度にひとつずつ表示します。テキスト表示時間の最低基準:ラベルは少なくとも0.8 s、文は完全に画面に表示されてから、単語数あたり約0.3 sです。時間内に収まらない場合は、表示を速めるのではなく、単語を削ります。

動きのルール

  • 動きには原因があります。キャラクターは画面上の何かに反応し、すべての動作に原因と結果があります。
  • キャラクターを完全に静止させません。待っている間も呼吸し、まばたきし、重心を移動させます。こうした待機中の動きも演技の一部なので、小さく不規則にします。
  • 左右対称の動きは避けます。腕を鏡写しのように動かさず、目、触角、体をすべて同じフレームで動かし始めないようにします。各パーツの動きは2〜4フレームずらします。
  • オーバーシュートやスクワッシュはキャラクターに使います(着地、飛び出し、驚き)。カメラとテキストは滑らかなイーズアウトで動かします。
  • シーンごとに主な移動方向をひとつに絞り、クロスフェードではなく、シーンの切り替わりをまたいでキャラクターや小道具を移動させます。
  • オチの直前に0.3〜0.75 sのポーズを入れ、オチを際立たせます。

スタイルのルール(常に適用)

  1. すべての線は温かみのある濃いインク色(#2b1d16前後)、1080幅で5〜8 px、角は丸くします。真っ黒は使いません。
  2. 線には揺らぎを加えます。インクレイヤー全体に、わずかに異なる3種類の変位フィルターのいずれかを適用し、2フレームごとに切り替えます(12 fps)。揺らぎがないと、滑らかなベクター画像に見えてしまいます。
  3. 紙の質感を常に残します。温かみのあるオフホワイトの背景に、かすかな粒子のオーバーレイと柔らかなビネットを加えます。
  4. 陰影はクレヨンのハッチングか、単色の濃いトーンで表現します。キャラクターにグラデーションは使いません。
  5. キャラクターは丸くシンプルにします。大きな頭や体、点または楕円形の目、白いハイライト、小さな口、短い手足を基本とします。全身を使って演技させます。
  6. すべての動作に、予備動作、動き、接触時のスクワッシュ、落ち着く動きを入れます。

デフォルトと上書き設定

優先順位は、ユーザーのブランドや仕様、明示的なリクエスト、これらのデフォルトの順です。ユーザーがブランドカラーを指定した場合は、キャラクターとアクセントカラーひとつに使います。インク、紙、粒子の質感はそのままにします。

  • 紙 #efe6d2、明るい紙 #fbf6ea、インク #2b1d16、アクセント #b8402f(タイトル、重要な小道具)、空のウォッシュ #b9d8e8、太陽またはアイデアを表す黄色 #f5c842、キャラクターの色 #7fb6c9。
  • フォント:タイトルにはCaveat Brush、ラベルにはPatrick Hand(Google Fonts)。9:16では、タイトルを80〜110 pxにします。

セットアップ(初回のみ)

node -v && ffmpeg -version
npx hyperframes init my-video --non-interactive --resolution portrait && cd my-video   # landscape for 16:9

既存の空のフォルダーで npx hyperframes init . --non-interactive --resolution portrait を実行し、次に index.html を構成に置き換えます。

方針

要件HyperFrames の SVG + GSAP(デフォルト)p5.js + p5.brush(キャンバス)
揺らぎのあるインク線はい(変位フィルター)はい(シードを再設定したブラシの揺らぎ)
水彩のにじみとドライブラシの質感近似(粒子、ハッチング)はい
GPU なしでの高速レンダリングはい遅め
名前付きの再利用可能なパーツを持つキャラクターはい難しい

デフォルトでは SVG + GSAP を使います。本物の絵の具のようなにじみが重要な場合に限り、p5.brush を使います。その場合は、時間 t から各フレームを描画します(固定シードなしでランダム性を使わないでください)。

ビジュアル表現

  • ステージ: 床の線、屋上、またはテーブルの縁と、小道具を 1 つか 2 つ配置し、空または壁を描きます。形は少し不規則にします(完璧な長方形ではなく、手描きのパスを使います)。
  • 奥行き: 遠景のレイヤー(太陽、雲、丘)、中景のレイヤー(ステージ)、近景のレイヤー(小道具やカメラの前を通り過ぎる雲)を用意します。ワールドグループを動かしてカメラを移動させ、遠景のレイヤーは移動量を少なくします。
  • キャラクターのパーツ: 体、目、口、左右の腕、アンテナや耳をそれぞれ別のグループにし、個別に動かせるようにします。ラッパーグループ(<g transform="scale(1.7)">)でキャラクターのサイズを調整し、外側のグループで x、y、回転をアニメーションさせます。SVG の変換はデフォルトで左上を原点とするため、アニメーションさせるグループ自体を拡大縮小すると位置がずれます。
  • スクワッシュ&ストレッチ: 足を中心に行い、キャラクター自身の座標で足の位置に svgOrigin を設定します(例:svgOrigin: "0 6")。体積を保ちます。高さを 10% 増やす場合は、幅を約 5% 狭めます。
  • エフェクト: ふくらませて消える砂ぼこり(r 属性のアニメーションで円を大きくしてからフェード)、回転する目が回った星、スピード線、きらめき。すべてにインク線を付けます。
動きタイミング
予備動作のスクワッシュ0.1–0.12 s
跳び上がり0.4–0.5 s、power2.out
頂点でのコミカルな滞空0.3–0.5 s
落下0.25 s、power3.in
着地時のスクワッシュ0.08 s。その後、0.5 s かけて弾むように落ち着かせる
まばたき0.12 s、2–4 s ごとに不規則に
頭を傾ける0.3 s、8–12°

目を引く映像にする

  • 最初のフレームを完成した絵にします。ステージ、キャラクター、空、手描きのカードに載せたタイトルを入れます。
  • すべての拍で何かを動かします。鳥、ゆっくり回る太陽、流れる雲、アンテナの揺れ、まばたきなどです。
  • 大きな見せ場ではカメラを使います。視差のあるレイヤーとともに、キャラクターを上または横に追います。
  • キーとなる小道具とタイトルのキーワードには、アクセントカラーを 1 色使います。それ以外は落ち着いた色にします。
  • ギャグはシルエットだけで伝わるようにします。失敗は砂ぼこりと星を伴う大きなスクワッシュ、成功はひと目で伝わる大きなポーズにします。
  • 最後のフレームは最初のフレームと一致させます(同じ構図、同じポーズ)。そうすれば動画をループできます。
  • 静止したどのフレームも、投稿する価値があるものにします。スナップショットが空っぽ、または平坦に見えるなら、まだ完成ではありません。

スターター

<div id="root" data-composition-id="main" data-start="0" data-duration="15" data-width="1080" data-height="1920">
<svg viewBox="0 0 1080 1920" width="1080" height="1920">
  <defs>
    <filter id="boil0"><feTurbulence type="fractalNoise" baseFrequency="0.03" numOctaves="2" seed="2"/><feDisplacementMap in="SourceGraphic" scale="4"/></filter>
    <filter id="boil1"><feTurbulence type="fractalNoise" baseFrequency="0.03" numOctaves="2" seed="9"/><feDisplacementMap in="SourceGraphic" scale="4"/></filter>
    <filter id="boil2"><feTurbulence type="fractalNoise" baseFrequency="0.03" numOctaves="2" seed="17"/><feDisplacementMap in="SourceGraphic" scale="4"/></filter>
    <filter id="grain"><feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="3" seed="5"/>
      <feColorMatrix type="matrix" values="0 0 0 0 .3  0 0 0 0 .24  0 0 0 0 .16  0 0 0 .2 0"/></filter>
    <pattern id="hatch" width="14" height="14" patternUnits="userSpaceOnUse" patternTransform="rotate(35)"><line x1="0" y1="0" x2="0" y2="14" stroke="#2b1d16" stroke-width="3" stroke-opacity=".28"/></pattern>
  </defs>
  <rect width="1080" height="1920" fill="#efe6d2"/>
  <g id="world"><g id="ink" filter="url(#boil0)" stroke="#2b1d16" stroke-width="7" stroke-linejoin="round" stroke-linecap="round">
    <path d="M-60 1312 L770 1304 Q810 1306 812 1330 L800 2200 L-60 2200 Z" fill="#c9b79a"/>          
    <g id="hero"><g transform="scale(1.7)">                                                         
      <g id="body"><circle cx="0" cy="-100" r="92" fill="#7fb6c9"/><path d="M-92 -100 a92 92 0 0 0 184 0" fill="url(#hatch)" stroke="none"/>
        <rect x="-58" y="-128" width="116" height="62" rx="30" fill="#fbf6ea"/>
        <g id="eyes" stroke="none" fill="#2b1d16"><ellipse cx="-24" cy="-98" rx="11" ry="15"/><ellipse cx="24" cy="-98" rx="11" ry="15"/></g>
        <g id="armR"><path d="M88 -92 q40 10 52 46" fill="none" stroke-width="12"/></g></g>
    </g></g>
  </g></g>
  <rect width="1080" height="1920" filter="url(#grain)"/>
</svg></div>
<script>
const tl = gsap.timeline({ paused: true });
for (let i = 0; i < 90; i++) tl.set("#ink", { attr: { filter: `url(#boil${i % 3})` } }, i / 6);   // boil on twos
gsap.set("#hero", { x: 400, y: 1316 });                                                          // feet on the stage
tl.to("#body", { scaleY: 0.85, scaleX: 1.1, svgOrigin: "0 6", duration: 0.1, yoyo: true, repeat: 1 }, 1.7);  // anticipation
tl.to("#hero", { y: 956, duration: 0.45, ease: "power2.out" }, 1.95).to("#hero", { y: 1316, duration: 0.25, ease: "power3.in" }, 2.9);
tl.to("#body", { scaleY: 0.5, scaleX: 1.35, svgOrigin: "0 6", duration: 0.08 }, 3.15)
  .to("#body", { scaleY: 1, scaleX: 1, svgOrigin: "0 6", duration: 0.5, ease: "elastic.out(1,0.4)" }, 4.3);
tl.to("#armR", { rotation: -60, svgOrigin: "88 -92", duration: 0.16, yoyo: true, repeat: 5 }, 13.6);   // wave
tl.set({}, {}, 15);
window.__timelines["main"] = tl;
</script>

<head> に GSAP スクリプト(https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js)、Google Fonts のリンク、html,body{margin:0;width:1080px;height:1920px;overflow:hidden} を追加します。ビートリストに沿って、同じ tl に動きを作り込んでください。

公開するパラメーター

format · duration · tone · characterColor · accent · paper · title · endLine · beats。スクリプトの先頭で定数として定義してください。

避けること

  • 完璧な幾何学図形や、揺らぎのないきれいな線(平面的なベクターに見えます)。
  • キャラクターへのグラデーション、グロー、ドロップシャドウ。
  • 広い空間の中で小さく見失われるキャラクター。キャラクターの高さはフレームの 25–45% にします。
  • キャラクターの顔に重なるテキスト、および 9:16 フレームの下から 670 px 以内、または上から 270 px 以内に配置するテキスト。
  • Math.random() や時刻に依存するロジック。揺らぎやエフェクトはタイムラインから生成してください。

失敗しやすい点

状態原因修正方法
きれいなベクターで、手描きに見えない揺らぎがなく、形が完璧すぎる3つの変位フィルターを2フレームごとに切り替え、手描きのパスを使います
拡大縮小するとキャラクターがずれたり沈んだりする動いているグループに拡大縮小のアニメーションを設定しているサイズは内側の<g transform="scale()">に設定し、足元をsvgOriginにして縦につぶします
エフェクトが隅から始まる表示前にx/yを設定していない時刻0で開始位置をgsap.setで設定します
色が濁ってコントラストが低い中間色が多すぎる明るい紙色、暗いインク色、アクセントカラーを1色にします
演技がぎこちない予備動作や収まりのない動きになっている前にスクワッシュを加え、後に弾むような収まりを加えます
タイトルを重ねた際にテキストの重なり警告が出る手書きフォントの行ボックスが接触している行間に10~20 pxの間隔を設け、スナップショットで確認します

検証

npx hyperframes check
npx hyperframes snapshot --at <one time per beat, plus one mid-transition>
npx hyperframes render -o renders/<name>.mp4

すべてのスナップショットとsnapshots/contact-sheet.jpgを確認します。

  • 1/6秒離れた2つのスナップショットで線がはっきり異なる(揺らぎが機能している)
  • キャラクターがステージ上に立っていて(沈んでおらず)、スマートフォンの画面サイズでも見やすい
  • シルエットで各ビートの内容が伝わり、失敗と成功の見せ場が大きく表現されている
  • テキストがセーフエリア内にあり、トランジション中に要素がぶつからない
  • 最終フレームが最初のフレームと一致する

最終レンダリング前の自己評価

スナップショットシートを、フック(最初の1秒)、スマートフォン幅での見やすさ、動きの質、構図、正確さ、「ミュートテスト」(音声なしで視聴者が一文で要約できるか)の各項目について1~10点で評価します。7点以下の項目だけ修正し、再度スナップショットを作成して、すべて8点以上になるまで繰り返します。可能であれば、自分の作品を評価することにならないよう、別の読み取り専用パスで採点します。

避けること代わりにすること
要素の多い2つのレイアウトをクロスフェードする古い内容を退場させてから新しい内容を登場させるか、1つのオブジェクトを引き継ぎます
複数の要素を同時に動かすタイミングをずらし、各瞬間の焦点を1つにします
間を浮遊や揺れで埋める静止させるか、キャラクターに演技させます
「躍動感」を出すために粒子、虹色のグラデーション、3D反転を加えるリビール、衝撃、カメラ移動など、より強いイベントを加えます
時間に収めるためにテキストを急いで表示する言葉を削ります

納品

  • 落ち着いた状態のフレームから最も良いものをポスターに選びます:ffmpeg -ss <t> -i renders/<name>.mp4 -frames:v 1 poster.jpg。サムネイルに表示されるよう、フレーム0として焼き込みます:ffmpeg -i renders/<name>.mp4 -i poster.jpg -filter_complex "[0:v][1:v]overlay=enable='eq(n,0)'" -c:a copy renders/<name>-final.mp4。
  • 手法ではなく、アイデアを説明する1~2文のキャプションを書きます。
  • 各ビートで何が起きるか、改訂時にどのパラメーターを変更すればよいかをユーザーに伝えます。

参考資料

コメント