vue项⽬中使⽤three.js添加3D模型,模型加载做加载中动画以
及模型作缓存、⿏标点击。。。
⼀、效果预览
⼆、代码页⾯容器
<template>
<div class="main-page">
<div class="center">
<div class="video-show module">
<div class="mx">
<!-- <iframe class="iframehtml" v-if="url" :src="url" frameborder="0" scrolling="no"></iframe> -->
<!-- 遮罩层 -->
<div class="modelMask" v-if="percentageBool">
<div class="marg">
<p>loading 3D model</p>
<div class="elPro">
<el-progress :stroke-width="6" :show-text="false" :percentage="percentage"></el-progress>
</div>
</div>
</div>
<!-- 模型存放区域 -->
<div id="threeContained"></div>
</div>
</div>
</div>
</div>
</template>
意:id为threeContained的div就是模型最终渲染的区域,所以在模型加载容器的时候注意,需要使⽤这个div的宽⾼,不是windows.innerwidth
三、⿏标交互事件(点击模型中的摄像头,获取摄像头的id)
// ⿏标点击事件
selectObject(event){
let container = ElementById('threeContained');
var raycaster = new THREE.Raycaster();
let getBoundingClientRect = BoundingClientRect()
let x = ((event.clientX - getBoundingClientRect.left) / container.offsetWidth) * 2 - 1;// 标准设备横坐标        let y = -((event.clientY - p) / container.offsetHeight) * 2 + 1;// 标准设备纵坐标        let standardVector = new THREE.Vector3(x, y, 1);// 标准设备坐标
// 标准设备坐标转世界坐标
let worldVector = standardVector.unproject(this.camera);
// 射线投射⽅向单位向量(worldVector坐标减相机位置坐标)
let ray = worldVector.sub(this.camera.position).normalize();
// 创建射线投射器对象
let rayCaster = new THREE.Raycaster(this.camera.position, ray);
// 返回射线选中的对象第⼆个参数如果不填默认是false
let intersected = rayCaster.intersectObjects(this.scene.children, true);
if (intersected.length) {
const found = intersected[0];
if(found.object.name == "354713923249152"){
this.$router.push({
path:'/home/monitoring/monitoringVideo',
query:{
id:found.object.name
}
})
}
}
}
四、全部代码贴图
<script>
import { videoList } from "@/api/mainpage";
import * as THREE from "three"; //引⼊Threejs
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Stats from "three/examples/jsm/dule";
// import rtsp2webrtc from '@/components/rtsp2webrtc'
export default {
name: "MainPage",
components: {
// rtsp2webrtc,
},
mounted() {
if(!Item('Admin-Token')){
this.$router.push('/');
return;
}
// 测试地址
/
/ this.$tStream(true, 'rtsp://admin:leinao123@192.168.8.220')
// this.init();
this.clock = new THREE.Clock();
this.init();
// this.animate();
},
data() {
return {
videoList: [],
curIndex: 0,
url: "realsee/ke/BEy832qG8mQDNnOe/1mlg5kWnP4kTkhxh1TaxzDMUG8wYBe4V/#lianjia",      // 模型信息
scene: "",
light: "",
camera: "",
controls: "",
renderer: "",
load: "",
clock: "",
mixer: "",
percentage:0,//进度条数据
percentageBool:true,
meshChildren:[],
};
},
methods: {
// 模型函数开始
init() {
var that = this;
// 加缓存,避免模型再次请求
// abled = true;
var container = ElementById("threeContained");
/
/ 创建场景
// that.scene.background = new THREE.Color(0x8cc7de);
that.scene.background = new THREE.Color("#080e30");
// 创建相机
that.camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
10000
);
// that.camera.position.set( -70, 25, 90 );
/
/ 定位相机,并且指向场景中⼼(这⾥设置的值我是根据模型尺⼨来写的,其实应该是动态获取模型长宽⾼后设置相机位置,根据⾃⼰模型⼤⼩来写)      that.camera.position.x = 800;
that.camera.position.y = 520;
that.camera.position.z = 3000;
//设置z轴朝上
// that.camera.up.x = 0;
// that.camera.up.y = 0;
// that.camera.up.z = 1;
that.camera.lookAt(that.scene.position);
// 显⽰三维坐标系
// var axes = new THREE.AxesHelper(100);
// // 添加坐标系到场景中:红⾊是X轴绿⾊是y轴蓝⾊是z轴
// that.scene.add(axes);
// // 创建地⾯的⼏何体
// var planeGeometry = new THREE.PlaneGeometry(800, 1000);
// // 给地⾯物体上⾊
// var planeMaterial = new THREE.MeshStandardMaterial({ color: 0xcccccc });
// // 创建地⾯
// var plane = new THREE.Mesh(planeGeometry, planeMaterial);
// plane.material.opacity = 0.6;
// ansparent = true;
// ation.x = -0.5 * Math.PI;
// plane.position.x = 0;
/
/ plane.position.y = 0;
// plane.position.z = 0;
// plane.castShadow = true;
// // 接收阴影
// iveShadow = true;
// that.scene.add(plane);
// 灯光
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 1, 0);
that.scene.add(hemiLight);
const directionalLight1 = new THREE.DirectionalLight(0xffeeff, 0.8);
directionalLight1.position.set(1, 1, 1);
that.scene.add(directionalLight1);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight2.position.set(-1, 0.5, -1);
that.scene.add(directionalLight2);
const ambientLight = new THREE.AmbientLight(0xffffee, 0.25);
that.scene.add(ambientLight);
// stats消耗资源展⽰
// that.stats = new Stats();
// container.appendChild(that.stats.dom);
// 材质
/
/  const normal = new THREE.TextureLoader().load(
//    "models/shanghai/textures/shanghai.jpg"
//  );
// model
that.loader = new FBXLoader();
// that.loader.load("/models/SHIWAI.FBX",function (geometry) {
// that.loader.load("imgbita/meshes.fbx",function (geometry) {
// that.loader.load("imgbita/fbx/BDZ.FBX", function (geometry) {
that.loader.load("/models/fbx/BDZ.FBX", function (geometry) {
// that.loader.load("imgbita/fbx/newMeshes.fbx", function (geometry) {
that.percentageBool = false;
/
/ geometry.scale.set(0.04, 0.04, 0.04);
geometry.scale.set(0.1,0.1,0.1);
geometry.position.set(0, 36, 0);
that.scene.add(geometry);
that.animate();
},
// onProgress回调
function ( xhr ) {
that.percentage = Math.floor(xhr.loaded / al * 100);
that.$forceUpdate();
// console.log( (xhr.loaded / al * 100) + '% loaded' );
},
// onError回调
function ( err ) {
<( 'An error happened' );
}
);
// 创建渲染器
antialias: true,
logarithmicDepthBuffer: true,
});
// 设置渲染器的初始颜⾊
// 设置输出canvas画⾯的⼤⼩
// derer.setSize(window.innerWidth, window.innerHeight);
container.derer.domElement);
// 控制模型的旋转
const controls = new OrbitControls(that.camera, derer.domElement);
controls.target.set(0, 12, 0);
controls.update();
window.addEventListener("resize", WindowResize);
},
// 窗⼝缩放
onWindowResize() {
var container = ElementById("threeContained");
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
},
// 动画
animate() {
/
/ requestAnimationFrame(this.animate);
// der(this.scene, this.camera);
react router缓存// this.stats.update();
requestAnimationFrame(this.animate);
const delta = Delta();
if (this.mixer) this.mixer.update(delta);
// this.stats.update();
},
// ⿏标点击事件
selectObject(event){
if(this.percentageBool){
return;
}
let container = ElementById('threeContained');
if(!container){
return;
}
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
let getBoundingClientRect = BoundingClientRect()
let x = ((event.clientX - getBoundingClientRect.left) / container.offsetWidth) * 2 - 1;// 标准设备横坐标     
  let y = -((event.clientY - p) / container.offsetHeight) * 2 + 1;// 标准设备纵坐标        let standardVector = new THREE.Vector3(x, y, 1);// 标准设备坐标
// 标准设备坐标转世界坐标
let worldVector = standardVector.unproject(this.camera);
// 射线投射⽅向单位向量(worldVector坐标减相机位置坐标)
let ray = worldVector.sub(this.camera.position).normalize();
// 创建射线投射器对象
let rayCaster = new THREE.Raycaster(this.camera.position, ray);
// 返回射线选中的对象第⼆个参数如果不填默认是false
let intersected = rayCaster.intersectObjects(this.scene.children, true);
if (intersected.length) {
const found = intersected[0];
if(found.object.name == "354713923249152"){
this.$router.push({
path:'/home/monitoring/monitoringVideo',
query:{
id:found.object.name
}
})
}
}
}
},
};
</script>
<style scoped lang="scss">
@import "style/index.scss";
#threeContained {
width: 100%;
height: 100%;
}
.iframehtml {
width: 100%;
height: 100%;
}
.mx {
width: 97.5%;
height: 96%;
margin: 0 auto;
border-radius: 6.5% 6% 6% 6%;
position: absolute;
left: 1.25%;
top: 2%;
overflow: hidden;
// bottom: 5%;
/
/ right: 4%;
.modelMask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
// background: #080e30;
// background: rgba($color: #080e30, $alpha: 0.85);
background: url('~@/assets/images/modelBg.png') no-repeat center center;    background-size: 100% 100%;
z-index: 9;
display: flex;
.marg {
width: 300px;
height: 60px;
margin: auto;
text-align: center;
p {
color: #e2e2e2;
font-size: 13px;
}
.elPro {
width: 100%;
margin-top: 10px;
}
}
}
}
</style>

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。