一架忌、首先我們需要創(chuàng)建一個Vue工程
本文主要詳細(xì)記錄搭建全景圖的過程,故搭建Vue工程不在過多描述我衬。
二叹放、安裝Three.js
npm install three --save
npm install three-trackballcontrols --save
npm install three-orbit-controls --save
npm i three-obj-mtl-loader --save
npm i three-fbx-loader --save
npm i three-stats --save
three-trackballcontrols:軌跡球控件,最常用的控件挠羔,可以使用鼠標(biāo)輕松的移動井仰、平移,縮放場景破加。
three-orbit-controls :三維場景操作插件俱恶。其實在 npm install three 的時候已經(jīng)下載對應(yīng)的插件, 在 node_modules 文件夾下找到 three/examples/jsm/controls/OrbitControls 這個路徑里面也能找到對應(yīng)的插件范舀。
three-obj-mtl-loader:加載 .obj 模型文件 , .mtl 材質(zhì)信息文件的插件合是。
three-fbx-loader:fbx模型文件的插件。
three-stats:性能檢測插件锭环,可以監(jiān)控動畫運(yùn)行的幀數(shù)聪全。
三、渲染器-renderer辅辩, 場景-scene难礼,相機(jī)-camera
??Three.js中吱七,場景可理解為是一個容器,我們可以將需要的物體放入場景中鹤竭。相機(jī)的作用在場景中取一個合適的景踊餐,把它拍下來。渲染器的作用就是將相機(jī)拍攝下來的圖片臀稚,渲染至瀏覽器展示吝岭。
四、具體實現(xiàn)
- 引入依賴
import * as THREE from "three";
import * as ThreeStats from 'three-stats'
const OrbitControls = require('three-orbit-controls')(THREE);
- 定義變量
data() {
return {
renderer: '', //渲染器
scene: '', //場景
light: '', //光源
camera: '', //相機(jī)
controls: '', //控制器
stats: '', //性能監(jiān)控器
mygroup: '', //模型組
action: '', //控制動畫的值
clock: '', //時鐘
mixer: '', //混合實例
rotateAnimate: '', //旋轉(zhuǎn)動畫
sRotate: 1, //是否開啟旋轉(zhuǎn)
}
}
- 初始化渲染器
rendererInit() {
var width = 1000;
var height = 800;
this.renderer = new THREE.WebGLRenderer();
this.renderer.setClearColor(0xffffff);
this.renderer.setSize(width, height);
// 通過 this.$refs獲取頁面的dom并綁定渲染器
this.$refs.threeDom.appendChild(this.renderer.domElement);
}
- 初始化場景
sceneInit() {
this.scene = new THREE.Scene();
var ambient = new THREE.AmbientLight(0x444444, 3); //添加光源 顏色和光照強(qiáng)度
var axisHelper = new THREE.AxesHelper(600); //添加輔助坐標(biāo)系
this.scene.add(ambient, axisHelper);
},
AmbientLight:環(huán)境光吧寺,會均勻的照亮場景中的所有物體窜管。不能用來投射陰影,因為它沒有方向稚机。
AmbientLight( color : Integer, intensity : Float )
color - (參數(shù)可選)顏色的rgb數(shù)值幕帆。缺省值為 0xffffff。
intensity - (參數(shù)可選)光照的強(qiáng)度赖条。缺省值為 1失乾。
AxesHelper:用于簡單模擬3個坐標(biāo)軸的對象。紅色代表 X 軸纬乍,綠色代表 Y 軸碱茁,藍(lán)色代表 Z 軸。
AxesHelper( size : Number )
size -- (可選的) 表示代表軸的線段長度. 默認(rèn)為 1仿贬。
- 創(chuàng)建模型
modelling(){
this.mygroup = new THREE.Group();
var textureLoader = new THREE.TextureLoader(); //創(chuàng)建紋理貼圖
var img = textureLoader.load(require('../../public/img/home3.jpeg'));
var geometry = new THREE.SphereGeometry(130, 256, 256); // 球體網(wǎng)格模型
var material = new THREE.MeshLambertMaterial({
map: img, //設(shè)置顏色貼圖屬性值
side: THREE.DoubleSide, //雙面渲染
});
var meshSphere = new THREE.Mesh(geometry, material); //網(wǎng)格模型對象Mesh
meshSphere.name = '球體容器';
this.mygroup.add(meshSphere);
var canvasText = this.getcanvers('進(jìn)門'); //生成一個canvers 文字圖案對象
var texture = new THREE.CanvasTexture(canvasText);
var geometryText = new THREE.PlaneGeometry(16, 10, 60, 60);
var materialText = new THREE.MeshPhongMaterial({
map: texture, // 設(shè)置紋理貼圖
side: THREE.DoubleSide, //雙面渲染
});
var meshText = new THREE.Mesh(geometryText, materialText);
meshText.name = '進(jìn)門';
meshText.position.set(40, 20, -90)
this.mygroup.add(meshText);
this.scene.add(this.mygroup);
this.addAnimation(); //添加并開啟動畫
this.refresh();
}
// 生成一個canvers圖案
getcanvers(text) {
var canvasText = document.createElement("canvas");
var c = canvasText.getContext('2d');
// 矩形區(qū)域填充背景
c.fillStyle = "#FFFFFF"; //canver背景
c.fillRect(0, 0, 300, 200); //生成一個矩形
c.translate(160, 80);
c.fillStyle = "#000000"; //文本填充顏色
c.font = "bold 100px 宋體"; //字體樣式設(shè)置
c.textBaseline = "middle"; //文本與
c.textAlign = "center"; //文本居中
c.fillText(text, 0, 0);
return canvasText;
}
SphereGeometry:一個用于生成球體的類纽竣。
SphereGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float, thetaLength : Float)
radius — 球體半徑,默認(rèn)為1茧泪。
widthSegments — 水平分段數(shù)(沿著經(jīng)線分段)蜓氨,最小值為3,默認(rèn)值為8队伟。
heightSegments — 垂直分段數(shù)(沿著緯線分段)穴吹,最小值為2,默認(rèn)值為6缰泡。
phiStart — 指定水平(經(jīng)線)起始角度刀荒,默認(rèn)值為0代嗤。棘钞。
phiLength — 指定水平(經(jīng)線)掃描角度的大小,默認(rèn)值為 Math.PI * 2干毅。
thetaStart — 指定垂直(緯線)起始角度宜猜,默認(rèn)值為0。
thetaLength — 指定垂直(緯線)掃描角度大小硝逢,默認(rèn)值為 Math.PI姨拥。
MeshLambertMaterial:一種非光澤表面的材質(zhì)绅喉,沒有鏡面高光。
MeshLambertMaterial( parameters : Object )
.map : Texture叫乌。顏色貼圖柴罐。默認(rèn)為null。
.side : Integer憨奸。定義將要渲染哪一面 - 正面革屠,背面或兩者。 默認(rèn)為THREE.FrontSide排宰。其他選項有THREE.BackSide和THREE.DoubleSide似芝。
CanvasTexture:從Canvas元素中創(chuàng)建紋理貼圖。
PlaneGeometry: 一個用于生成平面幾何體的類板甘。
MeshPhongMaterial:一種用于具有鏡面高光的光澤表面的材質(zhì)党瓮。
- 初始化相機(jī)
cameraInit() {
var width = 800; //窗口寬度
var height = 800; //窗口高度
this.camera = new THREE.PerspectiveCamera(90, width / height, 1, 1000); //使用透視相機(jī)
this.camera.position.set(0, 0, 10); //設(shè)置相機(jī)位置
this.camera.lookAt(new THREE.Vector3(0, 0, 0)); // 相機(jī)看向
}
PerspectiveCamera:透視相機(jī)。
PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )
fov — 攝像機(jī)視錐體垂直視野角度
aspect — 攝像機(jī)視錐體長寬比
near — 攝像機(jī)視錐體近端面
far — 攝像機(jī)視錐體遠(yuǎn)端面
- 初始化控制器(三維場景操作插件)
controlInit() {
this.controls = new OrbitControls(this.camera, this.$refs.threeDom); // 初始化控制器
this.controls.target.set(0, 0, 0); // 設(shè)置控制器的焦點(diǎn)盐类,使控制器圍繞這個焦點(diǎn)進(jìn)行旋轉(zhuǎn)
this.controls.minDistance = 10; // 設(shè)置移動的最短距離(默認(rèn)為零)
this.controls.maxPolarAngle = Math.PI; //繞垂直軌道的距離(范圍是0-Math.PI,默認(rèn)為Math.PI)
this.controls.maxDistance = 30; // 設(shè)置移動的最長距離(默認(rèn)為無窮)
this.controls.enablePan = false; //禁用右鍵功能
this.controls.addEventListener('change', this.refresh); //監(jiān)聽鼠標(biāo)寞奸、鍵盤事件 讓整個控件可以拖動
},
- 旋轉(zhuǎn)動畫
addAnimation() {
this.clock = new THREE.Clock();
var times = [0, 3600]; // 創(chuàng)建幀動畫序列
var position_x = [0, 360];
var keyframe = new THREE.KeyframeTrack('meshSphere.rotation[y]', times, position_x);
var duration = 100; //持續(xù)時間
var cilp = new THREE.AnimationClip('sphereRotate', duration, [keyframe]); //剪輯 keyframe對象
this.mixer = new THREE.AnimationMixer(this.mygroup); //動畫混合實例
this.action = this.mixer.clipAction(cilp);
this.action.timeScale = 1; //播放速度
this.action.setLoop(THREE.LoopPingPong).play(); //開始播放 像乒乓球一樣在起始點(diǎn)與結(jié)束點(diǎn)之間來回循環(huán)
this.animate(); //開啟動畫
},
// 循環(huán)渲染
animate() {
this.rotateAnimate = requestAnimationFrame(this.animate);
this.renderer.render(this.scene, this.camera);
this.update();
},
Clock:用于跟蹤時間。
KeyframeTrack:關(guān)鍵幀軌道(KeyframeTrack)是關(guān)鍵幀(keyframes)的定時序列, 它由時間和相關(guān)值的列表組成, 用來讓一個對象的某個特定屬性動起來在跳。
KeyframeTrack( name : String, times : Array, values : Array, interpolation : Constant )
name - 關(guān)鍵幀軌道(KeyframeTrack)的標(biāo)識符蝇闭。
times - 關(guān)鍵幀的時間數(shù)組, 被內(nèi)部轉(zhuǎn)化為 Float32Array。
values - 與時間數(shù)組中的時間點(diǎn)相關(guān)的值組成的數(shù)組, 被內(nèi)部轉(zhuǎn)化為 Float32Array硬毕。
interpolation - 使用的插值類型呻引。
AnimationClip:動畫剪輯(AnimationClip)是一個可重用的關(guān)鍵幀軌道集,它代表動畫吐咳。
AnimationClip( name : String, duration : Number, tracks : Array )
name - 此剪輯的名稱逻悠。
duration - 持續(xù)時間 (單位秒)。如果傳入負(fù)數(shù), 持續(xù)時間將會從傳入的數(shù)組中計算得到韭脊。
tracks - 一個由關(guān)鍵幀軌道(KeyframeTracks)組成的數(shù)組童谒。
AnimationMixer:動畫混合器是用于場景中特定對象的動畫的播放器。當(dāng)場景中的多個對象獨(dú)立動畫時沪羔,每個對象都可以使用同一個動畫混合器饥伊。
- 最后初始化加載
init() {
this.$refs.threeDom.addEventListener('dblclick', this.onMouseDblclick); //監(jiān)聽雙擊事件
this.rendererInit(); //創(chuàng)建渲染器
this.sceneInit(); //創(chuàng)建場景 包含光源和輔助坐標(biāo)系
this.cameraInit(); //創(chuàng)建相機(jī)
this.controlInit(); //初始化控制器
this.propertyInit(); //性能監(jiān)控
this.modelling(); //建立模型
}
參考文章:
https://juejin.cn/post/6927193628724953096
https://blog.csdn.net/ithanmang/article/details/84062933