沂源县建设局网站,开发公司绩效考核,网站建设的方案模板下载,花生壳免费域名注册网站在threejs中想要选中一个物体#xff0c;点击或者鼠标悬浮#xff0c;又或者移动端的touch事件#xff0c;核心都是通过new THREE.Raycaster完成的。这里用到了一个概念#xff0c;即我们点击时的 屏幕坐标 转换为 three中的3D坐标。 先看效果图#xff1a; 代码是#…在threejs中想要选中一个物体点击或者鼠标悬浮又或者移动端的touch事件核心都是通过new THREE.Raycaster完成的。这里用到了一个概念即我们点击时的 屏幕坐标 转换为 three中的3D坐标。 先看效果图 代码是
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlestylebody {width: 100%;height: 100%;}* {margin: 0;padding: 0;}.label {font-size: 20px;color: #000;font-weight: 700;}/style
/head
body
div idcontainer/div
script typeimportmap{imports: {three: ../three-155/build/three.module.js,three/addons/: ../three-155/examples/jsm/}}
/script
script typemodule
import * as THREE from three;
import Stats from three/addons/libs/stats.module.js;
import { OrbitControls } from three/addons/controls/OrbitControls.js;
import { GPUStatsPanel } from three/addons/utils/GPUStatsPanel.js;
import { CSS2DRenderer, CSS2DObject } from three/addons/renderers/CSS2DRenderer.js;
let stats, labelRenderer, gpuPanel, temporaryKeep;
let camera, scene, renderer, controls;
const group new THREE.Group();
let widthImg 200;
let heightImg 200;
const mouse new THREE.Vector2();
init();
initHelp();
initLight();
axesHelperWord();
animate();
// 添加平面
addPlane();let geometry new THREE.BoxGeometry(20, 20, 10);
let material new THREE.MeshLambertMaterial({color: 0xcccccc});
let cube new THREE.Mesh(geometry, material);
cube.position.y 10;
cube.name BoxGeometry;
scene.add(cube);/*** CylinderGeometry(radiusTop : Float, radiusBottom : Float, height : Float, radialSegments : Integer, heightSegments : Integer)radiusTop—顶部圆柱体的半径。默认值为1。radiusBottom—底部圆柱体的半径。默认值为1。height——圆柱体的高度。默认值为1。radialSegments—圆柱体圆周上的分段面数。默认值为32heightSegments—沿圆柱体高度的面行数。默认值为1。*/
let geometry1 new THREE.CylinderGeometry(15, 15, 10, 32, 1);
let material1 new THREE.MeshLambertMaterial({color: 0xffff00});
let cylinder new THREE.Mesh(geometry1, material1);
cylinder.position.set(30, 5, -50);
cylinder.name CylinderGeometry;
scene.add(cylinder);function onDocumentMouseMove(event) {event.preventDefault();// 将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,具体解释见代码释义 如果 canvas有左边距 和 上边距 需要减去mouse.x (event.clientX / window.innerWidth) * 2 - 1;mouse.y -(event.clientY / window.innerHeight) * 2 1;// 新建一个三维单位向量 假设z方向就是1// 根据照相机把这个向量转换到视点坐标系const vector new THREE.Vector3(mouse.x, mouse.y, 1).unproject(camera);// 在视点坐标系中形成射线,射线的起点向量是照相机 射线的方向向量是照相机到点击的点这个向量应该归一标准化。const raycaster new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());//射线和模型求交选中一系列直线const intersects raycaster.intersectObjects(scene.children);console.log(imtersrcts, intersects);/*** 不是所有的 Material 都有这个属性* emissive.getHex* emissive.setHex*/if (intersects.length 0) {//选中第一个射线相交的物体if (temporaryKeep ! intersects[0].object) {if (temporaryKeep) temporaryKeep.material.emissive?.setHex(temporaryKeep.currentHex);temporaryKeep intersects[0].object;temporaryKeep.currentHex temporaryKeep.material.emissive?.getHex();temporaryKeep.material.emissive?.setHex(0xff0000);}} else {if (temporaryKeep) temporaryKeep.material.emissive?.setHex(temporaryKeep.currentHex);temporaryKeep null;}
}function addPlane() {// 创建一个平面 PlaneGeometry(width, height, widthSegments, heightSegments)const planeGeometry new THREE.PlaneGeometry(widthImg, heightImg, 1, 1);// 创建 Lambert 材质会对场景中的光源作出反应但表现为暗淡而不光亮。const planeMaterial new THREE.MeshPhongMaterial({color: 0xb2d3e6,side: THREE.DoubleSide});const plane new THREE.Mesh(planeGeometry, planeMaterial);// 以自身中心为旋转轴绕 x 轴顺时针旋转 45 度plane.rotation.x -0.5 * Math.PI;plane.position.set(0, -4, 0);scene.add(plane);
}function init() {camera new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 10, 2000 );camera.up.set(0, 1, 0);camera.position.set(60, 40, 60);camera.lookAt(0, 0, 0);scene new THREE.Scene();scene.background new THREE.Color( #ccc );renderer new THREE.WebGLRenderer( { antialias: true } );renderer.setPixelRatio( window.devicePixelRatio );renderer.setSize( window.innerWidth, window.innerHeight );document.body.appendChild( renderer.domElement );labelRenderer new CSS2DRenderer();labelRenderer.setSize( window.innerWidth, window.innerHeight );labelRenderer.domElement.style.position absolute;labelRenderer.domElement.style.top 0px;labelRenderer.domElement.style.pointerEvents none;document.getElementById( container ).appendChild( labelRenderer.domElement );controls new OrbitControls( camera, renderer.domElement );controls.mouseButtons {LEFT: THREE.MOUSE.PAN,MIDDLE: THREE.MOUSE.DOLLY,RIGHT: THREE.MOUSE.ROTATE};controls.enablePan true;// 设置最大最小视距controls.minDistance 20;controls.maxDistance 1000;window.addEventListener( resize, onWindowResize );stats new Stats();stats.setMode(1); // 0: fps, 1: msdocument.body.appendChild( stats.dom );gpuPanel new GPUStatsPanel( renderer.getContext() );stats.addPanel( gpuPanel );stats.showPanel( 0 );scene.add( group );document.addEventListener(click, onDocumentMouseMove, false);
}function initLight() {const light new THREE.DirectionalLight(new THREE.Color(rgb(253,253,253)));light.position.set(100, 100, -10);light.intensity 3; // 光线强度light.castShadow true; // 是否有阴影light.shadow.mapSize.width 2048; // 阴影像素light.shadow.mapSize.height 2048;// 阴影范围const d 80;light.shadow.camera.left -d;light.shadow.camera.right d;light.shadow.camera.top d;light.shadow.camera.bottom -d;light.shadow.bias -0.0005; // 解决条纹阴影的出现// 最大可视距和最小可视距light.shadow.camera.near 0.01;light.shadow.camera.far 2000;const AmbientLight new THREE.AmbientLight(new THREE.Color(rgb(255, 255, 255)));scene.add( light );scene.add( AmbientLight );
}function initHelp() {// const size 100;// const divisions 5;// const gridHelper new THREE.GridHelper( size, divisions );// scene.add( gridHelper );// The X axis is red. The Y axis is green. The Z axis is blue.const axesHelper new THREE.AxesHelper( 100 );scene.add( axesHelper );
}function axesHelperWord() {let xP addWord(X轴);let yP addWord(Y轴);let zP addWord(Z轴);xP.position.set(50, 0, 0);yP.position.set(0, 50, 0);zP.position.set(0, 0, 50);
}function addWord(word) {let name span${word}/span;let moonDiv document.createElement( div );moonDiv.className label;// moonDiv.textContent Moon;// moonDiv.style.marginTop -1em;moonDiv.innerHTML name;const label new CSS2DObject( moonDiv );group.add( label );return label;
}function onWindowResize() {camera.aspect window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize( window.innerWidth, window.innerHeight );
}function animate() {requestAnimationFrame( animate );stats.update();controls.update();labelRenderer.render( scene, camera );renderer.render( scene, camera );
}
/script
/body
/html
具体思路代码中都有注释实在不懂也没关系函数一封装先用着就是后面慢慢理解