一、想讓場景動起來,第一個解決的問題就是如何在特定的時間間隔重新渲染場景。
之前是使用setInterval方法。比如每個100ms執行一次。但是這會導致較高的CPU使用率和性能不良。
現代瀏覽器提供了在特定時間間隔重新渲染場景的解決方案:即requestAnimationFrame方法。
二、在實現動畫效果之前,先來介紹一個輔助庫,用於檢測動畫運行時幀數。在動畫運行時,該庫可以在一個圖片中顯示畫面每秒傳輸幀數。
①先在head處添加這個js文件
<script type="text/javascript" src="../libs/stats.js"></script>
②添加div用於顯示統計圖形。
<div id="Stats-output">
</div>
③初始化統計對象,將該對象添加到div元素中(整個方法一般不會變)
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
④在init方法裏面調用initStats()
function init(){
var stats = initStats()
}
完成以上步驟就可以看到屏幕左上角這個東西。
⑤動畫要添加如下代碼:
function renderScene() {
stats.update();
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
document.getElementById('WebGL-output').appendChild(renderer.domElement);
renderer.render(scene,camera);
renderScene();
想讓球旋轉起來,則:
⑥在創建三維場景和動畫時,我們需要嘗試很多次才能確定最合適的速度和顏色,如果有一個GUI(可視化圖形界面)允許我們在運行期間修改這些屬性。
⑦添加這個js
<script type="text/javascript" src="../libs/dat.gui.js"></script>
⑧定義一個對象,該對象將保存希望通過該dat.GUI改變的屬性。
var controls = new function(){
this.rotationSpeed = 0.02;
}
var gui = new dat.GUI(); //
gui.add(controls,'rotationspeed',0,0.5);
在render方法裏面,將0.02用controls.rotationSpeec替代
function renderScene() {
stats.update();
console.log(controls)
// 讓球繞x軸旋轉起來
sphere1.rotation.x += controls.rotationSpeed
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
<!--
* @Author: your name
* @Date: 2018-09-17 05:22:00
* @LastEditTime: 2021-04-03 16:33:56
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /learning-threejs-master/chapter-01/01-basic-skeleton.html
-->
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to
use the complete page */
/*將邊距設置爲0並溢出到隱藏的使用整個頁面*/
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>
<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight);
var renderer = new THREE.WebGLRenderer();
var spotLight = new THREE.SpotLight(0xff4400);
spotLight.position.set(10,100,60);
spotLight.castShadow = true;
scene.add(spotLight)
// 設置背景色和背景大小
renderer.setClearColorHex();
renderer.setClearColor(new THREE.Color("#ccc"));
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.shadowMapEnabled = true; // 開啓陰影
// create the ground plane 創建地平面
var planeGeometry = new THREE.PlaneGeometry(60, 20);
// 創建面板顏色
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
// rotate and position the plane
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
// add the plane to the scene
scene.add(plane);
// 定義一個球體
var sphereGeometry = new THREE.SphereGeometry(2,20,20);
var sphereMaterial = new THREE.MeshLambertMaterial({color:0xffffff,wireframe:true})
var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);
scene.add(sphere);
sphere.position.x = 0;
sphere.position.y = 2;
sphere.position.z = 0;
sphere.castShadow = true;
// 定義一個球體
var sphereGeometry1 = new THREE.SphereGeometry(2,20,20);
var sphereMaterial1 = new THREE.MeshBasicMaterial({color:0xff0000,wireframe:false})
var sphere1 = new THREE.Mesh(sphereGeometry,sphereMaterial);
scene.add(sphere1);
sphere1.position.x = 0;
sphere1.position.y = 10;
sphere1.position.z = 0;
sphere1.castShadow = true;
camera.position.x = 20;
camera.position.y = 20;
camera.position.z = 20;
camera.lookAt(scene.position);
document.getElementById('WebGL-output').appendChild(renderer.domElement);
renderer.render(scene,camera);
var controls = new function(){
this.rotationSpeed = 0.02;
}
var gui = new dat.GUI(); //
gui.add(controls,'rotationSpeed',0,0.5);
renderScene();
function renderScene() {
stats.update();
console.log(controls)
// 讓球繞x軸旋轉起來
sphere1.rotation.x += controls.rotationSpeed
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init
</script>
</body>
</html>