十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

用Skill生成Three.js 3D特效网页:从粒子星云到工程实践

用Skill生成Three.js 3D特效网页:从粒子星云到工程实践 一个 Skill做出 3D 特效网页太炫酷了从 Skill 编写到 Three.js 粒子星云落地最近在折腾 AI 编程工具时发现一个特别有意思的玩法不用手写一大堆 Three.js 代码也不用反复调整相机参数和粒子颜色只需要让 AI 助手加载一个专门写好的Skill然后描述“我要一个星空粒子特效”它就能自动生成一个可以直接运行的 3D 网页。一开始我还以为这是某种“提示词魔法”但真正动手拆解之后才发现Skill的本质是一套结构化的规则文件 可复用的工具脚本它把平时我们写 3D 页面时反复踩坑的那些经验——场景初始化、相机位置、粒子动画、鼠标交互、CDN 引入方式——全部固化成了标准流程。本文就从零开始带着大家完整做一遍先搞清楚Skill是什么再编写一个专门生成 3D 特效网页的Skill最后用这个Skill生成一个基于 Three.js 的粒子星云动态页面。整个流程我会把每个文件、每段代码、每条命令都贴出来并解释关键参数的作用保证你照着操作就能跑起来。如果你之前对Skill和 3D 网页开发都只是听说过这篇教程应该能帮你把两边串起来。1. 背景与核心概念1.1 什么是“Skill”它和普通提示词有什么区别Skill可以理解为给 AI 编程助手准备的一套“岗位说明书 工具包”。它通常包含一个描述文件比如SKILL.md里面写清楚这个 Skill 的适用场景、输出规范、工作步骤和注意事项同时还可以附带一些可执行的脚本、模板文件或参考代码放在resources目录下。普通提示词的问题是“一次性”你每次都要重新告诉 AI 要做什么、不要做什么、输出格式是什么遇到复杂任务时AI 很容易在前几步就偏离方向。而Skill把这些上下文固化下来AI 一旦检测到用户需求匹配某个 Skill就会自动加载对应的规则和资源直接按照里面定义好的流程执行。对于 3D 网页这种“步骤固定、但要写的东西很多”的任务来说Skill的价值非常明显流程标准化、输出可预期、代码质量稳定。最近 GitHub 和各大 AI 编程工具中skill、agent skill、codex skill这些词的热度一路走高本质上就是因为大家发现与其每次让 AI “自由发挥”不如先用Skill把最佳实践沉淀下来。你可以把Skill理解成 AI 世界的“插件”而本文要实现的就是一个专门生成 3D 特效网页的插件。1.2 为什么用 Three.js 做 3D 特效网页Three.js 是目前 Web 端最流行的 3D 渲染库它基于 WebGL但把底层复杂的着色器、矩阵运算、缓冲区管理封装成了相对友好的 JavaScript API。我们不需要了解 GPU 管线细节就能用Scene、Camera、Mesh、Points这些对象搭建一个可交互的 3D 场景。常见的 3D 特效网页比如粒子星云、动态文字、产品 3D 展示、数据可视化大屏等使用 Three.js 都能在浏览器里直接运行。相比 C4D 或 Blender 导出的静态视频Three.js 做出来的页面是实时渲染的用户拖拽鼠标时画面会实时变化这种沉浸感特别适合活动页面、个人主页、产品介绍页。本文的实战部分会做一个粒子星云效果几千个粒子在空间中缓慢旋转鼠标移动时视角和粒子运动方向会发生变化视觉上像一片动态的星空。这个效果在 3D 特效网页里很常见但涉及的 API 覆盖了BufferGeometry、PointsMaterial、requestAnimationFrame、raycaster周边的基础用法很适合作为入门到进阶的过渡案例。1.3 一个 Skill 解决 3D 特效网页的完整链路我们用Skill生成 3D 网页本质上是要建立一条从“用户描述”到“可运行代码”的流水线。用户只需要说“我想要一个紫色调的 3D 粒子星空”Skill内部就会完成下面这些事解析场景类型识别是粒子效果、几何体动画还是文字特效。确定技术方案默认使用 Three.js可选 CDN 方式或 Vite 工程方式。生成完整代码包括 HTML 结构、Three.js 场景初始化、粒子系统、动画循环、鼠标交互。输出运行指引告诉用户如何启动本地服务器、如何修改参数。听起来很神奇但实现起来并不复杂核心就是一个写得很规范的SKILL.md文件加上一个生成脚本。下面我们就动手开始做。2. 环境准备与版本说明这个项目不依赖重型环境主要用到 Node.js 和现代浏览器。建议环境如下操作系统Windows 10/11、macOS、Linux 均可本文命令以 macOS/Linux 终端为主Windows 可改用 PowerShell 或 Git Bash。Node.js建议 18 或更高版本。本文的脚本使用 ESM 语法低版本 Node 需要调整。浏览器Chrome、Edge 或 Firefox 最新版用于预览 3D 页面。AI 编程工具支持 Skill 的 Claude Code、Cursor、Windsurf 等。本文以通用 Skill 规范为例如果你使用的工具目录结构不同可以按对应工具的官方文档调整。如果 Node.js 版本较低可以先升级或者把脚本中的 ESM 语法改为 CommonJS。本文示例以常见环境为例重点演示配置思路版本需要根据你的项目实际情况调整。先建一个总目录所有文件都放在里面mkdir skill-3d-web cd skill-3d-web后续所有路径都基于这个skill-3d-web目录展开。3. 编写一个生成 3D 特效网页的 Skill3.1 Skill 的目录结构一个标准的 Skill 通常由两部分组成描述文件SKILL.md和资源目录resources。我们还需要一个output目录来存放生成的网页。整体结构如下skill-3d-web/ ├── README.md ├── skill/ │ ├── SKILL.md │ └── resources/ │ └── generate-3d-scene.mjs └── output/说明SKILL.md是 AI 助手加载这个 Skill 时需要阅读的核心文件resources目录存放生成网页时可能用到的脚本和模板output是脚本生成的网页输出目录。3.2 编写 SKILL.mdSKILL.md的作用是告诉 AI 助手什么时候使用这个 Skill使用时的步骤是什么生成的结果应该满足什么要求。一个有效的SKILL.md不需要写很长但一定要把关键规则写清楚尤其是“输出物必须能直接运行”这条。下面是完整的skill/SKILL.md内容--- name: 3d-scene-generator description: 当用户要求生成 3D 特效网页、3D 粒子效果、3D 交互页面或 Three.js 场景时使用该 Skill。也可用于生成活动页、个人主页、产品展示页中的 3D 视觉模块。 --- # 3D 场景生成 Skill ## 适用场景 - 用户想要一个 3D 粒子星空、粒子漩涡、动态几何体页面 - 用户想要一个带鼠标交互的 3D 网页 - 用户想要一个基于 Three.js 的单页面 3D 特效 ## 输出要求 1. 默认生成两个文件index.html 和 main.js 2. 使用 Three.js优先通过 CDN 方式引入版本使用 0.160.0 以上 3. 页面必须包含 - 一个自动旋转或缓动的 3D 场景 - 粒子系统或几何体对象 - 鼠标移动交互 - 窗口尺寸变化的响应处理 4. 代码必须完整可运行不能使用“省略”“...” 5. 生成后给出启动本地服务器的命令 ## 工作步骤 1. 询问或推断用户的 3D 场景主题粒子星空、粒子漩涡、几何体动画 2. 询问主色调默认使用蓝紫色渐变 3. 运行 resources/generate-3d-scene.mjs 脚本生成网页文件 4. 检查生成结果确认没有缺少文件 5. 输出运行说明这个文件的核心是「输出要求」和「工作步骤」两部分。输出要求定义了代码质量底线工作步骤则约束了 AI 的行为顺序避免 AI 不问需求就直接写一堆用户不需要的代码。3.3 编写生成脚本generate-3d-scene.mjs是一个 Node.js 脚本作用是根据用户传入的主题和颜色自动生成一套完整的 3D 网页。这个脚本的初衷是让 AI 在执行 Skill 时有一个稳定的“生成器”而不是每次都在对话里随机拼接代码。脚本代码如下// 文件路径skill/resources/generate-3d-scene.mjs import fs from node:fs; import path from node:path; const args process.argv.slice(2); const sceneType args[0] || particle-star; const title args[1] || 3D Star Field; const colorHex args[2] || #7c5cff; const outputDir path.resolve(output, 3d-scene); fs.mkdirSync(outputDir, { recursive: true }); const html !DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title${title}/title style * { margin: 0; padding: 0; } body { overflow: hidden; background: #050510; } canvas { display: block; } #info { position: fixed; top: 20px; left: 20px; color: rgba(255,255,255,0.8); font-family: PingFang SC, Microsoft YaHei, sans-serif; font-size: 14px; pointer-events: none; z-index: 10; } /style /head body div idinfo${title} · 移动鼠标交互/div script typemodule src./main.js/script /body /html ; fs.writeFileSync(path.join(outputDir, index.html), html, utf-8); let mainJs ; if (sceneType particle-star) { mainJs import * as THREE from https://unpkg.com/three0.160.0/build/three.module.js; const scene new THREE.Scene(); scene.background new THREE.Color(0x050510); const camera new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 1.5, 6); camera.lookAt(0, 0, 0); const renderer new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.body.appendChild(renderer.domElement); const particleCount 2600; const positions new Float32Array(particleCount * 3); const velocities new Float32Array(particleCount); for (let i 0; i particleCount; i) { const radius 2.5 Math.random() * 3; const theta Math.random() * Math.PI * 2; const phi Math.acos(2 * Math.random() - 1); positions[i * 3] radius * Math.sin(phi) * Math.cos(theta); positions[i * 3 1] radius * Math.sin(phi) * Math.sin(theta) * 0.6; positions[i * 3 2] radius * Math.cos(phi); velocities[i] 0.005 Math.random() * 0.01; } const geometry new THREE.BufferGeometry(); geometry.setAttribute(position, new THREE.BufferAttribute(positions, 3)); const material new THREE.PointsMaterial({ color: ${JSON.stringify(colorHex)}, size: 0.035, transparent: true, opacity: 0.9, blending: THREE.AdditiveBlending, depthWrite: false }); const points new THREE.Points(geometry, material); scene.add(points); let mouseX 0; let mouseY 0; window.addEventListener(mousemove, (e) { mouseX (e.clientX / window.innerWidth) * 2 - 1; mouseY -(e.clientY / window.innerHeight) * 2 1; }); function animate() { requestAnimationFrame(animate); const time performance.now() * 0.001; const pos geometry.attributes.position.array; for (let i 0; i particleCount; i) { const idx i * 3; const angle velocities[i] * time; const x pos[idx]; const z pos[idx 2]; pos[idx] x * Math.cos(angle) - z * Math.sin(angle); pos[idx 2] x * Math.sin(angle) z * Math.cos(angle); } geometry.attributes.position.needsUpdate true; points.rotation.y 0.0008; points.rotation.x mouseY * 0.2; camera.position.x (mouseX * 1.2 - camera.position.x) * 0.05; camera.lookAt(0, 0, 0); renderer.render(scene, camera); } animate(); window.addEventListener(resize, () { camera.aspect window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); ; } else if (sceneType particle-vortex) { mainJs import * as THREE from https://unpkg.com/three0.160.0/build/three.module.js; const scene new THREE.Scene(); scene.background new THREE.Color(0x080818); const camera new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 3, 8); camera.lookAt(0, 0, 0); const renderer new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.body.appendChild(renderer.domElement); const particleCount 4000; const positions new Float32Array(particleCount * 3); const speeds new Float32Array(particleCount); for (let i 0; i particleCount; i) { const angle Math.random() * Math.PI * 2; const radius Math.random() * 4; positions[i * 3] Math.cos(angle) * radius; positions[i * 3 1] (Math.random() - 0.5) * 5; positions[i * 3 2] Math.sin(angle) * radius; speeds[i] 0.02 Math.random() * 0.04; } const geometry new THREE.BufferGeometry(); geometry.setAttribute(position, new THREE.BufferAttribute(positions, 3)); const material new THREE.PointsMaterial({ color: ${JSON.stringify(colorHex)}, size: 0.03, transparent: true, opacity: 0.85, blending: THREE.AdditiveBlending, depthWrite: false }); const points new THREE.Points(geometry, material); scene.add(points); let mouseX 0; let mouseY 0; window.addEventListener(mousemove, (e) { mouseX (e.clientX / window.innerWidth) * 2 - 1; mouseY -(e.clientY / window.innerHeight) * 2 1; }); function animate() { requestAnimationFrame(animate); const time performance.now() * 0.001; const pos geometry.attributes.position.array; for (let i 0; i particleCount; i) { const idx i * 3; const currentAngle Math.atan2(pos[idx 2], pos[idx]); const r Math.sqrt(pos[idx] * pos[idx] pos[idx 2] * pos[idx 2]); const nextAngle currentAngle speeds[i] * 0.01; pos[idx] Math.cos(nextAngle) * r; pos[idx 2] Math.sin(nextAngle) * r; } geometry.attributes.position.needsUpdate true; points.rotation.y time * 0.1; camera.position.x (mouseX * 2 - camera.position.x) * 0.04; camera.position.y (mouseY * 2 - camera.position.y) * 0.04; camera.lookAt(0, 0, 0); renderer.render(scene, camera); } animate(); window.addEventListener(resize, () { camera.aspect window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); ; } fs.writeFileSync(path.join(outputDir, main.js), mainJs, utf-8); console.log(生成完成); console.log(输出目录:, path.resolve(outputDir)); console.log(启动方式: cd output/3d-scene npx serve . 或 python3 -m http.server 8080);这个脚本涵盖了两种场景particle-star粒子星空和particle-vortex粒子漩涡。你可以按需扩展更多场景例如text-3d、mesh-wave等。脚本里有几个关键点需要特别说明使用 CDN 方式引入 Three.js。这里用的是unpkg上的 ESM 模块地址配合script typemodule可以在不安装 npm 依赖的情况下直接在浏览器运行。对于演示项目和活动页面来说非常方便如果要做生产级项目建议改用 npm 安装并配合 Vite 打包。粒子位置使用 BufferGeometry 的 Float32Array。直接操作positions数组并设置needsUpdate true是 Three.js 中做粒子动画的标准做法性能远高于每帧重新创建几何体对象。动画循环与鼠标交互。requestAnimationFrame是浏览器动画的标准驱动方式鼠标位置先归一化到-1到1再通过一个缓动系数例如0.05控制相机位置就能做出平滑跟随效果而不是生硬地跳变。3.4 添加 README.md在项目根目录放一个README.md方便以后使用和分享# Skill 生成 3D 特效网页 这是一个演示项目通过自定义 Skill 生成基于 Three.js 的 3D 特效网页。 ## 使用方法 1. 将 skill 目录放入你的 AI 工具 Skill 目录。 2. 在 AI 对话中描述你想要的 3D 网页。 3. AI 会调用 skill/resources/generate-3d-scene.mjs 生成页面。 4. 进入 output/3d-scene 目录启动本地服务器查看效果。 ## 手动运行脚本 直接执行 bash node skill/resources/generate-3d-scene.mjs particle-star My 3D Star #7c5cff4. 用 Skill 生成并运行 3D 特效网页4.1 模拟 AI 执行 Skill 的过程如果你想先手动测试脚本不需要真的打开 AI 工具直接在终端执行node skill/resources/generate-3d-scene.mjs particle-star My 3D Star #7c5cff执行成功后终端会输出生成完成 输出目录: /你的路径/skill-3d-web/output/3d-scene 启动方式: cd output/3d-scene npx serve . 或 python3 -m http.server 8080这时output/3d-scene目录下会多出index.html和main.js两个文件目录结构如下output/3d-scene/ ├── index.html └── main.js这里要注意因为main.js里使用import * as THREE from https://unpkg.com/...属于 ES Module直接用file://协议打开index.html会碰到跨域限制必须在本地启动一个静态服务器来访问。4.2 启动本地服务器常用的启动方式有两种。第一种使用 Node.js 的npx servecd output/3d-scene npx serve .第二种使用 Python 自带的 HTTP 服务器cd output/3d-scene python3 -m http.server 8080启动后浏览器访问http://localhost:8080就能看到 3D 粒子星空页面。移动鼠标时画面会随着鼠标位置产生视角偏移粒子本身会缓慢旋转视觉上像是漂浮在深邃宇宙中的星云。4.3 生成的网页代码解读为了方便你在没有脚本的情况下也能理解页面逻辑这里贴出main.js的核心片段并逐段解释。场景、相机、渲染器初始化const scene new THREE.Scene(); scene.background new THREE.Color(0x050510); const camera new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 1.5, 6); camera.lookAt(0, 0, 0); const renderer new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.body.appendChild(renderer.domElement);PerspectiveCamera是透视相机第一个参数是视野角度75值越大看到的范围越大第二个参数是宽高比第三、四个参数是近裁剪面和远裁剪面。antialias: true开启抗锯齿避免粒子边缘出现明显锯齿。生成粒子位置const particleCount 2600; const positions new Float32Array(particleCount * 3); const velocities new Float32Array(particleCount); for (let i 0; i particleCount; i) { const radius 2.5 Math.random() * 3; const theta Math.random() * Math.PI * 2; const phi Math.acos(2 * Math.random() - 1); positions[i * 3] radius * Math.sin(phi) * Math.cos(theta); positions[i * 3 1] radius * Math.sin(phi) * Math.sin(theta) * 0.6; positions[i * 3 2] radius * Math.cos(phi); velocities[i] 0.005 Math.random() * 0.01; }这里把 2600 个粒子分布在半径2.5到5.5的球壳上。Math.acos(2 * Math.random() - 1)是生成球面上均匀分布点的标准写法避免粒子聚集在球体两极。Y 轴方向乘以0.6是为了把球体在高度上压扁一点让整体更接近星云的扁平形状。动画循环const time performance.now() * 0.001; const pos geometry.attributes.position.array; for (let i 0; i particleCount; i) { const idx i * 3; const angle velocities[i] * time; const x pos[idx]; const z pos[idx 2]; pos[idx] x * Math.cos(angle) - z * Math.sin(angle); pos[idx 2] x * Math.sin(angle) z * Math.cos(angle); } geometry.attributes.position.needsUpdate true;这里的time是当前时间秒每个粒子按自己的velocity围绕 Y 轴旋转。把x和z先取出来再用旋转公式写入新值可以避免在计算过程中使用被覆盖过的数据。如果不设置needsUpdate trueThree.js 不会重新上传顶点数据画面就会静止不动。鼠标交互与相机缓动let mouseX 0; let mouseY 0; window.addEventListener(mousemove, (e) { mouseX (e.clientX / window.innerWidth) * 2 - 1; mouseY -(e.clientY / window.innerHeight) * 2 1; }); camera.position.x (mouseX * 1.2 - camera.position.x) * 0.05; camera.lookAt(0, 0, 0);mouseX和mouseY的范围是-1到1。每帧让相机位置向目标位置靠近5%这是一种非常经典的缓动写法。如果直接让相机位置等于鼠标位置画面会显得很生硬用这种“每帧逼近一部分”的方式移动会变得平滑自然这也是很多 3D 交互页面的细节所在。5. 常见问题与排查思路在跑 3D 网页的过程中大家容易在几个地方卡住。下面用表格整理一下高频问题问题现象常见原因解决思路浏览器打开index.html后画面全黑使用 ES Module 加载外部 CDNfile://协议被浏览器拦截启动本地静态服务器例如npx serve .或python3 -m http.server 8080控制台报错Failed to fetch dynamically imported moduleunpkg 地址无法访问或网络环境不稳更换为cdn.jsdelivr.net/npm/three0.160.0/build/three.module.js或其他可用镜像粒子不运动只显示静态球体忘记设置geometry.attributes.position.needsUpdate true在每次修改Float32Array的顶点数据后将needsUpdate置为true鼠标移动时画面卡顿严重粒子数量过多或使用低端设备时devicePixelRatio过高降低particleCount或将renderer.setPixelRatio的值限制为1页面在手机端显示不全没有适配窗口尺寸变化添加resize事件监听更新相机宽高比和渲染器尺寸场景中粒子颜色不是想要的PointsMaterial的color设置为0xffffff时粒子不会发光使用带透明度和AdditiveBlending的材质如示例中的color: #7c5cff如果遇到启动失败还可以按下面的顺序排查确认当前目录是否正确。终端中的路径需要在output/3d-scene目录下。确认 Node.js 版本。脚本使用的是 ESM 语法Node 18 及以上一般没问题。确认浏览器没有禁用本地服务器端口。如果8080被占用换一个端口试试。在浏览器控制台查看报错信息。大多数问题时控制台都会给出具体提示。6. 最佳实践与工程建议6.1 Skill 设计建议写Skill不只是把需求描述写长一点而是要把“稳定产出”作为目标。这里有几个经验可以分享。明确输出物清单。在SKILL.md里写清楚“生成哪些文件、必须包含哪几块内容”能有效避免 AI 在生成过程中偷懒或漏掉关键部分。比如本文就要求页面必须包含自动旋转、粒子系统、鼠标交互、窗口响应少任何一个都不合格。把可复用脚本和描述文件分离。如果生成逻辑很复杂不要全都塞进SKILL.md。把核心生成器放在resources目录下SKILL.md只描述“何时调用、怎么调用、结果格式是什么”。这样既方便调试也方便其他 Skill 复用同一个生成器。参数设计要收敛。生成脚本目前只接收三个参数场景类型、标题、颜色。参数越少越不容易出错。以后要扩展时建议通过配置文件而不是不断增加命令行参数来管理。6.2 Three.js 网页开发建议优先使用 CDN 或构建工具。个人演示项目适合用 CDN 方式零安装直接运行但正式项目建议使用 Vite Three.js可以更好地处理模块加载、代码分割和资源压缩。粒子数量不是越多越好。粒子数量从 1000 增加到 5000视觉差异明显但从 5000 增加到 10000画面提升有限性能却会明显下降。建议在开发时用devicePixelRatio和粒子数量做组合测试找到当前设备的最佳平衡点。动画中尽量复用对象。不要把BufferGeometry、Material、Points放在动画循环里反复创建。正确做法是在初始化阶段创建一次动画循环中只更新数据。鼠标交互要加缓动。直接让相机或物体跟随鼠标位置用户体验会比较僵硬。本文使用camera.position.x (targetX - camera.position.x) * 0.05的方式让移动更顺滑这是 3D 交互页面的通用技巧。6.3 工程与安全边界使用Skill自动生成代码时要注意以下边界如果需要自动执行命令务必确认命令不会对系统造成破坏。本文脚本只做文件写入和打印输出没有删除操作。生成脚本的输出目录应该是相对路径避免写入系统目录。如果要在生产环境部署建议把生成代码纳入版本管理并增加 Code Review 环节而不是完全信任自动化生成的结果。涉及外部 CDN 资源时建议记录版本号避免 CDN 内容变化导致页面异常。7. 总结与扩展方向本文围绕“一个 Skill 做出 3D 特效网页”这个主题完整拆解了从 Skill 概念、目录结构、SKILL.md编写、Node.js 生成脚本到最终生成一个基于 Three.js 的粒子星空页面全过程。你现在应该能理解Skill并不是某种黑魔法它就是一套约定好的规则和工具让 AI 助手在生成 3D 网页时不再“自由发挥”而是严格按标准流程输出可运行的代码。你可以继续在几个方向扩展把生成脚本扩展出更多场景类型比如 3D 动态文字、几何体波浪、全景图片浏览等。把输出从静态 HTML 升级为 Vite 工程方便后续二次开发和部署。在SKILL.md中增加更多参数校验规则让 AI 在生成之前先确认用户需求减少无效输出。把多个 Skill 组合起来比如用一个 Skill 做页面骨架另一个 Skill 做 3D 特效模块实现更复杂的活动页面。如果按照本文步骤操作后成功跑出粒子星空下一步可以试着把颜色改成你自己喜欢的渐变或者把粒子数量调整到 5000 看看视觉差异。如果遇到报错优先看第 5 节的排查表格大部分问题都能在本地解决。希望这篇教程对你有帮助也欢迎你在实际操作中改出更有意思的 3D 页面。
返回列表