用 Skill 让 Claude 稳定生成 3D 特效网页,这套模板值得收藏
一个 skill做出 3D 特效网页太炫酷了从 2025 年 3 月开始不少开发者发现Claude 的 Artifacts 生成界面变得“能打”了。不是按钮变多了而是它能真正输出一个完整可交互的 3D 场景一个带有轨道控制的 3D 地球、粒子烟花、分形地形甚至是一个小型的 3D 游戏原型。这一个多月的工程实践里我反复用它做 3D 特效网页基本摸清了哪些 skill 写法稳定可复现哪些写法在模型上下文窗口里会直接翻车。这篇博客就把这套方法写全。在动手之前先要说清楚一个关键点这个流程的本质并不是“让 AI 写代码”而是“让 AI 在一个受限但完整的 3D 渲染沙箱里完成创作”。这个沙箱由 HTML、CSS、Three.js 以及少量辅助脚本组成。它足够小小到模型可以在上下文里完整“看见”整个项目它又足够完整完整到可以直接运行 Three.js 的 3D 场景、交互事件和动画循环。所以这里的核心任务不是写业务代码而是把“3D 特效需求”转化为一份模型能稳定执行的页面规格。需要说明的是这里的“skill”不涉及任何商业产品或未经确认的工具。它指的是你可以保存在本地文本提示词库、项目模板描述、或者团队共享知识库中的一套可复用“技能包”。你把它喂给模型时它就知道该用什么结构、什么依赖、什么渲染管线来生成 3D 特效页面。下文会给出完整的 skill 定义内容、运行环境、验证方式和排错流程。本文读者定位是已经用过 Claude 网页版知道 Artifacts 是什么但被生成的 3D 效果“看得到、转不动”困扰的开发者。想在本地项目里复现“一套 3D 特效网页模板”的工程师。需要把 3D 可视化、产品演示页、3D 数据大屏等需求快速交付的前端开发者。读完这篇文章后你会得到一个可以直接复用、保存到本地提示词库的“3D 特效网页 skill”模板。一套从“文字需求”到“完成 3D 页面”的转换流程。运行、调试、检查 3D 场景的关键代码片段和控制台 API。一份覆盖常见问题的排查清单避免把时间浪费在模型反复生成同一处错误上。2. skill 的本质它是给模型的上下文压缩协议不是魔法在开始写 skill 之前先把这个概念讲透。很多人第一次看到“skill”时会觉得它是个插件或者独立程序但实际不是。2.1 skill 到底是什么解决什么问题一个 skill本质是一段结构化的文本指令。它描述的是“当用户提出某类需求时你应该按照什么方式思考和输出”。把它放在 Claude 的项目知识库、自定义指令或者个人提示词库中时它能起三个作用明确输出目标告诉模型生成什么样的页面、包含哪些交互、达到什么视觉效果。约束实现方式限定技术栈、依赖版本、渲染流程和关键 API 用法减少模型随意的“自由发挥”。提供自检路径让模型能够在生成代码时自动检查是否用了错误的 API、缺失了哪些渲染组件。在 3D 特效网页场景里skill 的作用尤其明显。因为 Three.js 项目涉及的东西非常多场景scene、相机camera、渲染器renderer、几何体、材质、纹理、灯光、动画循环、窗口自适应、轨道控制、性能监控。如果让模型随意组织这些内容它很容易生成一个看起来结构完整但一运行就白屏或者不动的东西。skill 就是把“三个月的 Three.js 使用经验”压缩成 300 行提示词。它不是代码库而是控制模型生成的“规格说明书”。2.2 为什么 3D 网页特别适合用 skill 驱动3D 网页和其他前端页面相比有一个很大的差异它的“运行结果”在代码之外。一个普通按钮点击你能立刻看到 DOM 变化但一个 3D 模型渲染它涉及 GPU、着色器、动画循环和坐标系统很多错误不会直接报错而是表现为“画面不动”“黑屏”“物体变形”“控制失效”。这种特性导致了一个结果模型生成 3D 页面时很容易生成“自己觉得没问题运行起来完全不对”的代码。而 skill 的价值就是提前把可能出错的环节标准化。它对模型说不要自己发明相机控制方式用 OrbitControls不要自己写动画循环用 renderer.setAnimationLoop不要手动管理所有 resize 事件按指定方式处理。这样模型输出的代码即使细节不完美至少骨架是安全的。2.3 skill、agent、插件三者到底有什么区别讨论 skill 时经常被拿来跟 agent 和插件对比。简单理解如下概念核心作用持久化方式典型场景skill定义提示词和输出规范文本模板、知识库、项目文件让模型按统一规格生成 3D 页面agent执行多步骤任务决定下一步操作脚本、API 调用逻辑自动截图验证、迭代修改、调用外部工具插件扩展宿主应用的功能浏览器扩展、服务端集成给编辑器增加快捷键、给浏览器增加截图能力在 Claude 生成 Artifacts 的场景里skill 是最轻量级的控制手段。它不需要额外安装不需要写独立服务只要求你在项目知识库或者自定义指令里放一份规范的文本即可。它的核心优势是模型能稳定地、可复现地输出你期望的页面结构。3. 准备一套完整可用的“3D 特效网页 skill”模板这一部分直接给出模板。你不用从头设计提示词直接保存下面的内容放到项目知识库、自定义指令或者个人提示词库中就可以开始使用。3.1 通用模板从需求到 3D 页面的最小规格下面是核心 skill 文本。它假设模型使用的是 Claude 的 Artifacts 或本地 HTML 预览环境支持直接运行 Three.js CDN 脚本。如果你的环境无法运行后面会有适配方案。你是一名资深 Three.js 前端工程师负责根据用户需求生成一个可直接在浏览器中运行的 3D 特效网页。 【输出要求】 生成一个完整 HTML 文件包含 !DOCTYPE html 到 /html 的所有内容。 页面必须满足以下要求 1. 使用 Three.js r128 或更高版本通过 CDN 引入避免使用本地依赖。 2. 核心 3D 场景必须包含场景 scene、透视相机 PerspectiveCamera、WebGL 渲染器 WebGLRenderer。 3. 默认使用 OrbitControls 实现鼠标拖拽旋转、滚轮缩放。 4. 使用 renderer.setAnimationLoop() 驱动动画循环不要在循环外创建一次性渲染。 5. 自动适配窗口大小变化resize 时更新相机 aspect 和渲染器尺寸。 6. 页面背景默认使用深色渐变3D 物体使用高饱和材质体现“炫酷”效果。 7. 必须提供静态文本标题展示页面主题。 8. 所有代码必须运行于单个 HTML 文件不额外引入 CSS 文件。 【3D 视觉要求】 - 使用 2 到 4 组不同类型的几何体构成视觉层次。 - 至少使用一种特效材质MeshStandardMaterial、MeshPhongMaterial、ShaderMaterial 均可。 - 使用 2 个以上点光源或方向光营造立体感。 - 可添加粒子系统、光晕、网格辅助线或环境反射效果。 - 动画必须持续运行不能静止。 【交互要求】 - 鼠标拖拽旋转。 - 滚轮缩放。 - 提供“播放/暂停”按钮控制动画开关。 【错误避免】 - 不要使用 document.write。 - 不要使用 Three.js 已废弃的 API如 Geometry、BufferGeometry 除外。 - 不要使用外部纹理图片所有材质使用程序化生成颜色或渐变。 - 不要覆盖现有页面结构整个页面由单个 HTML 输出。 【自检要求】 生成完成后检查以下内容 - scene、camera、renderer 是否都已定义并正确初始化。 - OrbitControls 是否被实例化并传入 camera 和 renderer.domElement。 - 动画循环里是否有 scene.render。 - 是否有 window.addEventListener(resize, ...) 处理。 - 所有几何体 name 属性都已设置方便后续调试。这套模板的核心逻辑是“把 3D 页面拆成固定要素”场景、相机、渲染器、控制、动画、自适应、标题、交互。模型按照这份清单生成页面时不容易遗漏关键环节。3.2 进阶模板支持主题换肤、参数配置和导出当需要生成多个不同主题的 3D 页面时可以增加一个“主题配置”层。下面这段是进阶版 skill 的扩展内容额外要求 - 页面顶部提供一个控制面板包含以下配置项 - 主题选择夜色、霓虹、极光、科技蓝。 - 动画速度滑块范围 0.1 到 3.0默认 1.0。 - 粒子数量选择少500、中2000、多6000。 - 修改主题时页面背景色、物体材质颜色、灯光强度必须同步变化。 - 配置项使用纯 JavaScript 实现不使用第三方 UI 库。 - 控制面板样式使用固定定位半透明背景不遮挡 3D 场景拖拽区域。这个扩展的价值在于模型生成的页面不再是一个固定演示而是一个可以交给用户调参的“小工具”。在实际工作中这种页面已经能用于产品概念展示、技术分享开场页、团队内部数据展厅。3.3 模板放置在哪个位置决定了它会不会生效把 skill 文本写出来只是第一步。不同的使用方式决定模型会不会真的按模板执行。使用位置生效条件适合场景Claude 项目知识库项目包含该文本文件模型会读取固定项目的持续创作自定义指令全局生效个人高频复用的通用模板每次对话里粘贴当次生效快速调试、临时生成团队共享知识库随项目内文件生效多人协作、统一输出规格这里有一个常见坑如果你把 skill 放在很长的项目文件里模型在选择读取哪些文件时可能只检索到部分内容。建议把 skill 的标题写得足够明确例如“threejs-skill-template.md”并在文件开头写一句“生成 3D 特效网页时使用以下规则”。这样模型在检索时更容易把它当成权威指令。4. 用 skill 实际生成一个 3D 粒子地球页面现在进入实操环节。目标是生成一个带粒子地球的 3D 特效页面。为什么选粒子地球因为它同时具备三个特点视觉效果好、Three.js 实现思路经典、适合验证 skill 是否生效。4.1 先定义一个标准输入需求一个优秀的“需求输入”是 skill 能发挥作用的起点。不要只说“做一个炫酷的 3D 效果”而是给出具体的格式请按 skill 模板生成一个 3D 特效网页主题为“粒子地球”。 具体要求 1. 页面标题显示“Particle Earth”。 2. 背景使用深蓝色渐变从 #050510 到 #0a0a2a。 3. 地球由 3000 个粒子组成粒子分布在一个球面上。 4. 粒子颜色使用蓝、白、青渐变透明度 0.9。 5. 地球缓慢自转自转速度 0.002 弧度/帧。 6. 添加一个半透明的球体网格作为辅助视觉层。 7. 使用 OrbitControls 控制视角。 8. 页面底部显示操作提示“拖拽旋转 / 滚轮缩放”。这段输入的优点是把视觉要求、粒子数量、颜色、动画速度、交互方式都做了明确限定。模型不需要猜你想表达什么它只需要把这段规格翻译成 Three.js 代码。4.2 让模型按 skill 模板输出将 skill 模板和需求输入一起交给模型。如果你使用的是 Claude 项目知识库方式直接把“需求输入”粘贴到对话中即可。如果使用的是自定义指令方式也要在同一对话里把需求说清楚。模型输出的结果通常是一份完整的 HTML 文件代码结构大致如下!DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / titleParticle Earth/title style * { margin: 0; padding: 0; box-sizing: border-box; } body { overflow: hidden; background: linear-gradient(135deg, #050510 0%, #0a0a2a 100%); font-family: Segoe UI, sans-serif; color: #fff; } #info { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); font-size: 14px; opacity: 0.7; z-index: 10; pointer-events: none; } #toggleBtn { position: fixed; top: 20px; right: 20px; z-index: 10; padding: 10px 18px; background: rgba(255,255,255,0.12); border: 1px solid rgba(255,255,255,0.3); color: #fff; border-radius: 8px; cursor: pointer; backdrop-filter: blur(6px); } /style /head body div idtitleParticle Earth/div button idtoggleBtn暂停/button div idinfo拖拽旋转 / 滚轮缩放/div script srchttps://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js/script script // 场景、相机、渲染器 const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(0, 0, 8); const renderer new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.body.appendChild(renderer.domElement); // OrbitControls const controls new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping true; controls.dampingFactor 0.05; controls.autoRotate false; // 粒子地球 const particleCount 3000; const radius 3; const positions new Float32Array(particleCount * 3); const colors new Float32Array(particleCount * 3); for (let i 0; i particleCount; i) { // 在球面上均匀分布 const theta Math.random() * Math.PI * 2; const phi Math.acos(2 * Math.random() - 1); const x radius * Math.sin(phi) * Math.cos(theta); const y radius * Math.sin(phi) * Math.sin(theta); const z radius * Math.cos(phi); positions[i * 3] x; positions[i * 3 1] y; positions[i * 3 2] z; const t Math.random(); // 蓝白青色渐变 colors[i * 3] 0.1 t * 0.3; colors[i * 3 1] 0.4 t * 0.4; colors[i * 3 2] 0.9; } const particleGeo new THREE.BufferGeometry(); particleGeo.setAttribute(position, new THREE.BufferAttribute(positions, 3)); particleGeo.setAttribute(color, new THREE.BufferAttribute(colors, 3)); const particleMat new THREE.PointsMaterial({ size: 0.05, vertexColors: true, transparent: true, opacity: 0.9, blending: THREE.AdditiveBlending, depthWrite: false }); const particles new THREE.Points(particleGeo, particleMat); particles.name particleEarth; scene.add(particles); // 辅助球体网格 const wireframeSphere new THREE.Mesh( new THREE.SphereGeometry(radius, 32, 32), new THREE.MeshBasicMaterial({ color: 0x2a5f9e, wireframe: true, transparent: true, opacity: 0.15 }) ); wireframeSphere.name gridSphere; scene.add(wireframeSphere); // 灯光 const ambientLight new THREE.AmbientLight(0xffffff, 0.3); const dirLight new THREE.DirectionalLight(0x4aa8ff, 1.2); dirLight.position.set(5, 5, 5); scene.add(ambientLight); scene.add(dirLight); // 动画循环 let isPlaying true; const animate () { if (isPlaying) { particles.rotation.y 0.002; wireframeSphere.rotation.y 0.002; } controls.update(); renderer.render(scene, camera); }; renderer.setAnimationLoop(animate); // 播放/暂停 const toggleBtn document.getElementById(toggleBtn); toggleBtn.addEventListener(click, () { isPlaying !isPlaying; toggleBtn.textContent isPlaying ? 暂停 : 播放; }); // resize 自适应 window.addEventListener(resize, () { camera.aspect window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); /script /body /html代码里的关键点已经不只是“生成一个 3D 页面”而是体现了几条工程经验粒子位置使用Math.acos(2 * Math.random() - 1)生成球面均匀分布避免粒子在南北极聚集。粒子材质使用AdditiveBlending和depthWrite: false让粒子叠加时产生光晕感这是 3D 特效页面“炫酷”的重要来源。使用renderer.setAnimationLoop()而不是requestAnimationFrame单独管理循环避免在多个地方出现多个循环导致动画卡顿。controls.enableDamping true让旋转更顺滑不再有“一顿一顿”的感觉。4.3 实际运行后如何确认 skill 生成了正确结果页面在浏览器里打开后不能只看一眼“好像有粒子”就认为成功。按下面这张检查表逐项验证检查项预期结果失败表现页面标题显示 Particle Earth页面无标题或标题错误背景深蓝色渐变白屏或黑色纯色粒子数量3000 个粒子分布在球面粒子明显过稀或过密粒子颜色蓝白青渐变全白或全蓝无渐变交互拖拽旋转、滚轮缩放拖拽无反应或页面整体拖动播放/暂停按钮可暂停动画点击后无变化或按钮消失自适应浏览器窗口变化后画面不拉伸画面变形或出现黑边这一步很重要。因为模型生成代码时即使 skill 写得很清楚也可能因为 Three.js 版本 API 差异产生问题。你必须在真实浏览器里运行一次才能确认这个 skill 模板在你当前环境里是可靠的。5. 调试与常见问题排查3D 页面最大的特点是错误表现形式和普通页面不一样。普通页面报错时命令行会直接抛红3D 页面很多错误会表现为“白屏”“黑屏”“不动”“变形”而控制台可能没有任何异常。所以排查思路要从“看报错”变成“看画面特征”。下面是我在实践中最常遇到的 5 类问题。5.1 页面白屏且有报错CDN 地址或 API 版本不匹配现象控制台出现THREE is not defined或Cannot read properties of undefined (reading PerspectiveCamera)。常见原因Three.js CDN 地址失效。引用了较新版本但代码使用旧 API。CDN 和本地代码使用不同版本。排查方式在浏览器控制台执行console.log(THREE.REVISION)确认加载的实际版本号。再检查代码里使用的 API 是否对应这个版本。处理建议统一使用固定版本的 CDN 地址例如r128。不要在页面中混用两个不同版本的 Three.js。如果必须使用最新版本先确认THREE.OrbitControls的引入位置是否已改为独立模块方式。5.2 页面黑屏但无报错相机位置或灯光设置问题现象控制台无报错但页面是纯黑背景什么都看不到。常见原因相机朝向错误物体不在相机可见范围内。灯光设置不合理物体表面被完全照亮或完全没光。物体的 scale 或 position 设置异常导致模型被缩放成不可见。排查方式在控制台执行console.log(camera.position)和console.log(particles.position)确认二者位置合理。把粒子材质临时改为MeshBasicMaterial或把PointsMaterial的颜色改成亮色确认物体是否真的在场景中。把灯光强度临时调大确认是否能看到轮廓。处理建议相机默认放置在(0, 0, 8)物体中心在原点(0, 0, 0)是最安全的组合。使用MeshBasicMaterial测试早期渲染因为它是无光照材质不受灯光影响。如果物体使用PointsMaterial注意粒子尺寸太小也看不见先调大size测试。5.3 粒子地球两极粒子过密球面分布算法不对现象粒子看起来堆积在顶部和底部赤道附近稀疏。原因直接用Math.random() * Math.PI作为极角会导致球面面积不均衡。在球面上均匀分布必须让phi Math.acos(2 * Math.random() - 1)。解决方案for (let i 0; i particleCount; i) { const theta Math.random() * Math.PI * 2; const phi Math.acos(2 * Math.random() - 1); // 其余同前 }检查点随机生成 3000 个点后统计每个纬度带的点数量应大致均匀。5.4 控制失效OrbitControls 被遮挡或重复实例化现象鼠标拖拽没有反应或者页面另一个交互区域会抢到事件。常见原因OrbitControls绑定到了错误的 DOM 元素。页面里有其他覆盖层把鼠标事件吃掉了。OrbitControls被实例化了两次互相干扰。排查方式检查new THREE.OrbitControls(camera, renderer.domElement)中第二个参数是不是renderer.domElement。检查是否有元素覆盖在 canvas 上方设置pointer-events: none。处理建议OrbitControls 统一绑定到renderer.domElement。控制面板、提示文本等浮层不使用事件时设置pointer-events: none。不要在代码里重复new OrbitControls实例化一次即可。5.5 动画只有一帧渲染没有被持续驱动现象页面能显示初始画面但物体始终不动也没有报错。原因渲染代码只在初始化时执行了一次没有进入循环。解决方案使用renderer.setAnimationLoop(animate)并确保animate函数里调用renderer.render(scene, camera)。const animate () { // 更新物体 particles.rotation.y 0.002; // 更新控制 controls.update(); // 渲染 renderer.render(scene, camera); }; renderer.setAnimationLoop(animate);同时要检查暂停按钮的isPlaying状态是否误把动画一直暂停。5.6 一张排查速查表现象可能原因检查动作快速处理白屏 控制台报错CDN 失效或版本 API 不匹配console.log(THREE.REVISION)固定 CDN 版本黑屏无报错相机位置、灯光或物体过小临时调大物体 size、查看 position把相机放到(0,0,8)粒子分布不均球面坐标算法错误统计纬度带数量用Math.acos(2*random-1)无法拖拽旋转OrbitControls 绑定错误/被遮挡检查绑定元素 pointer-events绑定 renderer.domElement动画静止没有进入渲染循环检查 setAnimationLoop在循环中调用 renderresize 后拉伸未更新相机 aspect 和 renderer 尺寸检查 resize 监听更新 camera.aspect 并调用 renderer.setSize6. 从“能跑”到“能用”生产级 3D 页面的设计要点当一个小型 3D 页面在浏览器里跑通后你在真实项目里还要考虑更多东西。这里把“能跑的 demo”和“能上线的页面”做一个边界梳理。6.1 性能粒子数量和渲染开销需要提前估算3D 特效网页最容易犯的问题是视觉效果很漂亮但用户电脑风扇起飞。要控制性能主要看两个指标粒子数量每帧需要更新的对象数量在 skill 模板中我建议默认把粒子数量控制在 3000 以内。实际项目中如果目标用户是普通办公电脑6000 个 OpenGL 粒子的开销已经不小尤其还要开启抗锯齿和 highp precision 时。有一份可参考的经验值目标设备建议粒子数量建议像素比备注旗舰手机2000 以内2关闭大尺寸全屏粒子普通 Windows 笔记本3000 左右2开启 antialias 影响不大中高端台式机6000 左右2可开启 Bloom 等后期特效数据大屏专用机10000 以上2需要配套 GPU 性能检测为什么建议renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))因为很多高分辨率屏幕的 devicePixelRatio 是 2 或更高如果不限制Canvas 实际渲染尺寸会变成屏幕逻辑尺寸的 3 倍、4 倍GPU 开销指数上升。6.2 工程化从单文件 HTML 到组件化结构当多个页面使用同一个 skill 模板时你会希望把重复代码抽出来。比如把粒子地球、粒子星系、粒子流场分别封装成独立函数。function createParticleSphere(scene, options) { const { radius, count, colorStart, colorEnd, size } options; const positions new Float32Array(count * 3); const colors new Float32Array(count * 3); for (let i 0; i count; i) { 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); positions[i * 3 2] radius * Math.cos(phi); const t Math.random(); colors[i * 3] colorStart[0] (colorEnd[0] - colorStart[0]) * t; colors[i * 3 1] colorStart[1] (colorEnd[1] - colorStart[1]) * t; colors[i * 3 2] colorStart[2] (colorEnd[2] - colorStart[2]) * t; } const geometry new THREE.BufferGeometry(); geometry.setAttribute(position, new THREE.BufferAttribute(positions, 3)); geometry.setAttribute(color, new THREE.BufferAttribute(colors, 3)); const material new THREE.PointsMaterial({ size, vertexColors: true, transparent: true, opacity: 0.9, blending: THREE.AdditiveBlending, depthWrite: false }); const points new THREE.Points(geometry, material); points.name options.name || particleSphere; scene.add(points); return points; }这样做的意义在于当业务方要求把粒子地球换成“3D 数据大屏的地球底座”时不再需要让模型重新生成一整页只需要调整createParticleSphere的参数。6.3 交互不能只做旋转缩放要提供明确反馈生产级 3D 页面需要具备以下交互要素操作反馈点击某个 3D 物体时该物体高亮、变色或弹出信息框。状态反馈播放/暂停、加载完成、数据更新时要有可见状态。错误反馈当浏览器不支持 WebGL 时要显示降级信息。可访问性为按钮和文本提供合适的字体大小、对比度必要时支持键盘操作。一个简单的点击反馈示例const raycaster new THREE.Raycaster(); const mouse new THREE.Vector2(); renderer.domElement.addEventListener(click, (event) { mouse.x (event.clientX / window.innerWidth) * 2 - 1; mouse.y -(event.clientY / window.innerHeight) * 2 1; raycaster.setFromCamera(mouse, camera); const intersects raycaster.intersectObjects(scene.children, true); if (intersects.length 0) { const obj intersects[0].object; if (obj.name particleEarth) { // 做高亮或跳转 console.log(particleEarth clicked, obj); } } });这里要记得intersectObjects默认只检测网格对象粒子系统需要开启对应设置。在 Three.js 中Points对象可以被 Raycaster 检测但粒子大小较小时点击命中会比较困难可以适当调大粒子 size 或用半透明包围球辅助检测。6.4 兼容性WebGL 不是所有环境都可用在真实项目中必须考虑降级。你可以用下面这段代码判断浏览器是否支持 WebGLfunction isWebGLSupported() { try { const canvas document.createElement(canvas); return !!(window.WebGLRenderingContext (canvas.getContext(webgl) || canvas.getContext(experimental-webgl))); } catch (e) { return false; } } if (!isWebGLSupported()) { // 显示静态提示或降级为 2D Canvas 效果 document.getElementById(fallback).style.display block; }在 skill 模板里加入这条检查可以在页面白屏之前先给用户一个清晰提示而不是让用户面对一个死了的页面。7. 输出之前把它变成自己的工具最后要说的是这套方法不能一直停留在“让模型顺便生成一个 3D 页面”的阶段。真正有价值的是把 skill 模板沉淀成团队或个人的工具资产。7.1 建立一个 3D 特效需求库建议把常用的 3D 特效需求整理成一份“需求卡片”放在项目知识库中。例如状态需求描述对应 skill 要点已复用3D 粒子地球球面均匀分布、AdditiveBlending、OrbitControls已复用3D 星球环形带环形粒子带、旋转动画、双材质待开发3D 柱状图数据大屏柱状几何体、数据纹理、Raycaster 点击待开发3D 烟花粒子物理、重力、生命周期建立这个库的核心目的是在团队协作时让模型更稳定地输出同类页面。你不需要重新描述“粒子如何分布、动画如何循环”只需要说“按 XXX skill 模板生成环形
上一篇/下一篇内容由系统自动关联
返回资讯列表 →