您的位置:首页 > Web前端 > JavaScript

threejs创建多个立方体,并支持鼠标点击选中

2017-12-20 15:58 2306 查看

threejs创建多个立方体,并支持鼠标点击选中

threejs创建多个立方体并支持鼠标点击选中
引入所需的插件

创建渲染器Renderer

创建相机Camera

创建视图控制器OrbitControls

创建场景Scene

创建辅助坐标轴AxisHelper

添加地面网格GirdHelper

添加空间正方体BoxGeometry Mesh

添加光投射器Raycaster

执行渲染

效果图

完整代码

引入所需的插件

<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
<!--该插件主要用于完成鼠标拖动改变相机视角-->
<script src="libs/OrbitControls.js"></script>


创建渲染器
Renderer

把三维的场景渲染到显示屏上


renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
//container:浏览器画图区域对应的dom元素
container.appendChild(renderer.domElement);


创建相机
Camera

相当于人的眼睛,看到物体的大小远近与相机的位置和设置有关


/*
创建相机【远景相机,与人眼观察类似,近大远小】
param1:视角【视角越大  物体渲染到屏幕时则看着越小,反之越大】
param2:相机拍摄面的长宽比
param3:近裁剪面,相机与物体的距离小于该值后将不在屏幕上显示
param4:远裁剪面,相机与物体的距离大于该值后将不在屏幕上显示
*/
camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000);
camera.position.set(10,10,800);


创建视图控制器
OrbitControls

通过鼠标拖动和滑轮移动自动改变相机的位置,调整视角,重新渲染页面


controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );


创建场景
Scene

用于添加空间范围内需要显示的物体


scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);


创建辅助坐标轴
AxisHelper

通过 X(屏幕右边) 、 Y(屏幕上边) 、 Z(屏幕由内到外) 三条轴线帮助你了解物体空间位置坐标


var axes = new THREE.AxisHelper(800);//参数设置了三条轴线的长度
scene.add(axes);


添加地面网格
GirdHelper

在指定位置条件指定长度、数量的网格图形


/**
* size 网格总边长
* step 网格个数
* colorCenterLine  网格中心线颜色
* colorGrid    网格其他线颜色
*/
var gridHelper = new THREE.GridHelper( 300, 10, 'red', 'gray' );
gridHelper.position.y = -100;
gridHelper.position.x = 0;
scene.add( gridHelper );


添加空间正方体
BoxGeometry Mesh

var geometry = new THREE.BoxGeometry(20,20,20);//盒子模型
for ( var i = 0; i < 100; i ++ ) {
var material = new THREE.MeshBasicMaterial({color:"gray"});//材料
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
scene.add( mesh );
}


添加光投射器
Raycaster

通过光投射器结合鼠标位置坐标,判断鼠标是否经过物体


raycaster = new THREE.Raycaster();//光线投射器
mouse = new THREE.Vector2();//二维向量
document.addEventListener('mousemove', function(){
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2
4000
+ 1;
}, false);

var projectiveObj;//定义上次投射到的对象
/**
* 根据光投射器判断鼠标所在向量方向是否穿过物体
* @param {*} raycaster 光投射器
* @param {*} scene     场景
* @param {*} camera    相机
* @param {*} mouse     鼠标位置对应的二维向量
*/
function renderRaycasterObj(raycaster,scene,camera,mouse) {
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
var currentProjectiveObjT = intersects[0].object;
if (projectiveObj != currentProjectiveObjT) {
if((currentProjectiveObjT instanceof THREE.AxisHelper) || (currentProjectiveObjT instanceof THREE.GridHelper)){
//穿过的是坐标轴线和网格线
return;
}
projectiveObj = intersects[0].object;
}
} else {
projectiveObj = null;
}
}


执行渲染

function render() {

requestAnimationFrame(render);

renderRaycasterObj(raycaster,scene,camera,mouse);//渲染光投射器投射到的对象

renderer.render( scene, camera);

}


效果图



完整代码

<!DOCTYPE html>
<html lang="en">
<head>
<title>创建threejs场景-旋转的立方体</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body{margin: 0}
canvas{width: 100% ; height: 100%}
div#drawArea{
position: fixed;
}
</style>
</head>
<body>

<div id="drawArea"></div>

<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
<script src="libs/OrbitControls.js"></script>

<script>

var scene,camera,renderer,light,controls;//场景,相机,渲染器,光源
var raycaster,mouse;//光投射器,鼠标位置对应的二维向量

init();

function init() {

var container = document.getElementById("drawArea");

/*
1、初始化渲染器
*/
renderer = new THREE.WebGLRenderer();
// renderer.setClearColor('white');//设置渲染出来的背景色
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth,window.innerHeight);
container.appendChild(renderer.domElement);

/*
2、初始化相机
创建相机【远景相机,与人眼观察类似,近大远小】
param1:视角【视角越大 物体渲染到屏幕时则看着越小,反之越大】
param2:相机拍摄面的长宽比
param3:近裁剪面
param4:远裁剪面
*/
camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000);
camera.position.set(10,10,800);

/*
添加视图控制器
*/
controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.addEventListener( 'change', render );

/*
3、初始化场景
*/
scene = new THREE.Scene(); scene.background = new THREE.Color(0xf0f0f0);

//initLight();
//scene.add( new THREE.PointLightHelper( light, 15 ) );

/*
4、添加辅助坐标轴
*/
var axes = new THREE.AxisHelper(800);
scene.add(axes);

/*
5、添加地面网格
*/
/** * size 网格总边长 * step 网格个数 * colorCenterLine 网格中心线颜色 * colorGrid 网格其他线颜色 */ var gridHelper = new THREE.GridHelper( 300, 10, 'red', 'gray' ); gridHelper.position.y = -100; gridHelper.position.x = 0; scene.add( gridHelper );

/*
6、添加正方体
*/
var geometry = new THREE.BoxGeometry(20,20,20);//盒子模型

for ( var i = 0; i < 100; i ++ ) {
var material = new THREE.MeshBasicMaterial({color:"gray"});//材料
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
scene.add( mesh );
}

/*
7、添加光投射器 及 鼠标二维向量 用于捕获鼠标移入物体

下次渲染时,通过mouse对于的二维向量判断是否经过指定物体
*/
raycaster = new THREE.Raycaster();//光线投射器
mouse = new THREE.Vector2();//二维向量
document.addEventListener('mousemove', function(){
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}, false);

/**
* 浏览器窗口大小调整
*/
window.addEventListener( 'resize', function(){

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );

}, false );

/**
* 添加鼠标点击事件,捕获点击时当前选中的物体
*/
window.addEventListener( 'click', function(){

if(projectiveObj){
console.log(projectiveObj);
if(projectiveObj.hasChecked){
projectiveObj.hasChecked = false;
projectiveObj.material.color.set("gray");
}else{
projectiveObj.hasChecked = true;
projectiveObj.material.color.set("#dd830d");
}
}

}, false );

render();
}

function render() { requestAnimationFrame(render); renderRaycasterObj(raycaster,scene,camera,mouse);//渲染光投射器投射到的对象 renderer.render( scene, camera); }

var projectiveObj;//定义上次投射到的对象
/**
* 根据光投射器判断鼠标所在向量方向是否穿过物体,穿过则改变物体材质
* @param {*} raycaster 光投射器
* @param {*} scene 场景
* @param {*} camera 相机
* @param {*} mouse 鼠标位置对应的二维向量
*/
function renderRaycasterObj(raycaster,scene,camera,mouse) {
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
var currentProjectiveObjT = intersects[0].object;
if (projectiveObj != currentProjectiveObjT) {

if((currentProjectiveObjT instanceof THREE.AxisHelper) || (currentProjectiveObjT instanceof THREE.GridHelper)){
//穿过的是坐标轴线和网格线
return;
}

projectiveObj.material.color.setHex(projectiveObj.currentHex);
projectiveObj = intersects[0].
8ada
object;
}
} else {
projectiveObj = null;
}
}
</script>
</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐