wordpress公众号管理员优化好的网站做企业网站
wordpress公众号管理员,优化好的网站做企业网站,微信会员卡管理系统怎么开通,太平洋手机一、点模型#xff08;Points#xff09;拾取实现
实现步骤#xff1a;
创建点模型#xff1a;使用 THREE.Points 和点材质设置点大小#xff1a;在材质中设置 size 属性Raycaster配置#xff1a;设置 Points 的拾取阈值拾取检测#xff1a;使用 intersectObjects 检测相…一、点模型Points拾取实现实现步骤创建点模型使用THREE.Points和点材质设置点大小在材质中设置size属性Raycaster配置设置Points的拾取阈值拾取检测使用intersectObjects检测相交完整案例templatedivclasscontainerrefcontainerRef/div/templatescriptsetupimport{onMounted,ref}fromvue;import*asTHREEfromthree;import{OrbitControls}fromthree/examples/jsm/controls/OrbitControls;constcontainerRefref(null);// 创建场景constscenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0xf0f0f0);// 创建相机constcameranewTHREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(0,0,10);// 创建渲染器constrenderernewTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);// 创建点模型functioncreatePointCloud(){// 创建100个随机点constvertices[];for(leti0;i100;i){constx(Math.random()-0.5)*10;consty(Math.random()-0.5)*10;constz(Math.random()-0.5)*10;vertices.push(x,y,z);}constgeometrynewTHREE.BufferGeometry();geometry.setAttribute(position,newTHREE.Float32BufferAttribute(vertices,3));// 创建点材质 - 关键设置点大小constmaterialnewTHREE.PointsMaterial({color:0xff0000,size:0.2,// 点的大小sizeAttenuation:true// 点大小是否随距离衰减});// 创建点云对象constpointsnewTHREE.Points(geometry,material);points.namepointCloud;scene.add(points);returnpoints;}// 创建点模型constpointCloudcreatePointCloud();// 添加光源constambientLightnewTHREE.AmbientLight(0xffffff,0.5);scene.add(ambientLight);constdirectionalLightnewTHREE.DirectionalLight(0xffffff,0.8);directionalLight.position.set(10,10,5);scene.add(directionalLight);// 添加坐标轴辅助constaxesHelpernewTHREE.AxesHelper(5);scene.add(axesHelper);// 动画循环functionanimate(){requestAnimationFrame(animate);// 让点云缓慢旋转pointCloud.rotation.y0.005;renderer.render(scene,camera);}animate();// 点模型拾取函数functionpickPoints(event){// 1. 获取鼠标归一化设备坐标constmousenewTHREE.Vector2();mouse.x(event.clientX/window.innerWidth)*2-1;mouse.y-(event.clientY/window.innerHeight)*21;// 2. 创建RaycasterconstraycasternewTHREE.Raycaster();raycaster.setFromCamera(mouse,camera);// 3. 关键设置点模型的拾取阈值// 这个值决定点击距离点多近才算选中值越大越容易选中raycaster.params.Points{threshold:0.2};// 4. 检测相交constintersectsraycaster.intersectObjects([pointCloud]);// 5. 处理结果if(intersects.length0){constintersectintersects[0];console.log(选中了点:,intersect);// 获取选中的点的索引constpointIndexintersect.index;// 创建高亮点在该位置添加一个更大的点consthighlightGeometrynewTHREE.BufferGeometry();constpositionintersect.object.geometry.attributes.position;constpointPosition[position.getX(pointIndex),position.getY(pointIndex),position.getZ(pointIndex)];highlightGeometry.setAttribute(position,newTHREE.Float32BufferAttribute(pointPosition,3));consthighlightMaterialnewTHREE.PointsMaterial({color:0xffff00,size:0.5,sizeAttenuation:true});consthighlightnewTHREE.Points(highlightGeometry,highlightMaterial);highlight.namehighlightPoint;// 移除之前的高亮点constoldHighlightscene.getObjectByName(highlightPoint);if(oldHighlight)scene.remove(oldHighlight);scene.add(highlight);// 显示信息console.log(点位置:,pointPosition);console.log(点索引:,pointIndex);}}// 添加点击事件window.addEventListener(click,pickPoints);// 挂载到DOMonMounted((){constcontrolsnewOrbitControls(camera,containerRef.value);controls.enableDampingtrue;containerRef.value.appendChild(renderer.domElement);// 窗口大小变化处理window.addEventListener(resize,(){camera.aspectwindow.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);});});/scriptstyle.container{width:100%;height:100vh;}/style关键点说明PointsMaterial.size控制点的大小raycaster.params.Points.threshold设置点拾取的敏感度intersect.index获取选中点的索引intersect.point获取选中点的具体位置二、线模型Line拾取实现实现步骤创建线模型使用THREE.Line或THREE.LineSegmentsRaycaster配置设置Line的拾取阈值提高拾取精度通过辅助方法增加拾取成功率处理拾取结果获取线段信息完整案例templatedivclasscontainerrefcontainerRef/div/templatescriptsetupimport{onMounted,ref}fromvue;import*asTHREEfromthree;import{OrbitControls}fromthree/examples/jsm/controls/OrbitControls;constcontainerRefref(null);// 创建场景constscenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0x222222);// 创建相机constcameranewTHREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(5,5,5);camera.lookAt(0,0,0);// 创建渲染器constrenderernewTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);// 创建复杂的线模型functioncreateComplexLine(){// 创建曲线路径constcurvenewTHREE.CatmullRomCurve3([newTHREE.Vector3(-4,0,0),newTHREE.Vector3(-2,3,1),newTHREE.Vector3(0,0,2),newTHREE.Vector3(2,3,1),newTHREE.Vector3(4,0,0)]);// 获取曲线上的点constpointscurve.getPoints(50);// 创建线几何体constgeometrynewTHREE.BufferGeometry().setFromPoints(points);// 创建线材质constmaterialnewTHREE.LineBasicMaterial({color:0x00aaff,linewidth:3// 注意大多数浏览器不支持大于1的线宽});// 创建线对象constlinenewTHREE.Line(geometry,material);line.namecomplexLine;scene.add(line);returnline;}// 创建网格线更容易拾取functioncreateGridLines(){constgroupnewTHREE.Group();// 创建水平线for(leti-5;i5;i){constgeometrynewTHREE.BufferGeometry().setFromPoints([newTHREE.Vector3(-5,i,0),newTHREE.Vector3(5,i,0)]);constmaterialnewTHREE.LineBasicMaterial({color:0x666666,linewidth:2});constlinenewTHREE.Line(geometry,material);line.userData.typegridLine;line.userData.indexi;group.add(line);}// 创建垂直线for(leti-5;i5;i){constgeometrynewTHREE.BufferGeometry().setFromPoints([newTHREE.Vector3(i,-5,0),newTHREE.Vector3(i,5,0)]);constmaterialnewTHREE.LineBasicMaterial({color:0x666666,linewidth:2});constlinenewTHREE.Line(geometry,material);line.userData.typegridLine;line.userData.indexi;group.add(line);}scene.add(group);returngroup;}// 创建线模型constcomplexLinecreateComplexLine();constgridLinescreateGridLines();// 添加光源constambientLightnewTHREE.AmbientLight(0xffffff,0.6);scene.add(ambientLight);constdirectionalLightnewTHREE.DirectionalLight(0xffffff,0.8);directionalLight.position.set(10,10,5);scene.add(directionalLight);// 添加坐标轴辅助constaxesHelpernewTHREE.AxesHelper(5);scene.add(axesHelper);// 动画循环functionanimate(){requestAnimationFrame(animate);renderer.render(scene,camera);}animate();// 线模型拾取函数functionpickLines(event){// 获取鼠标位置constmousenewTHREE.Vector2();mouse.x(event.clientX/window.innerWidth)*2-1;mouse.y-(event.clientY/window.innerHeight)*21;// 创建RaycasterconstraycasternewTHREE.Raycaster();raycaster.setFromCamera(mouse,camera);// 关键设置线模型的拾取阈值增大以提高拾取成功率// 这个值表示距离线多远的点击算选中单位世界单位raycaster.params.Line{threshold:0.3};// 收集所有线对象constlineObjects[];scene.traverse((object){if(object.typeLine||object.typeLineSegments){lineObjects.push(object);}});// 检测相交constintersectsraycaster.intersectObjects(lineObjects);if(intersects.length0){constintersectintersects[0];constlineintersect.object;console.log(选中了线:,line);console.log(相交点:,intersect.point);console.log(距离:,intersect.distance);console.log(线段索引:,intersect.faceIndex);// 改变线的颜色line.material.color.set(Math.random()*0xffffff);// 在相交点添加标记addIntersectionMarker(intersect.point);// 如果是网格线显示信息if(line.userData.typegridLine){console.log(网格线类型:${line.userData.type}, 索引:${line.userData.index});}}}// 添加相交点标记functionaddIntersectionMarker(position){// 移除旧的标记constoldMarkerscene.getObjectByName(intersectionMarker);if(oldMarker)scene.remove(oldMarker);// 创建标记几何体constmarkerGeometrynewTHREE.SphereGeometry(0.1,16,16);constmarkerMaterialnewTHREE.MeshBasicMaterial({color:0xff0000});constmarkernewTHREE.Mesh(markerGeometry,markerMaterial);marker.position.copy(position);marker.nameintersectionMarker;scene.add(marker);// 3秒后移除标记setTimeout((){if(marker.parent)scene.remove(marker);},3000);}// 添加点击事件window.addEventListener(click,pickLines);// 挂载到DOMonMounted((){constcontrolsnewOrbitControls(camera,containerRef.value);controls.enableDampingtrue;containerRef.value.appendChild(renderer.domElement);// 窗口大小变化处理window.addEventListener(resize,(){camera.aspectwindow.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);});});/scriptstyle.container{width:100%;height:100vh;}/style关键点说明raycaster.params.Line.threshold控制线拾取的敏感度线宽限制WebGL中大多不支持大于1的linewidthintersect.faceIndex获取选中线段的索引使用辅助标记通过添加标记点显示拾取位置三、精灵模型Sprite拾取实现实现步骤创建精灵模型使用THREE.Sprite和精灵材质设置精灵大小通过scale属性控制Raycaster配置Sprite会自动被检测无需特殊配置处理拾取结果获取精灵信息完整案例templatedivclasscontainerrefcontainerRef/div/templatescriptsetupimport{onMounted,ref}fromvue;import*asTHREEfromthree;import{OrbitControls}fromthree/examples/jsm/controls/OrbitControls;constcontainerRefref(null);// 创建场景constscenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0x111122);// 创建相机constcameranewTHREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(0,0,15);// 创建渲染器constrenderernewTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);// 创建精灵材质使用Canvas绘制纹理functioncreateSpriteMaterial(text,color#ff0000){// 创建Canvasconstcanvasdocument.createElement(canvas);canvas.width256;canvas.height256;constcontextcanvas.getContext(2d);// 绘制圆形背景context.beginPath();context.arc(128,128,120,0,2*Math.PI);context.fillStylecolor;context.fill();// 添加描边context.lineWidth8;context.strokeStyle#ffffff;context.stroke();// 添加文字context.fontbold 60px Arial;context.fillStyle#ffffff;context.textAligncenter;context.textBaselinemiddle;context.fillText(text,128,128);// 创建纹理consttexturenewTHREE.CanvasTexture(canvas);// 创建精灵材质constmaterialnewTHREE.SpriteMaterial({map:texture,transparent:true});returnmaterial;}// 创建多个精灵constsprites[];constspriteGroupnewTHREE.Group();functioncreateSprites(){constpositions[{x:-5,y:0,z:0,text:A,color:#ff0000},{x:-2.5,y:3,z:-2,text:B,color:#00ff00},{x:0,y:-2,z:2,text:C,color:#0000ff},{x:2.5,y:3,z:-2,text:D,color:#ffff00},{x:5,y:0,z:0,text:E,color:#ff00ff},{x:0,y:5,z:0,text:F,color:#00ffff}];positions.forEach((pos,index){constmaterialcreateSpriteMaterial(pos.text,pos.color);constspritenewTHREE.Sprite(material);// 设置位置sprite.position.set(pos.x,pos.y,pos.z);// 设置大小 - 精灵的大小通过scale控制sprite.scale.set(2,2,1);// 添加自定义数据sprite.userData{type:interactiveSprite,id:index,text:pos.text,originalColor:pos.color,originalScale:{x:2,y:2,z:1}};sprite.namesprite_${pos.text};sprites.push(sprite);spriteGroup.add(sprite);});scene.add(spriteGroup);}// 创建精灵createSprites();// 添加一个立方体作为参考constcubeGeometrynewTHREE.BoxGeometry(1,1,1);constcubeMaterialnewTHREE.MeshBasicMaterial({color:0x888888,wireframe:true});constcubenewTHREE.Mesh(cubeGeometry,cubeMaterial);scene.add(cube);// 添加光源constambientLightnewTHREE.AmbientLight(0xffffff,0.4);scene.add(ambientLight);constdirectionalLightnewTHREE.DirectionalLight(0xffffff,0.6);directionalLight.position.set(10,10,5);scene.add(directionalLight);// 添加坐标轴辅助constaxesHelpernewTHREE.AxesHelper(10);scene.add(axesHelper);// 动画循环functionanimate(){requestAnimationFrame(animate);// 让精灵组缓慢旋转spriteGroup.rotation.y0.005;renderer.render(scene,camera);}animate();// 精灵模型拾取函数functionpickSprites(event){// 获取鼠标位置constmousenewTHREE.Vector2();mouse.x(event.clientX/window.innerWidth)*2-1;mouse.y-(event.clientY/window.innerHeight)*21;// 创建RaycasterconstraycasternewTHREE.Raycaster();raycaster.setFromCamera(mouse,camera);// 注意精灵模型会自动被Raycaster检测无需特殊配置// 检测相交constintersectsraycaster.intersectObjects(sprites);if(intersects.length0){constintersectintersects[0];constspriteintersect.object;console.log(选中了精灵:,sprite.name);console.log(精灵数据:,sprite.userData);console.log(相交点:,intersect.point);console.log(距离:,intersect.distance);// 高亮效果放大精灵constoriginalScalesprite.userData.originalScale;sprite.scale.set(originalScale.x*1.5,originalScale.y*1.5,originalScale.z);// 3秒后恢复原大小setTimeout((){sprite.scale.set(originalScale.x,originalScale.y,originalScale.z);},300);// 显示选中信息showSelectionInfo(sprite.userData);}}// 显示选中信息functionshowSelectionInfo(spriteData){// 移除旧的信息显示constoldInfoscene.getObjectByName(selectionInfo);if(oldInfo)scene.remove(oldInfo);// 创建信息精灵constcanvasdocument.createElement(canvas);canvas.width512;canvas.height128;constcontextcanvas.getContext(2d);// 绘制背景context.fillStylergba(0, 0, 0, 0.8);context.fillRect(0,0,canvas.width,canvas.height);// 绘制文字context.fontbold 40px Arial;context.fillStyle#ffffff;context.textAligncenter;context.textBaselinemiddle;context.fillText(选中: 精灵${spriteData.text}(ID:${spriteData.id}),canvas.width/2,canvas.height/2);// 创建纹理和精灵consttexturenewTHREE.CanvasTexture(canvas);constmaterialnewTHREE.SpriteMaterial({map:texture});constinfoSpritenewTHREE.Sprite(material);// 设置位置相机上方infoSprite.position.set(0,8,0);infoSprite.scale.set(8,2,1);infoSprite.nameselectionInfo;scene.add(infoSprite);// 5秒后移除信息setTimeout((){if(infoSprite.parent)scene.remove(infoSprite);},5000);}// 添加点击事件window.addEventListener(click,pickSprites);// 挂载到DOMonMounted((){constcontrolsnewOrbitControls(camera,containerRef.value);controls.enableDampingtrue;containerRef.value.appendChild(renderer.domElement);// 窗口大小变化处理window.addEventListener(resize,(){camera.aspectwindow.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);});});/scriptstyle.container{width:100%;height:100vh;}/style关键点说明精灵创建使用THREE.Sprite和SpriteMaterial大小控制通过sprite.scale.set()控制精灵大小朝向精灵始终面向相机这是Sprite的特性拾取Sprite会自动被Raycaster检测无需特殊配置纹理创建通常使用Canvas创建动态纹理总结对比模型类型关键配置特点拾取难度点模型raycaster.params.Points.threshold需要设置阈值可获取点索引中等线模型raycaster.params.Line.threshold需要增大阈值线宽有限制较高精灵模型无需特殊配置始终面向相机自动检测容易网格模型无需特殊配置最常见的3D物体最容易每个模型类型都有其特定的应用场景和拾取配置根据实际需求选择合适的模型类型和拾取策略。