123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- <template>
- <div>
- <div id="containerThreeVehicleModel"></div>
- </div>
- </template>
- <script>
- import * as THREE from "three";
- import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
- import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
- import {
- showFullScreenLoading,
- tryHideFullScreenLoading,
- } from "../../../axios/filter";
- import { mapState } from "vuex";
- export default {
- name: "threeVehicleModel", // 动力学配置中的threeJS
- data() {
- return {
- publicPath: process.env.BASE_URL,
- scene: null,
- camera: null,
- renderer: null,
- light: null,
- geometryName: null,
- controls: null,
- mesh: null,
- cube: null,
- container: null,
- car: null,
- cubeTexture: null,
- raf: null,
- // scale: 2, // 物体加载换算倍数
- };
- },
- computed: {
- ...mapState(["scale", "scaleRate"]),
- },
- props: {
- carModel: {
- type: String,
- default: "",
- },
- },
- watch: {
- carModel(newVal, oldVal) {
- if (newVal != oldVal) {
- this.initCar(newVal);
- }
- },
- },
- methods: {
- // 场景
- initScene() {
- this.scene = new THREE.Scene();
- const gridHelper = new THREE.GridHelper(1000, 100);
- gridHelper.material.opacity = 0.25;
- gridHelper.material.transparent = true;
- this.scene.add(gridHelper);
- },
- // 相机
- initCamera() {
- this.camera = new THREE.PerspectiveCamera(
- 75,
- this.container.clientWidth / this.container.clientHeight,
- 0.1,
- 1000
- );
- this.camera.position.set(200, 200, 200);
- this.scene.add(this.camera);
- },
- // 渲染器
- initRenderer() {
- this.renderer = new THREE.WebGLRenderer({
- antialias: true,
- alpha: true,
- });
- this.renderer.setSize(
- this.container.clientWidth,
- this.container.clientHeight
- );
- this.renderer.setClearColor("#272727");
- this.container.appendChild(this.renderer.domElement);
- },
- // 初始化灯光
- initLight() {
- var hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
- hemiLight.position.set(0, 20, 0);
- this.scene.add(hemiLight);
- // 环境光会均匀的照亮场景中的所有物体
- const light = new THREE.AmbientLight(0x5c5c5c, 0.4); // soft white light
- this.scene.add(light);
- // 平行光是沿着特定方向发射的光
- const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
- this.scene.add(dirLight);
- },
- // 初始化车模型
- initCar(model) {
- if (this.car) {
- this.scene.remove(this.car);
- this.removeObj(this.car);
- this.car = null;
- }
- if (!model) return;
- if (!model.includes(".glb")) return;
- let that = this;
- let loader = new GLTFLoader();
- showFullScreenLoading();
- loader.load(
- model,
- function (obj) {
- tryHideFullScreenLoading();
- obj.scene.rotation.set(
- (-90 * Math.PI) / 180,
- 0,
- (-180 * Math.PI) / 180
- );
- let s = 0;
- if (model.includes("928.glb")) {
- s = that.scale / that.scaleRate;
- } else {
- s = that.scale;
- }
- let scale = 30 * s;
- obj.scene.scale.set(scale, scale, scale);
- that.scene.add(obj.scene);
- that.car = obj.scene;
- },
- (xhr) => {
- // console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
- },
- (error) => {
- tryHideFullScreenLoading();
- console.error(error);
- }
- );
- },
- // 初始化
- init() {
- this.initScene();
- this.initCamera();
- this.initRenderer();
- this.initLight();
- this.controls = new OrbitControls(
- this.camera,
- this.renderer.domElement
- ); //创建控件对象
- this.controls.minDistance = 30;
- this.controls.maxDistance = 600;
- this.controls.update();
- },
- animate() {
- this.raf = requestAnimationFrame(this.animate);
- this.renderer.render(this.scene, this.camera);
- this.controls.update();
- },
- onWindowResize() {
- this.camera.aspect =
- this.container.clientWidth / this.container.clientHeight;
- this.camera.updateProjectionMatrix();
- this.renderer.setSize(
- this.container.clientWidth,
- this.container.clientHeight
- );
- },
- go() {
- this.container = document.getElementById(
- "containerThreeVehicleModel"
- );
- this.init();
- this.animate();
- window.addEventListener("resize", this.onWindowResize);
- },
- removeScene() {
- this.clearScene();
- },
- clearCache(item) {
- if (item.geometry && item.geometry.dispose) item.geometry.dispose();
- if (item.material && item.material.dispose) item.material.dispose();
- },
- clearScene() {
- this.removeObj(this.scene);
- },
- removeObj(obj) {
- let arr = obj.children.filter((x) => x);
- arr.forEach((item) => {
- if (item.children.length) {
- this.removeObj(item);
- } else {
- this.clearCache(item);
- item.clear();
- }
- }),
- obj.clear();
- arr = null;
- },
- },
- mounted() {
- this.go();
- },
- destroyed() {
- window.removeEventListener("resize", this.onWindowResize);
- cancelAnimationFrame(this.raf);
- if (this.renderer) {
- this.renderer.renderLists.dispose();
- this.renderer.dispose();
- this.renderer.forceContextLoss();
- this.renderer.domElement = null;
- this.renderer.content = null;
- this.renderer = null;
- }
- if (this.controls) {
- this.controls.dispose();
- this.controls = null;
- }
- this.clearScene();
- this.scene = null;
- this.camera = null;
- this.light = null;
- this.geometryName = null;
- this.mesh = null;
- this.cube = null;
- this.container = null;
- this.car = null;
- this.cubeTexture = null;
- this.raf = null;
- THREE.Cache.clear();
- },
- };
- </script>
- <style lang="less" scoped>
- #containerThreeVehicleModel {
- width: 100%;
- height: calc(100vh - 180px);
- }
- </style>
|