ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Claude Code 100个真实案例 - 用AI做像素画编辑器(图层+调色板+导出)

Claude Code 100个真实案例 - 用AI做像素画编辑器(图层+调色板+导出) 1. 为什么我要用 Claude Code 手搓一个像素画编辑器像素画编辑器这个需求看起来简单真动手写起来坑不少。图层要能叠加、调色板要能取色、导出 PNG 还得保证透明区域正确这三块任何一块没处理好整个工具就废了。我试过直接用现成的在线工具但要么图层数量受限要么导出带水印要么调色板不能自定义。于是决定用 Claude Code 从零搭一个纯前端的像素画编辑器单 HTML 文件双击就能跑。这篇文章聚焦三个核心模块图层管理、调色板取色、PNG 导出。我会给出可复制的 Claude Code 配置骨架把 TaoToken 的统一 Key 和 API 通道接进去然后逐模块验证新建图层叠加是否正常、调色板取色能否写入画布、导出图片校验像素是否对齐。适合有基础 JavaScript 认知、想用 AI 辅助写工具类应用的同学。整个项目不依赖任何构建工具浏览器打开就能用代码量控制在 400 行左右。先说清楚技术选型Canvas 2D 负责渲染二维数组存像素数据null表示透明颜色值用十六进制字符串。图层就是一个数组每个元素包含name、data、visible、opacity四个字段。调色板用 DOM 网格渲染取色器从所有可见图层中反向查找颜色。导出用离屏 Canvas 按倍数放大后toDataURL下载。这套结构足够简单也足够扩展。2. 前置准备把 TaoToken 接入 Claude Code在开始写代码之前需要先让 Claude Code 能正常调用模型。我用的方案是通过 TaoToken 的统一 API 通道接入这样不用在多个平台之间切换 Key配置一次就能长期用。TaoToken 的官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 注意 API 地址后面不加 UTM 参数。Claude Code 的配置文件通常在用户目录下的.claude/settings.json如果你用的是项目级配置就放在项目根目录的.claude/settings.json。下面是我实测可用的配置骨架把ANTHROPIC_BASE_URL指向 TaoToken 的 API 通道ANTHROPIC_AUTH_TOKEN填你在控制台生成的 Key{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-20250514 }, permissions: { allow: [ Read, Write, Bash(mkdir:*), Bash(open:*) ] } }配置完成后在终端执行claude --version确认版本正常然后claude进入交互模式。如果提示认证失败优先检查 Key 是否复制完整、API 地址是否多了斜杠。Key 的获取入口在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 生成后只显示一次记得及时保存。注意ANTHROPIC_MODEL字段填你实际可用的模型名不同账号权限可能不同。如果调用报模型不存在换成claude-sonnet-4-20250514或咨询控制台文档。接入完成后Claude Code 就能在项目目录里读写文件、执行命令。接下来创建项目目录mkdir -p pixel-editor cd pixel-editor3. 可复制配置图层、调色板、导出三大模块骨架3.1 图层管理的数据结构与渲染逻辑图层的核心是一个数组每个图层持有独立的像素数据。渲染时从底到顶依次绘制透明区域自然透出下层。下面是图层系统的关键代码可以直接放进script标签// 图层状态 let layers []; let activeLayerIndex 0; let pixelSize 16; let cellSize 25; // 创建空图层null 表示透明 function createLayer(name) { const data Array.from({ length: pixelSize }, () Array.from({ length: pixelSize }, () null) ); layers.push({ name, data, visible: true, opacity: 1 }); } // 添加图层并切换到新图层 function addLayer() { createLayer(图层 ${layers.length 1}); activeLayerIndex layers.length - 1; renderLayerList(); render(); } // 删除当前图层至少保留一个 function removeLayer() { if (layers.length 1) return; layers.splice(activeLayerIndex, 1); if (activeLayerIndex layers.length) { activeLayerIndex layers.length - 1; } saveHistory(); renderLayerList(); render(); } // 渲染主画布棋盘格背景 所有可见图层 function render() { const w pixelSize * cellSize; mainCanvas.width w; mainCanvas.height w; // 棋盘格表示透明区域 for (let y 0; y pixelSize; y) { for (let x 0; x pixelSize; x) { mainCtx.fillStyle (x y) % 2 0 ? #e0e0e0 : #c0c0c0; mainCtx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); } } // 从底到顶绘制图层 layers.forEach(layer { if (!layer.visible) return; mainCtx.globalAlpha layer.opacity; for (let y 0; y pixelSize; y) { for (let x 0; x pixelSize; x) { const color layer.data[y][x]; if (color) { mainCtx.fillStyle color; mainCtx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); } } } }); mainCtx.globalAlpha 1; renderPreview(); }图层列表的 UI 渲染用 DOM 动态生成每个图层项包含可见性切换、名称、上移下移按钮。点击图层项切换activeLayerIndex双击名称可以重命名。透明度用滑块控制范围 0 到 100映射到layer.opacity的 0 到 1。3.2 调色板取色与写入画布调色板用 30 个预设颜色铺成网格点击任意色块调用setColor更新当前颜色。取色器工具则从所有可见图层中反向查找鼠标位置的颜色找到后自动切回画笔工具。关键代码如下const DEFAULT_PALETTE [ #000000,#ffffff,#ff0000,#00ff00,#0000ff,#ffff00, #ff00ff,#00ffff,#ff8800,#88ff00,#0088ff,#ff0088, #884400,#448800,#004488,#880044,#888888,#cccccc, #ff6666,#66ff66,#6666ff,#ffcc66,#66ffcc,#cc66ff, #8b4513,#2e8b57,#4682b4,#b22222,#daa520,#556b2f ]; let currentColor #000000; let currentTool pen; function buildPalette() { const pal document.getElementById(palette); pal.innerHTML ; DEFAULT_PALETTE.forEach(color { const div document.createElement(div); div.className palette-color; div.style.background color; div.onclick () setColor(color); pal.appendChild(div); }); } function setColor(color) { currentColor color; document.getElementById(colorPicker).value color; document.getElementById(colorPreview).style.background color; } // 取色器从顶层到底层查找第一个非透明像素 function pickColor(px, py) { for (let i layers.length - 1; i 0; i--) { if (layers[i].visible layers[i].data[py][px]) { setColor(layers[i].data[py][px]); setTool(pen); return; } } }写入画布的逻辑在applyTool函数里根据当前工具类型分别处理画笔、橡皮擦、油漆桶和取色器。画笔直接赋值layer.data[py][px] currentColor橡皮擦赋null油漆桶用栈实现的洪水填充算法避免递归在大画布上栈溢出。3.3 PNG 导出与倍数放大导出模块创建一个离屏 Canvas尺寸是pixelSize * scale然后按 scale 倍数把每个像素画成scale × scale的矩形。最后用toDataURL(image/png)生成下载链接function exportPNG() { const scale parseInt(document.getElementById(exportScale).value); const expCanvas document.createElement(canvas); expCanvas.width pixelSize * scale; expCanvas.height pixelSize * scale; const expCtx expCanvas.getContext(2d); layers.forEach(layer { if (!layer.visible) return; expCtx.globalAlpha layer.opacity; for (let y 0; y pixelSize; y) { for (let x 0; x pixelSize; x) { if (layer.data[y][x]) { expCtx.fillStyle layer.data[y][x]; expCtx.fillRect(x * scale, y * scale, scale, scale); } } } }); const link document.createElement(a); link.download pixel-art-${pixelSize}x${pixelSize}-${scale}x.png; link.href expCanvas.toDataURL(image/png); link.click(); }导出倍数支持 1x 到 16x默认 4x。透明区域在导出时保持透明不会被棋盘格背景污染因为离屏 Canvas 初始就是透明的只绘制有颜色的像素。4. 逐模块验证图层叠加、取色写入、导出校验4.1 验证图层叠加打开index.html默认创建一个 16×16 画布和一个图层。点击「 添加」新建第二个图层此时图层列表显示两个条目。在第一个图层上画一个红色方块切换到第二个图层画一个蓝色方块覆盖部分红色区域。预期结果是蓝色方块在上层红色方块在下层重叠区域显示蓝色。如果重叠区域显示红色说明图层渲染顺序反了检查layers.forEach是否从索引 0 开始遍历。再测试可见性切换点击图层项左侧的眼睛图标隐藏上层图层红色方块应该重新显现。透明度滑块拉到 50%上层蓝色方块应该半透明能透出下层红色。这两个动作验证了图层叠加和透明度混合的正确性。4.2 验证调色板取色写入在画布上画几个不同颜色的像素切换到取色器工具快捷键 I点击任意已上色像素。预期结果是当前颜色更新为该像素颜色工具自动切回画笔。然后在空白区域点击应该用取到的颜色上色。如果取色后颜色没变检查pickColor是否从layers.length - 1开始倒序遍历以及是否判断了layer.visible。调色板点击测试点击任意色块左侧颜色预览框应该同步更新。用自定义颜色选择器选一个颜色再点击画布像素颜色应该与选择器一致。这一步验证了调色板取色和写入画布的完整链路。4.3 验证导出 PNG画一个简单图案选择导出倍数 4x点击「导出 PNG」。下载的文件名格式为pixel-art-16x16-4x.png用图片查看器打开检查像素边缘是否锐利、透明区域是否透明。如果导出图片模糊说明用了插值缩放检查是否设置了image-rendering: pixelated。如果透明区域变成白色说明离屏 Canvas 被填充了背景色检查导出逻辑是否只绘制了有颜色的像素。再测试 1x 导出文件尺寸应该是 16×16 像素。用取色工具检查导出图片的某个像素颜色应该与编辑器内一致。这一步验证了导出数据的准确性。5. 本篇常见错排查报错一mainCanvas is not defined。原因是脚本在 DOM 加载前执行。把script标签放在body末尾或者用DOMContentLoaded事件包裹初始化逻辑。报错二图层切换后画布不更新。检查activeLayerIndex是否在点击图层项时正确赋值以及renderLayerList是否重新渲染了列表。常见疏漏是点击事件里只改了索引没调用render()。报错三取色器取不到颜色。确认取色时点击的像素在当前可见图层上有颜色值。如果所有图层该位置都是null取色器不会改变当前颜色。另外检查pickColor的循环是否从顶层开始否则会取到底层的颜色。报错四导出 PNG 全黑或全透明。全黑通常是fillStyle没设置就调用了fillRect全透明是循环条件写错导致没绘制任何像素。在导出函数里加console.log打印每个像素的颜色值确认数据源正确。报错五Claude Code 调用模型返回 401。检查settings.json里的ANTHROPIC_AUTH_TOKEN是否与 TaoToken 控制台生成的 Key 一致以及ANTHROPIC_BASE_URL是否填的https://taotoken.net/api。如果 Key 没问题确认账号是否有对应模型的调用权限。报错六洪水填充导致页面卡死。大画布上用递归实现洪水填充会栈溢出。改用栈或队列的迭代版本代码里已经用stack数组实现如果还卡检查visited集合是否正确去重。6. 继续用 Claude Code 扩展你的编辑器到这里图层、调色板、导出三个模块已经跑通。你可以继续用 Claude Code 加功能比如图层拖拽排序、导出 GIF 动画、导入图片转像素画。每次加功能前先让 Claude Code 读一遍现有代码再描述需求它能基于当前结构给出增量修改避免重写整个文件。如果你在接入或排障过程中遇到问题优先检查 API Keys 配置和接入文档https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先验证模型对话是否正常可以用模型对话入口https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。长期做编码和 Agent 类项目的话Coding Plan 更适合https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后留一个实用技巧把settings.json里的permissions.allow加上Bash(open:*)这样 Claude Code 生成完代码后可以直接帮你打开浏览器预览省去手动切换窗口的步骤。
返回列表