本示例主要介绍threejs简单应用,仅供入门学习,涉及商用产生的风险本人概不负责。其中涉及obj模型加载,obj模型由SU创建并导出,模型表面经过贴图处理,模型不能搞太多顶点,建议贴图处理,否则场景展现会卡,另外obj加载近场景后会以group类型存放。示例中还会涉及材质变化、物体选中、物体移动、以及全局小地图的简单实现。对于threejs相关概念可以参考threejs.org官网,本文中所引用js脚本经过测试可用。
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="three.png">
<title>CHZHtitle>
<style>
body {
margin: 0;
overflow: hidden;
/* 溢出隐藏 */
}
#titlepanel{
position:absolute;
top:0px;
left: calc(50% - 324px);
width:648px;
height: 50px;
/*background-color:#093909;*/
background-image: url("img/frame1.png");
-moz-background-size: 100% 100%;
-webkit-background-size: 100% 100%;
background-size: 100% 100%;
background-size:contain;
background-repeat: no-repeat;
opacity: 0.6;
z-index: 0;
border-width: 0px;
border-radius: 10px;
border-style:solid;
border-color: #093909;
color:#FFFFFF;
text-align: center;
}
#titletext{
position:absolute;
top:15px;
left: calc(50% - 150px);
width:300px;
height: 50px;
background-color:transparent;
z-index: 0;
border-color:transparent;
color:#76b9fd;
text-align: center;
font-family:微软雅黑;
font-size:large;
font-weight: bold;
}
#loading {
position: fixed;
top: 50%;
left: 50%;
color: #FFFFFF;
font-size: 20px;
margin-top: -30px;
margin-left: -40px;
}
#smallscreen{
position:absolute;
top:calc(100% - 325px);
left: 5px;
width: 320px;
height: 320px;
background-color:transparent;
z-index: 0;
border-style:solid;
border-width: 1px;
border-color: #76b9fd;
color: green;
}
#smallscreenlabel
{
position:absolute;
top:0px;
left: 0px;
background-color:transparent;
z-index: 0;
padding: 0px;
margin: 0px;
color: green;
}
#capturescreen{
position:absolute;
top:calc(100% - 245px);
left:calc(100% - 325px);
width: 320px;
height: 240px;
background-color: #FFFFFF;
z-index: 0;
border-style:solid;
border-width: 1px;
border-color: #76b9fd;
}
#movie{
width: 320px;
height: 240px;
}
#focusobjinfo{
position:absolute;
top:calc(95vh);
left: calc(100vh);
width:fit-content;
height:fit-content;
background-color:black;
opacity: 1;
z-index: 0;
border-width: 1px;
color:#76b9fd;
}
#findobjpanel{
position:absolute;
top:calc(95vh);
left: calc(50vh);
width: 450px;
height: 50px;
background-color:transparent;
opacity: 1;
z-index: 0;
border-width: 1px;
color:green;
}
#searchcontext{
background-color:black;
opacity: 1;
z-index: 0;
border-width: 1px;
color:white;
border-color: green;
}
#searchbutton{
background-color:darkgreen;
opacity: 1;
z-index: 0;
border-width: 1px;
color:white;
border-color: green;
}
#searchitem{
background-color:darkgreen;
opacity: 1;
z-index: 0;
border-width: 1px;
color:white;
border-color: green;
}
#whiteboard{
position:absolute;
top:80px;
left: 5px;
width: 320px;
height: 240px;
background-color:transparent;
z-index: 0;
border-style:solid;
border-width: 0px;
border-color: gray;
color: green;
}
style>
<script src="js/three-r93.js">script>
<script src="js/Detector.js">script>
<script src="js/dat.gui.min.js">script>
<script src="js/stats.min.js">script>
<script src="js/OrbitControls.js">script>
<script src="js/MTLLoader.js">script>
<script src="js/OBJLoader.js">script>
<script src="js/chroma.js">script>
head>
<body>
<p id="loading">加载中......p>
<div id="titlepanel">div>
<div id="titletext">货运场站仿真控制div>
<div id="whiteboard">
<p>总箱-22 (TEU)p>
<p>空箱-5p>
<p>重箱-16p>
<p>待提-2p>
div>
<div id="smallscreen" ><p id="smallscreenlabel">俯视p>div>
<div id="focusobjinfo">div>
<div id="findobjpanel">
<select id="searchitem" >
<option value="container" selected>集装箱option>
<option value="vehicle">货车option>
select>
<input id="searchcontext" type="text" width="100px" />
<input id="searchbutton" type="button" onclick="searchobject()" value="查找">
<input id="focusinfofollowmouse" onclick="layoutchange(this)" type="checkbox" >焦点信息跟随鼠标
div>
<div id="capturescreen"><video id="movie" src="capture.mp4" loop="loop" autoplay x5-video-player-type="h5">video>div>
<script>
var focusinfoleft,focusinfotop//焦点信息显示对象显示位置信息
var projectiveObj, selectobject;//定义上次投射到的对象,单击选中的对象
var raycaster, mouse;//光投射器,鼠标位置对应的二维向量
var focushelper,selectedhelper;
var directionalLight;
var listener, audioclick,audiobackground;
var moviesource;
var yourposition;
let scene, camera,smallcamera, renderer,smallrender, controls, guiControls,axes;
let stats = initStats();
function changemovesource(source){
document.getElementById("movie").src=source;
}
function initaudio(){
//初始化音频
// 非位置音频可用于不考虑位置的背景音乐
// 创建一个监听者
listener = new THREE.AudioListener();
// camera.add( listener );
// 创建一个非位置音频对象 用来控制播放
audioclick = new THREE.Audio(listener);
// 创建一个音频加载器对象
var audioLoader = new THREE.AudioLoader();
// 加载音频文件,返回一个音频缓冲区对象作为回调函数参数
audioLoader.load('audio/select.mp3', function (AudioBuffer) {
// console.log(AudioBuffer)
// 音频缓冲区对象关联到音频对象audio
audioclick.setBuffer(AudioBuffer);
audioclick.setLoop(false); //是否循环
audioclick.setVolume(1); //音量
// 播放缓冲区中的音频数据
});
audiobackground = new THREE.Audio(listener);
var backaudioloader=new THREE.AudioLoader();
backaudioloader.load("audio/background.mp3",function(AudioBuffer){
audiobackground.setBuffer(AudioBuffer);
audiobackground.setLoop(true); //是否循环
audiobackground.setVolume(0.1); //音量
});
}
function layoutchange(source){
if(source.checked)
{
remberlayoutinfo();
}
else
{
resetlayoutinfo();
}
}
function remberlayoutinfo(){
//记录布局历史信息
focusinfoleft=document.getElementById("focusobjinfo").offsetLeft;
focusinfotop= document.getElementById("focusobjinfo").offsetTop;
}
function resetlayoutinfo()
{
//恢复布局历史信息
document.getElementById("focusobjinfo").style.left = focusinfoleft+"px";
document.getElementById("focusobjinfo").style.top = focusinfotop+"px";
}
function searchobject()
{
var searchstring=document.getElementById("searchcontext").value;
var searchitem = document.getElementById("searchitem").value;
var findobjname="";
switch(searchitem)
{
case "container":
findobjname="集装箱";
break;
case "vehicle":
findobjname = "货车";
break;
}
//查找集装箱
for(var i=0;i<scene.children.length;i++)
{
var targetobj=scene.children[i];
if(targetobj instanceof THREE.Group)
{
if(targetobj.name=="container" && targetobj.name == searchitem)
{
if(targetobj.boxnumber== searchstring)
{
FocusObjectChanged(targetobj);
var f= new THREE.Vector3(0,0,0);
f.copy( targetobj.position);
controls.target= f;
return;
}
}
if(targetobj.name == "vehicle" && targetobj.name == searchitem)
{
if (targetobj.vehicleid == searchstring) {
FocusObjectChanged(targetobj);
var f = new THREE.Vector3(0, 0, 0);
f.copy(targetobj.position);
controls.target = f;
return;
}
}
}
}
alert("未找到"+searchstring+ findobjname+"!")
}
/* 场景 */
function initScene() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0x050505);
//scene.background = new THREE.Color(0xcccccc);
}
function initraycaster(){
/*
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;
{
//焦点信息跟随鼠标
if(document.getElementById("focusinfofollowmouse").checked)
{
var objinfo = document.getElementById('focusobjinfo');
objinfo.style.top= event.clientY+10+'px';
objinfo.style.left= event.clientX+2+'px';
}else
{
}
}
}, false);
}
function initboxhelper(){
focushelper = new THREE.BoxHelper(camera, 0xff0000);
scene.add(focushelper);
selectedhelper= new THREE.BoxHelper(camera, 0xffff00);
scene.add(selectedhelper);
}
function initax(){
//显示坐标轴
axes = new THREE.AxesHelper(8000);
scene.add(axes);
}
function initlandgrid(){
/*
5、添加地面网格
*/
/**
* size 网格总边长
* step 网格个数
* colorCenterLine 网格中心线颜色
* colorGrid 网格其他线颜色
*/
var gridHelper = new THREE.GridHelper(8000, 100, 'green', '#093909');
// var gridHelper = new THREE.GridHelper(8000, 100, 'green', 'silver');
gridHelper.position.y = -2;
gridHelper.position.x = 0;
scene.add(gridHelper);
}
/* 相机 */
function initCamera() {
camera = new THREE.PerspectiveCamera(120, window.innerWidth / window.innerHeight, 0.1, 100000);
camera.position.set(0, 150, 150);
camera.lookAt(new THREE.Vector3(0, 0, 0));
smallcamera= new THREE.PerspectiveCamera(120, 1, 0.1, 100000);
smallcamera.position.set(0, 1100, 0);
smallcamera.lookAt(new THREE.Vector3(0, 0, 0));
var yourgeo=new THREE.SphereGeometry(30,30,30);
// yourposition=new THREE.Mesh(yourgeo,new THREE.MeshLambertMaterial({ color:0xffffff, transparent: false, opacity: 0.0, side: THREE.DoubleSide }));
var yourmaterial = new THREE.MeshPhongMaterial({color: 0x00ffff });
//添加高光颜色
//yourmaterial.specular = new THREE.Color(0x00ffff);
//添加高光的平滑度,默认为30,值越高越强烈
yourmaterial.shininess = 30;
yourposition=new THREE.Mesh(yourgeo,yourmaterial);
yourposition.name="yourposition";
scene.add(yourposition);
}
/* 渲染器 */
function initRender() {
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: false });
renderer.setSize(window.innerWidth, window.innerHeight);
//renderer.shadowMap.Enabled=true;
document.body.appendChild(renderer.domElement);
renderer.autoClear = true;
//小窗口
smallrender = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: false });
smallrender.setSize(320,320);
smallrender.autoClear=false;
document.getElementById("smallscreen").appendChild(smallrender.domElement);
}
/* 灯光 */
function initLight() {
scene.add(new THREE.AmbientLight(0xFFFFFF, 5));
directionalLight = new THREE.DirectionalLight(0xcccccc, 2);
directionalLight.castShadow = true;
directionalLight.position.set(0, 1000, 1000);
scene.add(directionalLight);
}
/* 控制器 */
function initControls() {
// /* 轨迹球控件 */
// controls = new THREE.TrackballControls(camera, renderer.domElement);
// /* 属性参数 */
// controls.rotateSpeed = 0.8;// 旋转速度
// controls.zoomSpeed = 0.8;// 缩放速度
// controls.panSpeed = 0.8;// 平controls
// controls.staticMoving = false;// 静止移动,为 true 则没有惯性
// controls.dynamicDampingFactor = 0.2;// 阻尼系数 越小 则滑动越大
// controls.minDistance = 30; // 最小视角
// controls.maxDistance = 1000;// 最大视角 Infinity 无穷大
controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.addEventListener( 'change', render );
controls.autoRotateSpeed = 0.02;//自动旋转速度
controls.autoRotate = false;
controls.rotateSpeed = 0.5;// 旋转速度
controls.zoomSpeed = 0.5;// 缩放速度
controls.panSpeed = 0.5;// 平移速度
controls.enableDamping = true;// 有惯性
controls.dampingFactor = 0.25;// 阻尼系数 越小 则滑动越大
// controls.staticMoving = true;// 静止移动,为 true 则没有惯性
// controls.dynamicDampingFactor = 0.1;// 阻尼系数 越小 则滑动越大
controls.minDistance = 30; // 最小视角
controls.maxDistance = 900;// 最大视角 Infinity 无穷大
}
/* 调试插件 */
function initGui() {
guiControls = new function () {
this.rotateSpeed = controls.rotateSpeed;
this.zoomSpeed = controls.zoomSpeed;
this.panSpeed = controls.panSpeed;
this.enableDamping = controls.enableDamping;
this.dampingFactor = controls.dampingFactor;
this.minDistance = controls.minDistance;
this.maxDistance = controls.maxDistance;
this.自动旋转= controls.autoRotate;
this.距离=smallcamera.position.y;
};
var booldropdown = { 显示:'是' };
var boolstats = ['否', '是'];
var backaudiodropdown={背景音乐:'关'};
var switchstats=['关','开'];
var videosourcedropdown={视频源:"场站高点"};
var sourcelist=['场站高点','集卡入口','集卡出口'];
let gui = new dat.GUI();
var maincontrol=gui.addFolder("主视控制")
maincontrol.add(guiControls, 'rotateSpeed', 0, 1).onChange(function (e) {
controls.rotateSpeed = e;
});
maincontrol.add(guiControls, 'zoomSpeed', 0, 1).onChange(function (e) {
controls.zoomSpeed = e;
});
maincontrol.add(guiControls, 'panSpeed', 0, 1).onChange(function (e) {
controls.panSpeed = e;
});
maincontrol.add(guiControls, 'enableDamping').onChange(function (e) {
controls.enableDamping = e;
});
maincontrol.add(guiControls, 'dampingFactor', 0, 1).onChange(function (e) {
controls.dampingFactor = e;
});
maincontrol.add(guiControls, 'minDistance', 0, 500).onChange(function (e) {
controls.minDistance = e;
});
maincontrol.add(guiControls, 'maxDistance', 100, 1800).onChange(function (e) {
controls.maxDistance = e;
});
maincontrol.add(guiControls, '自动旋转', 0, 1).onChange(function (e) {
controls.autoRotate = e;
});
maincontrol.add(backaudiodropdown, '背景音乐').options(switchstats).onChange(function (e) {
if (e=="开") {
audiobackground.play();
} else {
audiobackground.stop();
}
});
var smallcontrol = gui.addFolder("俯视控制")
smallcontrol.add(guiControls, "距离", 300, 2000).onChange(function (e) {
smallcamera.position.y = e;
});
smallcontrol.add(booldropdown, '显示').options(boolstats).onChange(function(e){
document.getElementById("smallscreen").style.visibility=e=="是"?"visible":"hidden";
});
var capturecontrol = gui.addFolder("云台控制")
capturecontrol.add(booldropdown, '显示').options(boolstats).onChange(function (e) {
document.getElementById("capturescreen").style.visibility = e == "是" ? "visible" : "hidden";
});
capturecontrol.add(videosourcedropdown, '视频源').options(sourcelist).onChange(function (e) {
var source;
switch(e)
{
case "场站高点":
source="capture.mp4"
break;
case "集卡入口":
source = "capture1.mp4"
break;
case "集卡出口":
source = "capture2.mp4"
break;
}
changemovesource(source);
});
gui.closed=true;//控制面板默认打开
}
/* 场景中的内容 */
function initContent() {
Container("TBJU123411", "J510010071", "20", true, -900);
Container("TBJU123412", "J510010081", "20", false, -800);
Container("TBJU123413", "J510010091", "20", false, -700);
Container("TBJU123414", "J510010101", "20", false, -600);
Container("TBJU123415", "J510010111", "20", false, -500);
Container("TBJU123416", "J510010121", "20", false, -400);
Container("TBJU123678", "J510010151", "20",false,-100);
Container("TBJU123567", "J510010141", "20",true,-200);
Container("TBJU123456", "J510010131", "20",true,-300);
Container("TBJU234678", "J510020151", "20",false, -100,0,30);
Container("TBJU234567", "J510020141", "20",false, -200,0,30);
Container("TBJU234456", "J510020131", "20",false, -300,0,30);
Container("TBJU123789","J510010161","20",false);
Container("TBJU123678", "J510010162", "20",false,0,26,0);
Container("TBJU123890", "J510010171","40",false,100,0);
Container("TBJU123901", "J510010181","40",false, 250, 0);
Container("TBJU123902", "J510020171", "40", true,100, 0,30);
Container("TBJU123904", "J510020191", "40", true, 250, 30, 0);
Container("TBJU123903", "J510020201", "40", false, 400, 0, 30);
Container("TBJU123904", "J510020201", "40", false, 550, 0, 30);
Container("TBJU123905", "J510020201", "40", false, 700, 0, 30);
Container("TBJU123906", "J510020201", "40", false, 850, 0, 30);
Vehicle("128", "哈尔滨", "天津",false, -1050, 0, 80);
Vehicle("127", "哈尔滨", "天津",false, -900, 0, 80);
Vehicle("126", "哈尔滨", "天津",false, -750, 0, 80);
Vehicle("125", "哈尔滨", "天津",false, -600, 0, 80);
Vehicle("124", "哈尔滨", "天津",false, -450, 0, 80);
Vehicle("123","哈尔滨","天津",false ,-300, 0, 80);
Vehicle("456", "哈尔滨", "南京",false, -150, 0, 80);
Vehicle("789", "哈尔滨", "上海",false, 0, 0, 80);
Vehicle("345", "哈尔滨", "福建",false, 150, 0, 80);
Vehicle("234", "哈尔滨", "广州",false, 300, 0, 80);
Vehicle("235", "哈尔滨", "广州",false, 450, 0, 80);
Vehicle("236", "哈尔滨", "广州",true, 600, 0, 80);
Vehicle("237", "哈尔滨", "广州",false, 750, 0, 80);
Vehicle("238", "哈尔滨", "广州",false, 900, 0, 80);
document.getElementById('loading').style.display = 'none';
}
/*
ContainerType:20 or 40
boxid:箱号
dockerid:容器号,车厢号、集卡号、箱位号
*/
function Container(boxnumber,dockerid,ContainerType, isempty=false,x=0,y=0,z=0)
{
var objname="";
var height=0;
switch(ContainerType)
{
case "40":
objname="container40";
height=28;
break;
case "20":
objname="container20";
height=25;
break;
}
let mtlLoader = new THREE.MTLLoader();
mtlLoader.load(objname+'.mtl', function (materials) {
new THREE.OBJLoader()
.setMaterials(materials)
.load(objname+'.obj', function (object) {
object.scale.set(0.01, 0.01, 0.01);
object.position.x=x;
object.position.y=y;
object.position.z=z;
object.name= "container"; //对象名
object.containertype= ContainerType; //箱型
object.boxnumber= boxnumber; //箱号
object.dockerid = dockerid; //容器号
object.isempty=isempty;
//object.castShadow=true;
//object.receiveShadow=true;
object.selfheight=height;
if(isempty){
setobjopacity(object,0.6);
}
scene.add(object);
//return object;
});
});
}
function Vehicle(vehicleid,fromstation,tostation,iserror=false,x=0,y=0,z=0)
{
let mtlLoader = new THREE.MTLLoader();
mtlLoader.load('vehiclenowheel.mtl', function (materials) {
new THREE.OBJLoader()
.setMaterials(materials)
.load('vehiclenowheel.obj', function (object) {
object.scale.set(0.03, 0.035, 0.045);
object.position.x = x;
object.position.y = y;
object.position.z = z;
object.name = "vehicle"; //对象名
object.fromstation= fromstation;
object.tostation= tostation;
object.vehicleid = vehicleid; //容器号
object.iserror= iserror;
object.selfheight=12;
scene.add(object);
if(iserror)
{
setobjcolor(object,0x000000);
}
//return object;
});
});
}
function setobjopacity(obj,opacity)
{
/*
设置对象透明度
*/
if(obj instanceof THREE.Group)
{
for(var i=0;i<obj.children[0].material.length;i++)
{
obj.children[0].material[i].transparent=true;
obj.children[0].material[i].opacity=opacity;
//obj.children[0].material[i].wireframe=true;
//obj.children[0].material[i].depthTest = false;
}
return;
}
if(obj instanceof THREE.Mesh)
{
return;
}
}
function setobjcolor(obj, color) {
/*
设置对象颜色
*/
if (obj instanceof THREE.Group) {
for (var i = 0; i < obj.children[0].material.length; i++) {
obj.children[0].material[i].color.set(color);
}
return;
}
if (obj instanceof THREE.Mesh) {
return;
}
}
/* 性能插件 */
function initStats() {
let stats = new Stats();
document.body.appendChild(stats.domElement);
return stats;
}
/* 窗口变动触发 */
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/* 数据更新 */
function update() {
stats.update();
controls.update();
yourposition.position.x=camera.position.x;
yourposition.position.z=camera.position.z;
}
/* 初始化 */
function init() {
initScene();
initaudio();
//initax();
initlandgrid();
initCamera();
initraycaster();
initRender();
initLight();
initControls();
initContent();
initGui();
initboxhelper();
/* 监听事件 */
window.addEventListener('resize', onWindowResize, false);
window.addEventListener('click', function (event) {
if (projectiveObj) {
if (projectiveObj.hasChecked ) {
projectiveObj.hasChecked = false;
selectobject = null;
}
else {
if(selectobject != null && selectobject != projectiveObj)
{
selectobject.position.x=projectiveObj.position.x;
selectobject.position.y=projectiveObj.position.y+ projectiveObj.selfheight;
selectobject.position.z=projectiveObj.position.z;
//selectobject = null;
}else
{
projectiveObj.hasChecked = true;
selectobject = projectiveObj;
}
}
SelectObjectChanged(selectobject);
}
}, false);
}
/**
* 根据光投射器判断鼠标所在向量方向是否穿过物体,穿过则改变物体材质
* @param {*} raycaster 光投射器
* @param {*} scene 场景
* @param {*} camera 相机
* @param {*} mouse 鼠标位置对应的二维向量
*/
function renderRaycasterObj(raycaster, scene, camera, mouse) {
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children, true);
//检查射线指向物体集合是否不为空
if (intersects.length > 0) {
var currentProjectiveObjT= intersects[0].object;
if((currentProjectiveObjT instanceof THREE.AxisHelper) || (currentProjectiveObjT instanceof THREE.GridHelper))
{
return;
}
if(currentProjectiveObjT instanceof THREE.Mesh)
{
if(currentProjectiveObjT.name=="yourposition"){return;/*忽略定位指示标*/}
if (projectiveObj != currentProjectiveObjT) {
projectiveObj = currentProjectiveObjT.parent;
FocusObjectChanged(projectiveObj);
}
}
}
else
{
projectiveObj = null;
}
}
function SelectObjectChanged(object)
{
audioclick.play(); //play播放、stop停止、pause暂停
if(object == null)
{
selectedhelper.visible=false;
}
else
{
selectedhelper.setFromObject(object);
selectedhelper.visible=true;
}
}
function FocusObjectChanged(object) {
if (object === undefined) object = null;
if (object === null) {
focushelper.visible = false;
} else {
focushelper.setFromObject(object);
focushelper.visible = true;
if(object.name=="container")
{
document.getElementById("focusobjinfo").innerText = "集装箱:" + object.boxnumber+","+object.containertype+","+ object.dockerid+","+(object.isempty?"空":"重");
}
else if(object.name=="vehicle")
{
document.getElementById("focusobjinfo").innerText = "货车:" + object.vehicleid +","+object.fromstation+">>>>"+object.tostation +","+(object.iserror?"坏":"好");
}
}
}
/* 循环渲染 */
function animate() {
requestAnimationFrame(animate);
renderRaycasterObj(raycaster, scene, camera, mouse);//渲染光投射器投射到的对象
yourposition.visible=false;
renderer.render(scene, camera);
yourposition.visible = true;
smallrender.render(scene, smallcamera);
update();
}
/* 初始加载 */
(function () {
console.log("three init start...");
init();
animate();
console.log("three init end...");
}
)();
script>
body>
html>
threejs后期可做更多特效处理,结合音效可实现更好视听觉体验,弄不好就是玩,希望有喜欢这块的同行不吝拍砖。
示例代码下载