本文へ移動
cccskills
無料GitHub で公開

ascii-backdrop

Turn any subject into an animated ASCII backdrop behind a UI, like a dark prompt page with jellyfish drawn in drifting characters, or a swarm of colour-tile bodies that veer away from the cursor. The subject is open-ended: creatures, objects, particles, smoke, a word or logo, an image or video, a per-pixel field, a shaded 3D solid, or your own canvas draw function. Six print modes can be mixed: brightness glyphs, edge-following glyphs, shape-matched glyphs, braille dots, ordered-dither dots and colour tiles; plus cursor glow, click ripples, a CRT terminal finish, and two page helpers (text decode and image-to-ASCII dissolve). Ships a dependency-free JS engine with HTML and React wiring. Use when the user asks for an ASCII background, ASCII art animation, glyph or braille backdrop, text scramble/decode, or an ASCII image reveal, or says 'ASCII 背景' / '字符画动效'.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbookスター 288(GitHub 288 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(5)

  • SKILL.md11.4 KB
  • assets/ascii-backdrop.js53.1 KB
  • assets/demo.html14.8 KB
  • scripts/check.mjs2.2 KB
  • scripts/regression.mjs36.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

ASCII Backdrop

A subject paints brightness or colour on a small canvas; the engine prints every character cell as a glyph, dot or tile. Anything that can paint on a canvas can be the subject.

How it works

Every frame, each layer's subject draws itself on a small offscreen canvas (a few pixels per character cell). The engine reads those pixels and prints them in the layer's mode. A lower depth dims a layer, which gives depth for free; a clear zone fades output around the UI so headings and inputs stay readable. Changing the subject means changing one draw function; the engine does not change.

Print modeLayer settingLookFrame cost at 1440×900 (measured)
Brightness glyphsdefault mode: 'glyph'Glyph from the density ramp; the brightest cells print as filled boxes~8 ms
Edge glyphsglyph: { edges: true }/ \ | - follow strong edges~8 ms
Shape matchingglyph: { match: 'shape' }Samples a 2×3 grid per cell and picks the glyph whose shape fits best, for crisper outlines (after Alex Harri)~5 ms (cached)
Braillemode: 'braille'2×4 dots per cell, twice the resolution, optional Bayer dither~6 ms
Dithermode: 'dither'Bayer 4×4 ordered dither, dots or squares sized by level~6 ms
Colour tilesmode: 'tile'Rounded squares in the colours the subject paints~3 ms

Subjects paint in white (brightness = density); only tile layers paint real colours. Layers in different modes can share one scene.

Files

  • assets/ascii-backdrop.js: engine, built-in subjects and page helpers, no dependencies, exposed as window.AsciiBackdrop. Copy it into the project.
  • assets/demo.html: a dark prompt page with the backdrop behind it; switch subjects, print modes, glyph sets, CRT and palettes; the heading decodes; a corner card shows the image dissolve; upload an image or video.
  • scripts/check.mjs: screenshots desktop, phone and reduced-motion views and reports errors and frame rate (needs Playwright).

Steps

  1. Choose the subject. Ask what it should say (a brand mascot, a product, a mood) instead of assuming a creature. Pick the source in this order:
    • Existing image, SVG, video or logo: subjects.image(src, { invert, motion }). Use invert: true for dark art on a light background.
    • A word, name or emoji: subjects.text('…').
    • A mathematical field (plasma, interference, noise, gradients): subjects.field((u, v, t) => brightness) with u, v in [-0.5, 0.5], like a fragment shader.
    • A shaded 3D solid: subjects.sdf({ shape: 'torus' | 'sphere' | 'box' | 'capsule' }), or pass your own (p) => distance.
    • Presets: jellyfish, school (many small bodies), cloud (smoke, nebula), strands (kelp, hair; flip: true for flames), rising (fire, bubbles, sparks; fall: true for snow or rain), solid (spinning wireframe), ripples (ambient rings plus a ring per click), wanderers (tile-mode segmented bodies that wander and veer away from the cursor).
    • Nothing fits: subjects.custom((ctx, t, s, env) => { … }) (see "Write a subject"). Presets are starting points, not the menu.
  2. Choose the print mode. Edge glyphs or shape matching for clean outlines; braille for fine shading; dither for a printed, retro look; tiles for coloured subjects.
  3. Compose the layers. Each layer is { subject, mode, x, y, scale, depth, drift, speed, timeOffset, rotate }; x and y are 0–1 of the screen. A layout that works: one hero below the input, one above it, two faint ones at the sides (depth 0.4–0.6). Give repeats different seed or timeOffset values so they do not move in sync.
  4. Palette, glyphs and finish. palette lists 3–5 colours from dark to bright; built-ins are PALETTES.abyss / ember / mono / phosphor / amber / duo. background matches the page. Glyph sets: RAMPS.dense / soft / classic / binary / blocks / dots / katakana. Add crt for a terminal look and keep it subtle. Aim clear at the heading and input.
  5. Wire it in. Put a full-screen <canvas> behind the content (position: fixed; inset: 0), keep content above it, and give panels a translucent fill with backdrop-filter. React notes are below.
  6. Verify. Run node scripts/check.mjs page.html and look at the three images: is the subject recognisable, are the heading and input clear, is the phone view too busy, does reduced motion show one still frame? Completed-frame rate should track the configured fps; a stopped backdrop reports 0. Fields and CRT cost about 16–17 ms per frame; if frames drop, raise cell, lower fps, or lower the field's resolution.

Wiring

<canvas id="bd" style="position:fixed;inset:0;width:100%;height:100%"></canvas>
<script src="ascii-backdrop.js"></script>
<script>
  const { subjects: S, PALETTES } = AsciiBackdrop;
  const bd = AsciiBackdrop.create(document.getElementById('bd'), {
    palette: PALETTES.abyss,
    clear: { x: 0.5, y: 0.46, rx: 0.3, ry: 0.2, strength: 0.85 },
    glyph: { edges: true },                                    // outlines in / \ | -
    interactive: true, pointerGlow: { radius: 110, strength: 0.35 },
    layers: [
      { subject: S.jellyfish({ seed: 1 }), x: 0.56, y: 0.76, scale: 0.72, depth: 1 },
      { subject: S.sdf({ shape: 'torus' }), mode: 'braille', x: 0.15, y: 0.3, scale: 0.45, depth: 0.6 },
    ],
  });
  bd.start();
</script>

React: call create inside useEffect and return () => bd.destroy(). When layers change, call bd.setLayers(...); when options change, call bd.set({...}). Do not recreate the backdrop on every render.

Tile mode and interaction

const bd = AsciiBackdrop.create(canvas, {
  interactive: true,
  background: '#1b1a18', grid: 'dots',
  palette: ['#34322f', '#5f5c56', '#9a968e', '#e6e2da'],
  tile: { size: 12, gap: 2, radius: 2 },            // square size, gap, corner radius
  layers: [
    { subject: S.ripples(), x: 0.5, y: 0.5, scale: 1.9, depth: 0.7 },                  // glyph ripples
    { subject: S.wanderers({ count: 7 }), mode: 'tile', x: 0.5, y: 0.5, scale: 1.7 },  // tile bodies
  ],
});
  • Tile layers paint real colours. Use dark grey instead of pure black for dark markings; pure black reads as empty. Pass your own colours with wanderers({ colors: [{ base, mark, accent }] }).
  • With interactive: true, subjects receive env.pointer (the cursor in that layer's local units) and env.clicks (recent clicks with their age). pointerGlow brightens output near the cursor on every non-tile layer without any subject code.
  • Read interaction from env instead of storing state in the subject. Write fleeing as "the closer the cursor, the further the push" so any moment can still be sampled directly.

Page helpers

// Heading text cycles through noise and settles left to right. trigger: 'load' | 'hover' | 'view' | 'manual'
AsciiBackdrop.scramble(document.querySelector('h1'), { trigger: 'view', duration: 900 });

// An image shows as characters, then dissolves cell by cell into the picture.
// trigger: 'hover' | 'scroll' | 'load' | 'manual'; pattern: 'center' | 'edges' | 'down' | 'up' | 'random'.
// The image needs a positioned parent and must be same-origin.
const r = AsciiBackdrop.reveal(document.querySelector('.hero img'), { trigger: 'scroll', pattern: 'edges' });
r.progress(0.5); // drive it yourself, 0–1

Both show the final state immediately under reduced motion.

Write a subject

const lighthouse = AsciiBackdrop.subjects.custom((ctx, t, s) => {
  // Draw around the origin, roughly inside [-s/2, s/2]. Brighter, more opaque white = denser output.
  ctx.fillRect(-s * 0.05, -s * 0.3, s * 0.1, s * 0.6);                    // tower
  AsciiBackdrop.helpers.softDot(ctx, 0, -s * 0.32, s * 0.12, 0.9);        // lamp
  ctx.save(); ctx.rotate(t * 0.8);                                          // beam
  ctx.globalAlpha *= 0.35; ctx.fillRect(0, -s * 0.33, s * 0.6, s * 0.03); ctx.restore();
});
const plasma = AsciiBackdrop.subjects.field((u, v, t) => 0.5 + 0.5 * Math.sin(10 * u + t) * Math.cos(8 * v - t));
  • Brightness is the whole language: use alpha, gradients and line width to decide where output is dense. A flat white area becomes a wall of filled boxes; give it a gradient or lower alpha.
  • Animate from t (seconds) and env only, never from the previous frame, so reduced motion, screenshots and recordings can sample any moment.
  • Keep lines at least about one cell wide (s * 0.015 or more), or they break into scattered dots.
  • Helpers: helpers.softDot(ctx, x, y, r, alpha) for soft glows; helpers.strand(ctx, points, w0, w1, a0, a1) for lines that taper and fade from root to tip.

Options

OptionDefaultMeaning
cell{w:9,h:15}Character cell size; larger is coarser and cheaper
rampRAMPS.denseGlyphs from sparse to dense
glyph{ edges:false, match:'ramp' }Edge glyphs and shape matching; edgeStrength sets edge sensitivity, contrast the shape-match contrast
braille{ threshold:0.35, dither:true }Dot threshold and Bayer dither
dither{ size:6, shape:'dot', levels:4 }Grid size, 'dot' or 'square', brightness levels
tile{ size:12, gap:2, radius:2, color:'source' }Tile size, gap, corner radius, colour source
pointerGlownull{ radius, strength }; needs interactive: true
crtnull{ scanlines, glow, vignette, flicker }; 0.15–0.35 reads well
cutoff / highlight0.06 / 0.9Below cutoff stays empty; above highlight prints a filled box
texture / shimmer0.3 / 0.12Brightness grain and glyph flicker; set 0 for a still poster
grid'lines'Background grid: 'lines', 'dots' or false
fps3030 is enough for a character backdrop

Out of scope

Character fluid simulation (needs per-frame state), morphing between two ASCII images, webcam input (needs device permission), and a WebGL shader build. Build those separately instead of growing this engine.

Gotchas

  • Cross-origin images taint the canvas and the engine cannot read pixels. Use same-origin, data: or blob: URLs, or a server that sends CORS headers. Pages opened from file:// treat local images as cross-origin too.
  • Keep CRT scanlines and flicker subtle; flicker is skipped under reduced motion. Do not put body text under the CRT finish.
  • Handled by the engine: high-DPI sharpness, resize, pausing in hidden tabs, and a single still frame under prefers-reduced-motion.
  • Keep the UI copy neutral; do not copy another product's name or interface text.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Use when a project uses agent-qa and the user asks to validate its YAML, run a selected regression test, or triage a failed/healed run with memidex evidence. For a general app feature inventory, use app-user-story-qa.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbook2882026年10月28日 更新

Audit and organize AI coding-agent instructions, including AGENTS.md, CLAUDE.md, skills, and agent definitions. Use when the user asks to diagnose conflicting instructions, excessive approval pauses, broad skill triggers, duplicate guidance, or broken instruction references, or to clean up that instruction set. Ordinary code review, Markdown editing, or application debugging alone does not trigger this workflow. Inspection stays read-only; apply changes when authorized.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbook2882026年10月28日 更新

Generate or update repository-specific AGENTS.md instruction files from real repo evidence. Use when asked to create, design, scaffold, split, or improve root or scoped AGENTS.md files for Codex/Claude/agent workflows, especially when a repo needs directory-specific rules, validation commands, generated-file boundaries, or a short agent onboarding router.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbook2882026年10月28日 更新

REST/GraphQL/gRPC API design best practices. Use when designing APIs, defining contracts, handling versioning. Covers OpenAPI 3.2, GraphQL Federation, gRPC streaming.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbook2882026年10月28日 更新

Mobile app UI design expert for iOS and Android. Use when designing app interfaces, creating design systems, ensuring accessibility, or following platform guidelines. Covers Material Design 3, Human Interface Guidelines, color theory, typography, and 2025 trends.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbook2882026年10月28日 更新

End-to-end app feature inventory and user-story testing workflow with a canonical tracker. Use when the user asks to audit every feature, derive expected behavior from code, test user journeys, or explicitly fix and retest documented UX or logistical defects.

日本語の概要は準備中です。原文の説明を表示しています。

majiayu000/spellbook2882026年10月28日 更新

majiayu000 のスキルをすべて見る

このスキルの問題を報告する