讨论

交互式3D体素樱花谷网页场景

来自 Wikiprompt,自由的提示词百科全书

宝玉
贡献者宝玉X来源

2026年9月23日

交互式3D体素樱花谷网页场景 一份极其详细的中文提示词,指导AI编程助手构建一个完全交互式的3D体素艺术日本樱花谷,作为自包含的HTML/JS网页,包含相机视角、氛围切换以及交付前的自我验证清单。

相关媒体

提示词内容收藏

🌐
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>日式樱花山谷 · 蓝调时刻</title> <style> body { margin: 0; overflow: hidden; font-family: "Hiragino Mincho Pro", "Yu Mincho", "MS Mincho", serif; background-color: #0a0f1a; } #info { position: absolute; top: 20px; left: 20px; color: rgba(255, 240, 220, 0.9); text-shadow: 0 2px 8px rgba(0,0,0,0.5); z-index: 10; pointer-events: none; font-size: 14px; letter-spacing: 2px; backdrop-filter: blur(4px); padding: 8px 16px; border-left: 2px solid rgba(255, 180, 180, 0.6); background: rgba(20, 20, 30, 0.2); border-radius: 0 8px 8px 0; } #controls { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 12px; z-index: 20; background: rgba(15, 15, 25, 0.6); backdrop-filter: blur(8px); padding: 12px 24px; border-radius: 40px; border: 1px solid rgba(255, 200, 200, 0.2); box-shadow: 0 4px 20px rgba(0,0,0,0.4); flex-wrap: wrap; justify-content: center; pointer-events: auto; } .btn { background: rgba(60, 50, 50, 0.5); border: 1px solid rgba(255, 180, 180, 0.3); color: #f0e6d8; padding: 8px 16px; border-radius: 30px; font-size: 13px; cursor: pointer; transition: all 0.2s ease; letter-spacing: 1px; backdrop-filter: blur(4px); white-space: nowrap; font-family: inherit; } .btn:hover { background: rgba(120, 80, 80, 0.6); border-color: rgba(255, 220, 220, 0.6); color: white; box-shadow: 0 0 15px rgba(255, 150, 150, 0.3); } .btn.active { background: rgba(180, 100, 100, 0.7); border-color: #ffb0b0; color: white; } #toggle-ui { position: absolute; top: 20px; right: 20px; z-index: 30; background: rgba(20, 20, 30, 0.5); border: 1px solid rgba(255, 200, 200, 0.2); color: #ddd; border-radius: 30px; padding: 6px 14px; font-size: 12px; backdrop-filter: blur(4px); cursor: pointer; } #loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #eee; font-size: 18px; z-index: 100; background: rgba(0,0,0,0.5); padding: 20px 40px; border-radius: 8px; letter-spacing: 2px; backdrop-filter: blur(4px); border: 1px solid rgba(255,255,255,0.2); } #error { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #ffaaaa; background: rgba(0,0,0,0.7); padding: 20px; border-radius: 8px; z-index: 200; display: none; text-align: center; } @media (max-width: 600px) { #controls { bottom: 15px; padding: 8px 12px; gap: 8px; width: 90%; border-radius: 30px; } .btn { padding: 6px 10px; font-size: 11px; } #info { font-size: 11px; top: 10px; left: 10px; } #toggle-ui { top: 10px; right: 10px; font-size: 10px; } } </style> </head> <body> <div id="info">🌸 樱花山谷 · 蓝调时刻</div> <div id="toggle-ui">◉ 隐藏界面</div> <div id="controls"> <button class="btn active" data-camera="overview">🏔️ 全景</button> <button class="btn" data-camera="river">🌊 河边</button> <button class="btn" data-camera="temple">⛩️ 小径</button> <button class="btn" data-camera="hill">🌄 山坡</button> <button class="btn" data-atmosphere="dusk">🌆 蓝调</button> <button class="btn" data-atmosphere="morning">🌅 清晨</button> <button class="btn" data-atmosphere="rain">🌧️ 雨中</button> <button class="btn" id="reset-view">⟲ 重置</button> <button class="btn" id="save-image">📷 保存</button> </div> <div id="loading">加载中…</div> <div id="error">⚠️ WebGL 不可用或加载失败</div> <!-- 引入 Three.js 核心库和扩展 --> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.128.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.128.0/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'; // ---------- 初始化 ---------- const container = document.getElementById('container'); const scene = new THREE.Scene(); scene.background = new THREE.Color(0x0a1220); // 深蓝夜空 // 雾效 scene.fog = new THREE.Fog(0x0a1220, 30, 120); // 相机 const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(12, 8, 18); camera.lookAt(0, 2, 0); // 渲染器 const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.body.appendChild(renderer.domElement); // 控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.maxPolarAngle = Math.PI / 2.2; controls.minDistance = 3; controls.maxDistance = 40; controls.target.set(0, 2, 0); // 加载提示移除 setTimeout(() => { document.getElementById('loading').style.display = 'none'; }, 500); // 错误处理 if (!renderer.capabilities.isWebGL2) { document.getElementById('error').style.display = 'block'; } // ---------- 灯光 ---------- // 环境光 const ambientLight = new THREE.AmbientLight(0x404060); scene.add(ambientLight); // 主光源 (模拟月光/蓝调) const dirLight = new THREE.DirectionalLight(0xc0d0ff, 0.8); dirLight.position.set(5, 12, 8); dirLight.castShadow = true; dirLight.shadow.mapSize.width = 1024; dirLight.shadow.mapSize.height = 1024; scene.add(dirLight); // 补光暖色 (灯笼/窗光) const warmLight = new THREE.PointLight(0xffaa66, 0.6, 20); warmLight.position.set(2, 1.5, 3); scene.add(warmLight); // 辅助光 const fillLight = new THREE.DirectionalLight(0x8899cc, 0.3); fillLight.position.set(-3, 4, 5); scene.add(fillLight); // ---------- 地面与地形 ---------- // 基础地面 (起伏) const groundGeo = new THREE.CylinderGeometry(18, 20, 1.5, 32); const groundMat = new THREE.MeshStandardMaterial({ color: 0x2a3a2a, roughness: 0.9, metalness: 0.1 }); const ground = new THREE.Mesh(groundGeo, groundMat); ground.position.y = -0.8; ground.receiveShadow = true; scene.add(ground); // 山谷草地 (用多个平面模拟起伏) for (let i = 0; i < 30; i++) { const patch = new THREE.Mesh( new THREE.CircleGeometry(0.8 + Math.random() * 1.5, 6), new THREE.MeshStandardMaterial({ color: 0x3a5a3a, roughness: 0.8 }) ); patch.rotation.x = -Math.PI / 2; patch.position.x = (Math.random() - 0.5) * 20; patch.position.z = (Math.random() - 0.5) * 20; patch.position.y = -0.5 + Math.random() * 0.3; patch.receiveShadow = true; scene.add(patch); } // 河流 (半透明蓝色平面) const riverGeo = new THREE.PlaneGeometry(2.5, 12); const riverMat = new THREE.MeshStandardMaterial({ color: 0x3a6a8a, transparent: true, opacity: 0.7, roughness: 0.2, metalness: 0.1, emissive: new THREE.Color(0x112233) }); const river = new THREE.Mesh(riverGeo, riverMat); river.rotation.x = -Math.PI / 2; river.position.set(0, 0.1, 2); river.receiveShadow = true; scene.add(river); // 河岸石块 for (let i = 0; i < 20; i++) { const stone = new THREE.Mesh( new THREE.DodecahedronGeometry(0.2 + Math.random() * 0.3), new THREE.MeshStandardMaterial({ color: 0x556655, roughness: 0.9 }) ); stone.position.x = (Math.random() - 0.5) * 3; stone.position.z = 1.5 + Math.random() * 8; stone.position.y = 0.1 + Math.random() * 0.2; stone.castShadow = true; stone.receiveShadow = true; scene.add(stone); } // ---------- 樱花树 (程序化) ---------- function createSakuraTree(x, z, scale = 1) { const treeGroup = new THREE.Group(); // 树干 const trunkMat = new THREE.MeshStandardMaterial({ color: 0x4a3a2a, roughness: 0.8 }); const trunk = new THREE.Mesh(new THREE.CylinderGeometry(0.3 * scale, 0.5 * scale, 2.5 * scale, 6), trunkMat); trunk.position.y = 1.2 * scale; trunk.castShadow = true; trunk.receiveShadow = true; treeGroup.add(trunk); // 分支 for (let i = 0; i < 5; i++) { const branch = new THREE.Mesh( new THREE.CylinderGeometry(0.1 * scale, 0.2 * scale, 1.2 * scale, 5), trunkMat ); branch.position.y = 1.8 * scale + i * 0.3 * scale; branch.position.x = Math.sin(i * 1.5) * 0.6 * scale; branch.position.z = Math.cos(i * 1.2) * 0.6 * scale; branch.rotation.z = Math.sin(i) * 0.5; branch.rotation.x = Math.cos(i) * 0.4; branch.castShadow = true; treeGroup.add(branch); } // 花簇 (多个小立方体) const flowerMat = new THREE.MeshStandardMaterial({ color: 0xffaacc, emissive: new THREE.Color(0x552233), roughness: 0.4, transparent: true, opacity: 0.9 }); for (let i = 0; i < 40; i++) { const flower = new THREE.Mesh(new THREE.BoxGeometry(0.2 * scale, 0.2 * scale, 0.2 * scale), flowerMat); const angle = Math.random() * Math.PI * 2; const radius = 0.8 * scale + Math.random() * 0.8 * scale; flower.position.x = Math.cos(angle) * radius; flower.position.z = Math.sin(angle) * radius; flower.position.y = 2.2 * scale + Math.random() * 1.2 * scale; flower.rotation.set(Math.random(), Math.random(), Math.random()); flower.castShadow = true; treeGroup.add(flower); } treeGroup.position.set(x, 0, z); return treeGroup; } // 前景大樱花树 const bigTree = createSakuraTree(-3, -2, 1.4); scene.add(bigTree); // 中景几棵 scene.add(createSakuraTree(3, 1, 0.8)); scene.add(createSakuraTree(-1, 4, 0.9)); scene.add(createSakuraTree(2, 5, 0.7)); // 远景小树 scene.add(createSakuraTree(-5, 8, 0.5)); scene.add(createSakuraTree(6, 9, 0.6)); // ---------- 建筑 (茶屋/神社/塔) ---------- function createBuilding(x, z, type = 'house') { const group = new THREE.Group(); const baseMat = new THREE.MeshStandardMaterial({ color: 0x8a6a4a, roughness: 0.7 }); const roofMat = new THREE.MeshStandardMaterial({ color: 0x6a3a2a, roughness: 0.6 }); if (type === 'house') { const base = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.8, 1.2), baseMat); base.position.y = 0.4; base.castShadow = true; group.add(base); const roof = new THREE.Mesh(new THREE.ConeGeometry(1.0, 0.6, 4), roofMat); roof.position.y = 1.0; roof.rotation.y = Math.PI/4; roof.castShadow = true; group.add(roof); } else if (type === 'tower') { // 多层塔 for (let i = 0; i < 3; i++) { const floor = new THREE.Mesh(new THREE.BoxGeometry(0.8 - i*0.15, 0.5, 0.8 - i*0.15), baseMat); floor.position.y = 0.5 + i * 0.7; floor.castShadow = true; group.add(floor); const roof = new THREE.Mesh(new THREE.ConeGeometry(0.6 - i*0.1, 0.4, 4), roofMat); roof.position.y = 1.0 + i * 0.7; roof.rotation.y = Math.PI/4; roof.castShadow = true; group.add(roof); } } else { // 神社 const base = new THREE.Mesh(new THREE.BoxGeometry(1.5, 0.6, 1.0), baseMat); base.position.y = 0.3; base.castShadow = true; group.add(base); const roof = new THREE.Mesh(new THREE.BoxGeometry(1.8, 0.3, 1.2), roofMat); roof.position.y = 0.8; roof.castShadow = true; group.add(roof); const pillar = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.8), baseMat); pillar.position.set(0.5, 0.4, 0.3); group.add(pillar); const pillar2 = pillar.clone(); pillar2.position.set(-0.5, 0.4, 0.3); group.add(pillar2); } group.position.set(x, 0, z); return group; } // 放置建筑 scene.add(createBuilding(1, 3, 'house')); scene.add(createBuilding(-1.5, 4.5, 'house')); scene.add(createBuilding(0.5, 6, 'tower')); scene.add(createBuilding(-2, 7, 'shrine')); scene.add(createBuilding(3, 5, 'house')); // 石灯笼 function createLantern(x, z) { const group = new THREE.Group(); const stoneMat = new THREE.MeshStandardMaterial({ color: 0x888888, roughness: 0.8 }); const base = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.3, 0.5), stoneMat); base.position.y = 0.25; base.castShadow = true; group.add(base); const top = new THREE.Mesh(new THREE.SphereGeometry(0.15), stoneMat); top.position.y = 0.6; top.castShadow = true; group.add(top); // 暖光 const light = new THREE.PointLight(0xffaa66, 0.4, 3); light.position.y = 0.7; group.add(light); group.position.set(x, 0, z); return group; } scene.add(createLantern(-2.5, 2)); scene.add(createLantern(2.5, 4)); scene.add(createLantern(-1, 6)); // 小桥 (红色) const bridgeGroup = new THREE.Group(); const bridgeMat = new THREE.MeshStandardMaterial({ color: 0xaa3333, roughness: 0.5 }); for (let i = 0; i < 3; i++) { const plank = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.1, 1.2), bridgeMat); plank.position.x = -0.4 + i * 0.4; plank.position.y = 0.3; plank.position.z = 2.5; plank.castShadow = true; bridgeGroup.add(plank); } // 桥柱 const pillarMat = new THREE.MeshStandardMaterial({ color: 0x8a5a3a }); for (let i = 0; i < 2; i++) { const pillar = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.6), pillarMat); pillar.position.set(-0.5 + i, 0.3, 2.5); pillar.castShadow = true; bridgeGroup.add(pillar); } scene.add(bridgeGroup); // 远山 function createMountain(x, z, scale) { const mountainMat = new THREE.MeshStandardMaterial({ color: 0x4a5a6a, roughness: 0.9, emissive: new THREE.Color(0x1a2a3a) }); const mountain = new THREE.Mesh(new THREE.ConeGeometry(scale, scale * 1.5, 6), mountainMat); mountain.position.set(x, scale * 0.5, z); mountain.castShadow = true; mountain.receiveShadow = true; scene.add(mountain); } createMountain(-8, 12, 3); createMountain(6, 14, 4); createMountain(-2, 16, 5); createMountain(10, 10, 2.5); // 雪山 (白色) const snowMat = new THREE.MeshStandardMaterial({ color: 0xeeeeff, roughness: 0.6 }); const snowMountain = new THREE.Mesh(new THREE.ConeGeometry(4, 5, 6), snowMat); snowMountain.position.set(-4, 2.5, 18); snowMountain.castShadow = true; scene.add(snowMountain); // 落花粒子 const petalGeo = new THREE.BoxGeometry(0.1, 0.02, 0.05); const petalMat = new THREE.MeshStandardMaterial({ color: 0xffaacc, emissive: new THREE.Color(0x552233) }); const petals = []; for (let i = 0; i < 80; i++) { const petal = new THREE.Mesh(petalGeo, petalMat); petal.position.set((Math.random() - 0.5) * 15, Math.random() * 5, (Math.random() - 0.5) * 15); petal.rotation.set(Math.random() * Math.PI, Math.random() * Math.PI, Math.random() * Math.PI); scene.add(petal); petals.push(petal); } // 萤火虫 (点光源) const fireflies = []; for (let i = 0; i < 10; i++) { const light = new THREE.PointLight(0xaaffaa, 0.3, 2); light.position.set((Math.random() - 0.5) * 10, 0.5 + Math.random() * 3, (Math.random() - 0.5) * 10); scene.add(light); fireflies.push(light); } // ---------- 氛围切换 ---------- const atmosphereState = { dusk: { bg: 0x0a1220, fog: new THREE.Fog(0x0a1220, 30, 120), ambient: 0x404060, dir: 0xc0d0ff, dirIntensity: 0.8, warm: 0xffaa66, warmIntensity: 0.6 }, morning: { bg: 0x8a9aaa, fog: new THREE.Fog(0x8a9aaa, 40, 150), ambient: 0x8899aa, dir: 0xffeedd, dirIntensity: 1.0, warm: 0xffcc88, warmIntensity: 0.8 }, rain: { bg: 0x3a4a5a, fog: new THREE.Fog(0x3a4a5a, 20, 80), ambient: 0x556677, dir: 0x8899aa, dirIntensity: 0.5, warm: 0xccaa88, warmIntensity: 0.4 } }; function setAtmosphere(type) { const state = atmosphereState[type]; scene.background = new THREE.Color(state.bg); scene.fog = state.fog; ambientLight.color.setHex(state.ambient); dirLight.color.setHex(state.dir); dirLight.intensity = state.dirIntensity; warmLight.color.setHex(state.warm); warmLight.intensity = state.warmIntensity; } // 默认蓝调 setAtmosphere('dusk'); // ---------- 相机预设 ---------- const cameraPresets = { overview: { pos: [12, 8, 18], target: [0, 2, 0] }, river: { pos: [2, 1.5, 6], target: [0, 1, 3] }, temple: { pos: [-3, 2, 7], target: [-1, 1, 5] }, hill: { pos: [8, 10, 12], target: [0, 3, 5] } }; function setCamera(presetName) { const preset = cameraPresets[presetName]; if (!preset) return; // 平滑过渡 (简单实现) const startPos = camera.position.clone(); const startTarget = controls.target.clone(); const endPos = new THREE.Vector3(...preset.pos); const endTarget = new THREE.Vector3(...preset.target); let t = 0; const animate = () => { t += 0.03; if (t > 1) t = 1; camera.position.lerpVectors(startPos, endPos, t); controls.target.lerpVectors(startTarget, endTarget, t); controls.update(); if (t < 1) requestAnimationFrame(animate); }; animate(); } // ---------- UI 事件 ---------- document.querySelectorAll('[data-camera]').forEach(btn => { btn.addEventListener('click', () => { setCamera(btn.dataset.camera); document.querySelectorAll('[data-camera]').forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); }); document.querySelectorAll('[data-atmosphere]').forEach(btn => { btn.addEventListener('click', () => { setAtmosphere(btn.dataset.atmosphere); document.querySelectorAll('[data-atmosphere]').forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); }); document.getElementById('reset-view').addEventListener('click', () => { setCamera('overview'); }); document.getElementById('save-image').addEventListener('click', () => { renderer.render(scene, camera); const link = document.createElement('a'); link.download = 'sakura_valley.png'; link.href = renderer.domElement.toDataURL('image/png'); link.click(); }); // 隐藏界面 let uiVisible = true; document.getElementById('toggle-ui').addEventListener('click', () => { uiVisible = !uiVisible; document.getElementById('controls').style.display = uiVisible ? 'flex' : 'none'; document.getElementById('info').style.display = uiVisible ? 'block' : 'none'; }); // 窗口大小调整 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); // ---------- 动画循环 ---------- let time = 0; function animate() { requestAnimationFrame(animate); time += 0.01; // 落花飘动 petals.forEach((petal, i) => { petal.position.y += Math.sin(time * 2 + i) * 0.002; petal.rotation.x += 0.01; petal.rotation.z += 0.005; }); // 萤火虫闪烁 fireflies.forEach((light, i) => { light.intensity = 0.2 + Math.sin(time * 3 + i) * 0.1; }); controls.update(); renderer.render(scene, camera); } animate(); // 初始相机 setCamera('overview'); // 移动端轻量模式 if (window.innerWidth < 600) { renderer.setPixelRatio(1); dirLight.shadow.mapSize.width = 512; dirLight.shadow.mapSize.height = 512; } console.log('🌸 樱花山谷加载完成'); </script> </body> </html>

登录以查看完整提示词

继续使用:

登录即表示你同意我们的 使用条款 和 隐私政策

用法

此提示词专为 coding 设计。复制上方内容并粘贴到你常用的 AI 工具中。

为获得最佳效果,可将占位符(方括号或大写字母标示)替换为你的具体需求。

参考资料

分类:coding| twitter| 3d-voxel-art| interactive-webpage

讨论