Vue集成three.js 3D场景渲染示例

  • Demo工程目录结构如下所示
│  .browserslistrc
│  .eslintrc.js
│  .gitignore
│  babel.config.js
│  package-lock.json
│  package.json
│  README.md
│  tsconfig.json
│
├─public
│  │  favicon.ico
│  │  index.html
│  │
│  └─model
│          agvCar.gltf
│          house001.glb
│
└─src
    │  App.vue
    │  main.ts
    │  shims-tsx.d.ts
    │  shims-vue.d.ts
    │
    ├─assets
    │      logo.png
    │
    ├─components
    │      HelloWorld.vue
    │
    ├─router
    │      index.ts
    │
    ├─store
    │      index.ts
    │
    └─views
            About.vue
            Home.vue
  • 导入threejs库
// 当前版本为 "three": "^0.118.3",
npm i three
  • HelloWorld.vue 创建并渲染3D场景主要逻辑
<template>
    <div style="width:100%;height:100%;text-align:center;">
        <div id="threeContent" style="width:1000px;height:800px;margin: 0 auto;"></div>
    </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import {
    Scene,
    PerspectiveCamera,
    Color,
    WebGLRenderer,
    LinearToneMapping,
    AmbientLight,
    DirectionalLight,
    PointLight,
    SpotLight,
    Vector3,
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; // 控制器
import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader'; // gltf文件加载

@Component
export default class HelloWorld extends Vue {
    @Prop() private msg!: string;
    private threeContainer!: HTMLElement;
    private scene!: Scene;
    private camera!: PerspectiveCamera;
    private loader!: GLTFLoader;
    private renderer!: WebGLRenderer;
    private controls!: OrbitControls;

    public created(): void {
        setTimeout(() => {
            this.initScene();
            this.loadModel();
        }, 200);
    }

    public mounted(): void {
        this.startAnimation();
    }

    public initScene() {
        this.threeContainer = document.getElementById(
            'threeContent'
        ) as HTMLElement;

        this.scene = new Scene();
        this.scene.background = new Color(0xccccee);

        //环境光 / 平行光
        this.scene.add(new AmbientLight(0xffffff, 2.5));
        const light = new PointLight(0xdfebff, 1);
        this.scene.add(light);

        // 相机
        this.camera = new PerspectiveCamera(
            45,
            this.threeContainer.clientWidth / this.threeContainer.clientHeight,
            0.1,
            2500
        );
        this.camera.position.copy(new Vector3(-50, 50, 0));
        // this.camera.lookAt(new Vector3(100, 0, 100));
        this.scene.add(this.camera);

        // 渲染器
        this.renderer = new WebGLRenderer({ antialias: true, alpha: true });
        this.renderer.context.getShaderInfoLog = () => '';
        this.renderer.setSize(
            this.threeContainer.scrollWidth,
            this.threeContainer.scrollHeight
        );
        this.renderer.setPixelRatio(devicePixelRatio);
        this.renderer.toneMapping = LinearToneMapping;
        this.renderer.toneMappingExposure = 0.4;

        // 相机控件
        this.controls = new OrbitControls(
            this.camera,
            this.renderer.domElement
        );
        this.controls.minDistance = 10;
        this.controls.maxDistance = 400;
        // 设置相机的lookAt
        this.controls.target.copy(new Vector3(100, 0, 50));

        this.threeContainer.appendChild(this.renderer.domElement);
    }

    public loadModel() {
        this.loader = new GLTFLoader();
        this.loader.load('/model/house001.glb', (obj: GLTF) => {
            this.scene.add(obj.scene);
        });
    }

    public startAnimation() {
        const animation = () => {
            if (this.renderer) {
                this.renderer.render(this.scene, this.camera);
            }
            if (this.controls) {
                this.controls.update();
            }
            requestAnimationFrame(animation);
        };
        animation();
    }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
    margin: 40px 0 0;
}
ul {
    list-style-type: none;
    padding: 0;
}
li {
    display: inline-block;
    margin: 0 10px;
}
a {
    color: #42b983;
}
</style>
  • 演示效果,如图所示:
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/moxiaomomo/article/details/107540481