Ascii Art
將圖片轉為可動畫的 ASCII/像素藝術。
把任何圖片(或文字/emoji)即時降採樣成 ASCII 字元或像素色塊,並以打散、波動或掃描動畫進場。全程 canvas 2D 繪製,尊重「減少動態效果」。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add ascii-artASCII Art 是用 React 與 canvas 2D 做的圖片轉 ASCII 字元畫(ASCII art generator、文字藝術)元件:把圖片或一段文字降採樣成字元格,依亮度換成不同密度的字元,也能改成彩色像素色塊,並提供打散、波浪與對角揭露三種動畫。Motion 只用來讀取「減少動態效果」設定。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<AsciiArt/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
適用情境
- 開發者工具、CLI 產品或終端機風格網站的主視覺
- 404 或維護頁面,用大字「404」做成會動的字元畫
- 黑客松、技術活動頁的 Logo 或講者頭像
- 作品集裡偏實驗性、復古電腦風格的區塊
安裝
npx webberui@latest add https://webberui.com/r/ascii-art.json或在 components.json 設定 registries 後,改用 @webberui/ascii-art 安裝。
使用
以 src 傳入圖片(建議用 data: URI 保持元件自足),或改用 text 把文字/emoji 當作來源圖形。
import { AsciiArt } from "@/components/ui/ascii-art";
<AsciiArt src="/portrait.png" columns={90} animation="scramble" loop />
<AsciiArt text="★" mode="pixel" animation="reveal" />提示:
columns是水平字元欄數,數字越大越精細也越吃效能。跨來源(cross-origin)圖片若未帶 CORS 標頭會污染 canvas 而無法取樣,改用同源資源或data:URI 最穩。
範例
404 頁面
沒有傳 src 時,text 的內容會先畫成粗體大字再轉成字元;wave 動畫會持續播放。
import { AsciiArt } from "@/components/ui/ascii-art";
export default function NotFound() {
return (
<main className="grid min-h-[60vh] place-items-center gap-6 text-emerald-500">
<AsciiArt text="404" alt="404 找不到頁面" columns={80} animation="wave" />
<p className="text-neutral-500">這個頁面不存在或已經移除。</p>
</main>
);
}color 沒指定時會讀取畫布的 currentColor,所以外層的 text-emerald-500 就決定了字色。
像素模式的 Logo 揭露
mode="pixel" 會保留圖片原本的顏色,以方形色塊輸出;reveal 會從左上往右下依對角線掃出畫面。
<AsciiArt
src="/brand/logo.png"
alt="公司 Logo"
mode="pixel"
animation="reveal"
columns={48}
fontSize={6}
background="#0a0a0a"
/>自訂字元梯度與亮色背景
chars 由暗到亮排列。在白底頁面上,深色的主體應該用較密的字元,這時加上 invert 反轉亮度對應。
<AsciiArt
src="/team/avatar.jpg"
alt="講者頭像"
chars=" ░▒▓█"
invert
columns={64}
animation="scramble"
speed={0.8}
className="text-neutral-900"
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
src | string | — | 來源圖片 URL 或 data: URI |
text | string | "★" | 無 src 時,改把這段文字/emoji 當來源圖形 |
alt | string | — | 給輔助科技的替代文字 |
columns | number | 72 | 水平解析度(字元欄數) |
chars | string | " .:-=+*#%@" | 由暗到亮的字元梯度,至少兩個字元 |
color | string | currentColor | ascii 模式的文字顏色 |
background | string | "transparent" | 底色 |
mode | "ascii" | "pixel" | "ascii" | 輸出字元或色塊像素 |
animation | "scramble" | "wave" | "reveal" | "none" | "scramble" | 動畫模式 |
speed | number | 1 | 動畫速度倍率 |
fontSize | number | 9 | 單一單元的像素高度(ascii 為字級) |
invert | boolean | false | 反轉亮度對應 |
loop | boolean | false | 動畫結束後是否持續循環 |
可及性
- 使用者系統開啟「減少動態效果」時,直接繪製最終靜態畫面,不播放動畫
- 畫布帶
role="img"與aria-label,朗讀時回報替代文字而非逐格字元
常見問題
輸出的尺寸怎麼算?
畫布寬度由 columns 和 fontSize 決定:ascii 模式每格寬約 fontSize × 0.6 px,pixel 模式每格是 fontSize 的正方形;列數依來源圖片比例自動算出。外層加了 max-w-full,不會超出容器寬度。
為什麼圖片沒有顯示?
元件需要讀取像素資料。跨來源圖片若伺服器沒有回傳 CORS 標頭,canvas 會被污染而無法取樣,元件會靜默略過。改用同源路徑或 data: URI 最穩。
長時間放在頁面上會一直耗效能嗎?
scramble 與 reveal 在動畫結束後就停止繪製(除非設 loop);wave 與 loop 會持續執行,但捲出畫面時會由 IntersectionObserver 暫停 requestAnimationFrame。columns 越大,每一幀要畫的字元越多。
切換深淺主題時字色會跟著變嗎?
預設字色是在元件繪製時讀取一次 currentColor,主題切換後若元件沒有重新渲染,字色不會更新。需要明確的配色時,直接傳 color。
可以在 Next.js App Router 使用嗎?
可以。原始碼已經有 "use client",圖片載入與繪製都在 effect 內執行,伺服器端只輸出一個空的 canvas。依賴是 motion、clsx、tailwind-merge,也可以從「手動」分頁直接複製原始碼。