两小时做出会发光的网页灯牌:NeonCraft 全程拆解
1. 为什么你会想读这篇文章?
-
“我想给直播加一个炫酷的霓虹标题,但不想学 After Effects。” -
“我只会一点前端,两小时能跑起来吗?” -
“如果我想改颜色、加手绘图案、让文字呼吸闪烁,该怎么做?”
本文把官方 README 里密密麻麻的技术点拆成大白话,并给出可复制粘贴的代码片段、踩坑提醒和常见疑问解答。读完你就能:
-
在本地跑起一个可编辑、可全屏展示的 NeonCraft 网页。 -
知道每个按钮背后调用了 Konva 的哪一行 API。 -
快速改动颜色、动画速度,甚至换字体。
2. NeonCraft 是什么?
一句话:浏览器里的“数字霓虹招牌编辑器”。
-
编辑模式:像 Figma 一样拖文字、随手画形状,调颜色、发光、线宽。 -
展示模式:一键全屏,循环呼吸或闪烁,像夜店里真正的霓虹灯。 -
技术底线:纯前端,React + Konva + Zustand,不依赖后端。
3. 2 小时落地路线图(官方计划口语化)
时间段 | 你实际做的事 | 关键产出 |
---|---|---|
0 ~ 15 min | 跑通脚手架 | 空画布出现 |
15 ~ 45 min | 能加文字、能拖拽、能改颜色 | 第一个“NEON”字样 |
45 ~ 75 min | 能随手画曲线 | 一条发光的“闪电” |
75 ~ 90 min | 刷新网页不丢数据 | localStorage 自动保存 |
90 ~ 105 min | 点击“展示”全屏播放 | 呼吸动画跑起来 |
105 ~ 120 min | 修细节:默认深色背景、示例灯牌 | 可发朋友圈的 Demo |
4. 安装与启动(3 条命令)
前提:电脑已装 Node ≥ 16。
# 1. 拉源码
git clone <repo-url>
cd neoncraft
# 2. 装依赖
npm install
# 3. 跑起来
npm run dev
浏览器自动打开 http://localhost:5173
,看到黑色画布就成功。
5. 技术选型为什么这样组合?
工具 | 作用 | 不选它的理由 |
---|---|---|
React + Vite | 最快的热更新,2 小时够用 | 用 Vue 也行,但社区示例少 |
Konva + react-konva | Canvas 2D 库,发光效果一行配置 shadowBlur 搞定 |
Fabric 更重,PixiJS 需要 WebGL |
Zustand | 10 行代码写完全局状态,比 Redux 轻 | useReducer 样板太多 |
localStorage | 免后端,刷新不丢图 | 多人协作时再考虑云端 |
6. 数据模型:一张图看懂
// 伪代码,真实文件在 src/types.ts
interface Scene {
name: string; // 灯牌名称
width: 1280; height: 720; // 画布大小
background: { color: '#0B0F1A' };
global: {
brightness: 1; // 全局亮度
animation: 'breathe'; // 呼吸 or 闪烁
};
nodes: Array<TextNode | PathNode>;
}
-
每个节点有唯一 id
,方便选中、删除、改层级。 -
glow.blur
越大,光晕越虚;intensity
决定透明度。
7. 编辑模式:从 0 到可交互
7.1 添加文字
// store/scene.ts
addText() {
const newText: TextNode = {
id: crypto.randomUUID(),
type: 'text',
text: 'NEON',
x: 460, y: 260,
stroke: '#00F0FF',
strokeWidth: 10,
fontSize: 120,
glow: { enabled: true, blur: 40, intensity: 0.9 }
};
set(state => ({ nodes: [...state.nodes, newText] }));
}
-
画布上点一下即可出现默认文字。 -
右侧属性面板实时联动:改 stroke
立即变色,改fontSize
立即放大。
7.2 手绘形状
startDraw() {
isDrawing = true;
currentPath = [];
}
pushPoint(x, y) {
if (isDrawing) currentPath.push(x, y);
}
endDraw() {
const path: PathNode = {
id: crypto.randomUUID(),
type: 'path',
points: [...currentPath],
tension: 0.5, // 让线条平滑
closed: false,
stroke: '#FF00FF',
strokeWidth: 8,
glow: { enabled: true, blur: 30, intensity: 0.8 }
};
addNode(path);
}
-
鼠标按下拖动即可画线,松开自动生成节点。 -
Konva 的 Line
组件用tension
一键曲线平滑,不需要贝塞尔数学。
7.3 选中与变形
-
点击元素 → selectedId
更新 →Konva.Transformer
出现 8 个控点。 -
拖拽、旋转、缩放都是 Konva 内建,不用再算矩阵。
8. 展示模式:三步让灯牌动起来
-
路由切到 /play
,关闭工具栏。 -
全屏 API: document.documentElement.requestFullscreen()
。 -
动画循环(requestAnimationFrame):
// Player.tsx
function animate() {
const t = (Math.sin(Date.now() * speed) + 1) / 2; // 0~1
const brightness = 0.8 + t * 0.4; // 0.8~1.2
stageRef.current.container().style.filter =
`brightness(${brightness}) hue-rotate(${global.hueRotate}deg)`;
requestAnimationFrame(animate);
}
-
闪烁效果把 t
换成随机噪声即可。 -
全局色相滑杆实时映射到 CSS hue-rotate()
,无需逐节点改颜色。
9. 保存与加载:localStorage 一行代码
// 自动保存,防抖 500 ms
useEffect(() => {
const debounce = setTimeout(() => {
localStorage.setItem('neoncraft:scene', JSON.stringify(scene));
}, 500);
return () => clearTimeout(debounce);
}, [scene]);
// 首次加载
const saved = localStorage.getItem('neoncraft:scene');
if (saved) setScene(JSON.parse(saved));
10. 常见问题 FAQ
Q1:我想换中文字体怎么办?
在 TextNode
里加 fontFamily: 'Noto Sans SC'
,确保网页提前加载对应 Google Font。
Q2:画布太大手机卡?
把 width/height
设成 720p,限制 shadowBlur < 60
,Konva 会自动做像素裁剪。
Q3:如何导出 PNG?
const dataURL = stageRef.current.toDataURL({ pixelRatio: 2 });
const link = document.createElement('a');
link.download = 'my-neon.png';
link.href = dataURL;
link.click();
Q4:能接入物理 LED 灯带吗?
官方 README 把硬件联动列为“范围外”。思路:把 Scene
序列化后通过 WebSocket 发到树莓派,再用 Python 解析坐标映射到 WS2812B 像素。
Q5:Zustand 不会用怎么办?
把 store/scene.ts
换成 React useReducer
,数据结构保持不变,只是样板多几行。
11. 默认示例数据速查
直接复制到 localStorage
的 neoncraft:scene
键即可恢复官方 Demo:
{
"id": "demo-1",
"name": "NeonCraft Demo",
"width": 1280,
"height": 720,
"background": { "color": "#0B0F1A" },
"global": { "brightness": 1, "hueRotate": 0, "animation": "breathe", "animSpeed": 0.6 },
"nodes": [
{
"id": "t1",
"type": "text",
"text": "NEON",
"x": 460, "y": 260,
"stroke": "#00F0FF", "strokeWidth": 10,
"glow": { "enabled": true, "blur": 40, "intensity": 0.9 },
"fontSize": 120
}
]
}
12. 结语:两小时只是起点
NeonCraft 的 MVP 用“最小可用”证明了浏览器也能做出专业级霓虹效果。下一步你可以:
-
加“导出 GIF”按钮,把动画录下来做短视频片头。 -
做模板市场,把 Scene
存云端,别人一键复刻。 -
用 Web Audio API 把麦克风音量映射到 brightness
,实现音乐律动。
把这篇文章收藏,下次黑客松开场前 10 分钟,你就能自信地说:“给我两小时,现场做一块会发光的灯牌。”