当前位置:网站首页>用Three.js做一個簡單的3D場景
用Three.js做一個簡單的3D場景
2022-07-03 03:17:00 【抱緊北方】
Three.js是什麼
Three.js 是一款運行在瀏覽器中的 3D 引擎,我們可以用它來創造我們所需要的一系列3D動畫場景,簡而言之就是建在網頁上的3D模型。利用Three.js可以制作出很多酷炫的3D動畫,並且Three.js還可以通過鼠標、鍵盤、拖拽等事件形成交互,在頁面上增加一些3D動畫和3D交互可以產生更好的用戶體驗。
Three.js程序結構
主要分為三大結構:場景Scene 相機Camera 渲染器Renderer
程序整個運行的過程就是:先加載場景—— 然後相機——最後渲染器

從實際生活中拍照角度理解,立方體網格模型和光照組成了一個虛擬的三維場景類似你要拍攝的物體,相機對象就像你生活中使用的相機一樣可以拍照,只不過一個是拍攝真實的景物,一個是拍攝虛擬的景物,拍攝一個物體的時候相機的比特置和角度需要調整,虛擬的相機還需要設置投影方式,當你創建好一個三維場景,相機也設置好,就差一個動作“哢”,通過渲染器就可以執行拍照動作了
簡單理解了用Three.js做3D引擎的原理,那今天我們就來做一個簡單的3D立方體吧
立方體
首先我們要在html文件中引入three.js,就像引入其它.js文件一樣直接引入,它需要去官網下載
這裏,我用的是相對路徑

或者引用相對路徑
<!--絕對路徑遠程加載-->
<script src="http://www.yanhuangxueyuan.com/3D/example/three.js"></script>
<!-- 壓縮版本 -->
<script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>然後,在body裏插入代碼段就可以了,具體代碼解釋如下:
<body>
<script>
// 創建場景對象Scene
var scene = new THREE.Scene();
//創建網格模型
// var geometry = new THREE.SphereGeometry(60, 40, 40); //創建一個球體幾何對象
var geometry = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象
var material = new THREE.MeshLambertMaterial({ //創建材質對象Material
color: 0x008080 //立方體的顏色
});
var mesh = new THREE.Mesh(geometry, material); //創建網格模型對象Mesh
scene.add(mesh); //將網格mesh模型添加到場景中
// 光源設置
//點光源
var point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300); //點光源的比特置
scene.add(point); //點光源添加到場景中
//環境光
var ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);
// console.log(scene)
// console.log(scene.children)
// 相機設置
var width = window.innerWidth; //窗口寬度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口寬高比
var s = 200; //三維場景顯示範圍控制系數,系數越大,顯示的範圍越大
//創建相機對象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); //設置相機比特置
camera.lookAt(scene.position); //設置相機方向(指向的場景對象)
// 創建渲染器對象
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);//設置渲染區域尺寸
renderer.setClearColor(0xb9d3ff, 1); //設置背景顏色
document.body.appendChild(renderer.domElement); //body元素中插入canvas對象
//執行渲染操作 指定場景、相機作為參數
renderer.render(scene, camera);
</script>
</body>展示效果:

旋轉動畫
做到這裏,只是在網頁上呈現一個不動的3D立方體,為了增加趣味性和操作性,我們可以將渲染操作封裝成一個函數,用setInterval讓它間隔20ms周期性地調用render()渲染函數、不斷地刷新
// 渲染函數
function render() {
renderer.render(scene,camera);//執行渲染操作
mesh.rotateY(0.01);//每次繞y軸旋轉0.01弧度
}
//間隔20ms周期性調用渲染函數render()
setInterval("render()",20);這裏的時間單比特是ms,20ms也就是刷新頻率為50FPS(1s/20ms),即1s內屏幕刷新50次(相信打遊戲的小夥伴都不陌生)
展示效果如下:

或者也可以通過requestAnimationFrame請求再次執行渲染函數render,渲染下一幀,這樣也可以達到不斷刷新,旋轉的效果
// 渲染函數
let T0 = new Date();//上次時間
function render() {
let T1 = new Date();//本次時間
let t = T1-T0;//時間差
console.log(t);//兩幀之間時間間隔 單比特:ms
T0 = T1;//把本次時間賦值給上次時間
renderer.render(scene,camera);//執行渲染操作
mesh.rotateY(0.01);//每次繞y軸旋轉0.01弧度
requestAnimationFrame(render);//請求再次執行渲染函數render,渲染下一幀
}
render();我們可以創建兩個臨時變量T1和T0去記錄本次執行渲染和上次執行渲染所需時間,再將他們相减,就得到了兩幀之間的時間間隔,發現穩定在17ms左右,58的fps,相較於我們自己設置的時間周期,它的fps更高,也沒有局限性
展示效果如下:

鼠標操作三維場景旋轉縮放
我們已經實現了讓立方體機械性的動了起來,那可不可以通過鼠標來操控,讓它可以轉到任意我們想要的角度和比特置呢
首先,我們還需要引入一個新的Threejs擴展控件——OrbitControls.js,它叫軌道控件,用它可以實現場景用鼠標交互,讓場景動起來,控制場景的旋轉、平移和縮放
<!-- 引入軌道控件OrbitControls.js -->
<!-- 相對路徑 -->
<script src="./OrbitControls.js"></script>
<!-- 絕對路徑 -->
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>這裏,軌道控件提供了一個構造函數,我們創建一個新的構造函數,再添加一個鼠標監聽事件,鼠標有所動作,觸發渲染函數,立方體會執行相應的效果
// 渲染函數
function render() {
renderer.render(scene, camera); //執行渲染操作
}
render();
//創建控件對象 相機對象camera作為參數 控件可以監聽鼠標的變化,改變相機對象的屬性
var controls = new THREE.OrbitControls(camera,renderer.domElement);
//監聽鼠標事件,觸發渲染函數,更新canvas畫布渲染效果
controls.addEventListener('change', render);展示效果:

實際上軌道控件還有很多屬性可以設置,但在本小例中沒有應用到,詳細的用法可參考官方文檔:點擊打開鏈接
边栏推荐
- [algebraic structure] group (definition of group | basic properties of group | proof method of group | commutative group)
- 监听对象中值变化及访问
- Do you really understand relays?
- Pat class B common function Usage Summary
- Force deduction ----- the minimum path cost in the grid
- Spark on yarn资源优化思路笔记
- C # general interface call
- MySQL practice 45 lecture [row lock]
- Stepping on pits and solutions when using inputfilter to limit EditText
- Why does thread crash not cause JVM crash
猜你喜欢

Idea set method call ignore case
![MySQL practice 45 lecture [transaction isolation]](/img/a5/5420651d6be51e892976f02be8c43c.png)
MySQL practice 45 lecture [transaction isolation]

Installation and use of memory leak tool VLD

Vs 2019 configuration tensorrt

The idea cannot be loaded, and the market solution can be applied (pro test)

Idea format code idea set shortcut key format code

I2C subsystem (I): I2C spec

Docker install MySQL

Opengauss database development and debugging tool guide

用Three.js做一个简单的3D场景
随机推荐
Yiwen takes you to know ZigBee
Hi3536c v100r001c02spc040 cross compiler installation
二维数组中的元素求其存储地址
Update and return document in mongodb - update and return document in mongodb
Nce detail of softmax approximation
The series of hyperbolic function in daily problem
Spark on yarn resource optimization ideas notes
C#通用接口调用
idea 加载不了应用市场解决办法(亲测)
Edit and preview in the back pipe to get the value writing method of the form
Are there any recommended term life insurance products? I want to buy a term life insurance.
MySql實戰45講【SQL查詢和更新執行流程】
[mathematical logic] predicate logic (individual word | individual domain | predicate | full name quantifier | existence quantifier | predicate formula | exercise)
Opengauss database development and debugging tool guide
Elsevier latex 提交文章 pdftex.def Error: File `thumbnails/cas-email.jpeg‘ not found: using draf
The XML file generated by labelimg is converted to VOC format
Application of derivative in daily question
Lvgl usage experience
The calculation of stripe, kernel and padding in CNN
二进制流转换成字节数组