THREE.JS 場景世界座標和平面二維座標互轉
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>場景世界座標轉</title>
<style type="text/css">
html, body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
.title{
position: absolute;
padding: 10px;
background: rgba(255, 255, 255, 0.5);
line-height: 1;
border-radius: 5px;
}
</style>
</head>
<body onload="draw();">
<div class="title one">第一個盒子</div>
<div class="title two">第二個盒子</div>
<div class="title three">第三個盒子</div>
</body>
<script src="https://cdn.bootcss.com/three.js/91/three.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="/lib/js/controls/OrbitControls.js"></script>
<script src="/lib/js/libs/stats.min.js"></script>
<script src="https://cdn.bootcss.com/dat-gui/0.7.1/dat.gui.min.js"></script>
<script src="/lib/js/Detector.js"></script>
<script>
var renderer, camera, scene, gui, light, stats, controls;
var cube, cube2, cube3;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xeeeeee);
renderer.shadowMap.enabled = true;
//告訴渲染器需要陰影效果
document.body.appendChild(renderer.domElement);
}
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 15 );
}
function initScene() {
//給場景新增天空盒子紋理
var cubeTextureLoader = new THREE.CubeTextureLoader();
cubeTextureLoader.setPath( '/lib/textures/cube/space/' );
//六張圖片分別是朝前的(posz)、朝後的(negz)、朝上的(posy)、朝下的(negy)、朝右的(posx)和朝左的(negx)。
var cubeTexture = cubeTextureLoader.load( [
'right.jpg', 'left.jpg',
'top.jpg', 'bottom.jpg',
'front.jpg', 'back.jpg'
] );
scene = new THREE.Scene();
scene.background = cubeTexture;
}
//初始化dat.GUI簡化試驗流程
function initGui() {
//宣告一個儲存需求修改的相關資料的物件
gui = {
};
var datGui = new dat.GUI();
//將設定屬性新增到gui當中,gui.add(物件,屬性,最小值,最大值)
}
function initLight() {
scene.add(new THREE.AmbientLight(0x444444));
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 20 );
light.castShadow = true;
light.shadow.camera.top = 10;
light.shadow.camera.bottom = -10;
light.shadow.camera.left = -10;
light.shadow.camera.right = 10;
//告訴平行光需要開啟陰影投射
light.castShadow = true;
scene.add(light);
}
function initModel() {
//輔助工具
var helper = new THREE.AxesHelper(50);
scene.add(helper);
var material = new THREE.MeshStandardMaterial({color:0x00ffff});
//新增立方體
var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
//新增第一個
cube = new THREE.Mesh(geometry, material);
scene.add(cube);
//新增第二個
cube2 = new THREE.Mesh(geometry, material);
cube2.position.set(3, 3, -2);
scene.add(cube2);
//新增第三個
cube3 = new THREE.Mesh(geometry, material);
cube3.position.set(-3, 3, 2);
scene.add(cube3);
}
//初始化效能外掛
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
function initControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
//設定控制器的中心點
//controls.target.set( 0, 5, 0 );
// 如果使用animate方法時,將此函式刪除
//controls.addEventListener( 'change', render );
// 使動畫迴圈使用時阻尼或自轉 意思是否有慣性
controls.enableDamping = true;
//動態阻尼係數 就是滑鼠拖拽旋轉靈敏度
//controls.dampingFactor = 0.25;
//是否可以縮放
controls.enableZoom = true;
//是否自動旋轉
controls.autoRotate = false;
controls.autoRotateSpeed = 0.5;
//設定相機距離原點的最遠距離
controls.minDistance = 1;
//設定相機距離原點的最遠距離
controls.maxDistance = 2000;
//是否開啟右鍵拖拽
controls.enablePan = true;
}
//每幀額外的運算
function render() {
//獲取到視窗的一半高度和一半寬度
let halfWidth = window.innerWidth / 2;
let halfHeight = window.innerHeight / 2;
let vector1 = cube.position.clone().project(camera);
let vector2 = cube2.position.clone().project(camera);
let vector3 = cube3.position.clone().project(camera);
//修改第一個的div的位置
$(".one").css({
left:vector1.x * halfWidth + halfWidth,
top:-vector1.y * halfHeight + halfHeight
});
$(".two").css({
left:vector2.x * halfWidth + halfWidth,
top:-vector2.y * halfHeight + halfHeight
});
$(".three").css({
left:vector3.x * halfWidth + halfWidth,
top:-vector3.y * halfHeight + halfHeight
});
}
//視窗變動觸發的函式
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
//每幀額外的運算
render();
//更新效能外掛
stats.update();
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
function draw() {
//相容性判斷
if (!Detector.webgl) Detector.addGetWebGLMessage();
initGui();
initRender();
initScene();
initCamera();
initLight();
initModel();
initControls();
initStats();
animate();
window.onresize = onWindowResize;
}
</script>
</html>