尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

3D正方形颜色和信息展示练习

3D正方形颜色和信息展示练习 3D正方形颜色和信息展示练习一个小功能把知识点串起来使用写一个中间正方形模型我可以使用按钮改变它的颜色并且点击模型利用射线拾取获取模型信息弹框粗略的展示一下信息增加记忆点。涉及代码template div classcontainer div classdialogBox v-iftextShow div stylefont-size: 20px; font-weight: bold;margin: 5px 0;物体信息/div div选中物体: {{ selectedObject.name }}/div div选中物体位置: {{ selectedObject.position }}/div /div div classbtnBox div classbtn v-foritem in btnList :keyitem.name :style{ backgroundColor: item.color } clickhandleColorClick(item.color) {{ item.name }} /div /div /div /template script setup import { ref, onMounted } from vue; import * as THREE from three; import { OrbitControls } from three/examples/jsm/controls/OrbitControls; // 轨道控制器 let scene null; //场景 let camera null; //相机 let renderer null; //渲染器 let controls null; //控制器 const cubes []; const textShow ref(false); //是否显示弹框 const btnList ref([ { name: 红色, color: #ff0000, }, { name: 绿色, color: #00ff00, }, { name: 蓝色, color: #0000ff, }, ]); //按钮列表 import imgUrl from ../assets/img/backImg.png; const initThreeMap () { scene new THREE.Scene(); //场景 scene.background new THREE.Color(black); //设置场景背景色 const fog new THREE.Fog(0xffffff, 0.005, 1000); //雾 scene.fog fog; //添加雾 // 添加光源 const ambientLight new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); setCamera(); //设置相机 setRenderer(); //设置渲染器 initMesh(); //初始化网格 window.addEventListener(resize, () { //监听窗口大小变化 camera.aspect window.innerWidth / window.innerHeight; //设置相机纵横比 camera.updateProjectionMatrix(); //更新相机投影矩阵 renderer.setSize(window.innerWidth, window.innerHeight); //设置渲染器大小 }); setControls(); //设置控制器 }; const setCamera () { camera new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); //透视相机 camera.position.z 10; //设置相机位置 camera.position.y 5; //设置相机位置 camera.lookAt(0, 0, 0); //设置相机目标点 }; const setRenderer () { renderer new THREE.WebGLRenderer({ antialias: true }); //渲染器 renderer.setSize(window.innerWidth, window.innerHeight); //设置渲染器大小 // 【关键步骤1】开启渲染器的阴影映射功能 renderer.shadowMap.enabled true; // 可选使用柔和阴影边缘更自然 renderer.shadowMap.type THREE.PCFSoftShadowMap; document.body.appendChild(renderer.domElement); //将渲染器添加到页面中 }; let cubeMesh null; //立方体网格 const initMesh () { const cubeGeometry new THREE.BoxGeometry(3, 3, 3); //立方体 const cubeMaterial new THREE.MeshStandardMaterial({ color: 0xff0000, metalness: 0.5, roughness: 0.0, }); //材质 cubeMesh new THREE.Mesh(cubeGeometry, cubeMaterial); //网格 cubeMesh.position.set(0, 1.5, 2); //设置网格位置 cubeMaterial.transparent true; //设置透明度 // cubeMaterial.opacity 0.5; //设置透明度 cubeMesh.castShadow true; //设置网格投射阴影 cubeMesh.name 测试模型; //设置立方体网格名称 console.log(cubeMesh); const light new THREE.DirectionalLight(0xffffff, 2, 100); //点光源 light.position.set(0, 5, 10); //设置点光源位置 light.castShadow true; scene.add(light); //添加到场景 const lightHelper new THREE.DirectionalLightHelper(light, 1); // scene.add(lightHelper); // 4. 创建阴影接收平面 (地面) const planeGeometry new THREE.PlaneGeometry(20, 20); const planeMaterial new THREE.MeshStandardMaterial({ color: 0xcccccc, roughness: 0.8, metalness: 1, side: THREE.DoubleSide, }); const plane new THREE.Mesh(planeGeometry, planeMaterial); // 【关键步骤3】旋转平面使其水平 plane.rotation.x -Math.PI / 2; plane.position.y 0; // 位于 y0 高度 // 【关键步骤4】允许平面接收阴影 plane.receiveShadow true; scene.add(plane); scene.add(cubeMesh); //添加到场景 }; const raycaster new THREE.Raycaster(); //射线投射器 const mouse new THREE.Vector2(); //鼠标 let selectedObject ref(null); //选中物体 const handleClick (event) { // 获取 Canvas 在页面中的位置 const rect renderer.domElement.getBoundingClientRect(); console.log(rect , rect); // 计算归一化设备坐标 (NDC) mouse.x ((event.clientX - rect.left) / rect.width) * 2 - 1; mouse.y -((event.clientY - rect.top) / rect.height) * 2 1; checkIntersection(event); }; window.addEventListener(click, handleClick, false); const checkIntersection (event) { raycaster.setFromCamera(mouse, camera); const intersects raycaster.intersectObjects(scene.children, true); console.log(intersects , intersects); if (intersects.length 0) { console.log(选中物体:, intersects[0].object); textShow.value true; if (intersects[0].object.name 测试模型) { selectedObject.value intersects[0].object; } } }; const handleColorClick (color) { console.log(color); cubeMesh.material.color.set(color); cubeMesh.material.needsUpdate true; cubeMesh.name 测试模型: color; cubeMesh.color2 color; textShow.value false; }; const setControls () { controls new OrbitControls(camera, renderer.domElement); //控制器 controls.minPolarAngle 0; controls.maxPolarAngle Math.PI / 2; controls.enableDamping true; // 给控制器添加阻尼必须在动画循环里调用.update()。 controls.update(); //更新控制器 }; const animate () { requestAnimationFrame(animate); //请求动画帧 renderer.render(scene, camera); //渲染场景和相机 controls.update(); //更新控制器 }; onMounted(() { initThreeMap(); //初始化 animate(); //动画 }); /script style scoped .container { width: 100%; height: 100vh; position: relative; } .dialogBox { position: absolute; top: 30%; left: 50%; width: 400px; height: 100px; color: #000; background-color: #fff; z-index: 9999; } .btnBox { position: absolute; bottom: 80px; left: 50%; right: 50%; } .btn { display: inline-block; margin: 10px; width: 100px; height: 30px; line-height: 30px; text-align: center; border-radius: 5px; background-color: #ff0000; color: #fff; cursor: pointer; } /style
返回列表