vue中使用Three.js

2023-06-15-11-25-56

1.安装

npm install three

2.引入

// 方式 1: 导入整个 three.js核心库
import * as THREE from 'three';

const scene = new THREE.Scene();


// 方式 2: 仅导入你所需要的部分
import { Scene } from 'three';

const scene = new Scene();

3.vue中使用

<template>
    <div class="SimpleExampleViewPage">
        <div class="SimpleExampleViewPageOutbox">
            <div class="mythreedemojsdiv" ref="MyThreeJsContainer">
            </div>
        </div>
    </div>
</template>
<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
export default {
    name: "SimpleExampleViewPage",
    data() {
        return {
            MyThreeJsContainer: null,
            ThreeJsConfig: {
                WBGLCanvasWidth: null,
                WBGLCanvasHeight: null,
                scene: null,
                camera: null,
                renderer: null,
                clock: null,
                controls: null
            },
            RequestAnimationFrameVal: null
        }
    },
    mounted() {
        this.$nextTick(() => {
            this.Draw()

        })
    },
    beforeDestroy() {
        this.dispose();
    },
    methods: {
        InitThreeJsRendererFun() {
            this.MyThreeJsContainer = this.$refs.MyThreeJsContainer
            this.ThreeJsConfig.WBGLCanvasWidth = this.MyThreeJsContainer.getBoundingClientRect().width
            this.ThreeJsConfig.WBGLCanvasHeight = this.MyThreeJsContainer.getBoundingClientRect().height
            console.log(`this.ThreeJsConfig.WBGLCanvasWidth `, this.ThreeJsConfig.WBGLCanvasWidth);
            this.ThreeJsConfig.scene = new THREE.Scene()
            const light = new THREE.DirectionalLight(0xFFFFFF, 1);
            light.position.set(-1, 2, 4);
            this.ThreeJsConfig.scene.add(light);
            this.ThreeJsConfig.camera = new THREE.PerspectiveCamera(75, this.ThreeJsConfig.WBGLCanvasWidth / this.ThreeJsConfig.WBGLCanvasHeight, 0.1, 1000);
            this.ThreeJsConfig.camera.position.z = 5
            this.ThreeJsConfig.camera.lookAt(this.ThreeJsConfig.scene.position)
            this.ThreeJsConfig.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
            this.ThreeJsConfig.renderer.setSize(this.ThreeJsConfig.WBGLCanvasWidth, this.ThreeJsConfig.WBGLCanvasHeight)
            this.ThreeJsConfig.renderer.setClearColor('#fff')
            this.ThreeJsConfig.renderer.shadowMap.enabled = true; // 显示阴影
            this.ThreeJsConfig.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            this.MyThreeJsContainer.appendChild(this.ThreeJsConfig.renderer.domElement);
            this.ThreeJsConfig.clock = new THREE.Clock(); //创建THREE.Clock对象,用于计算上次调用经过的时间
            this.ThreeJsConfig.controls = new OrbitControls(this.ThreeJsConfig.camera, this.ThreeJsConfig.renderer.domElement);
            this.ThreeJsConfig.controls.autoRotate = true; //是否自动旋转
            return this.ThreeJsConfig
        },
        PromiseFun(fun = fun()) {
            return new Promise((resolve, reject) => {
                let res = fun()
                resolve(res)
            })
        },
        Draw() {
            this.PromiseFun(this.InitThreeJsRendererFun)
                .then(() => {
                    console.log(`this.ThreeJsConfig`, this.ThreeJsConfig);
                    this.PromiseFun(this.AllDrawFun)
                        .then(() => {
                            this.ThreeJsConfig.renderer.render(this.ThreeJsConfig.scene, this.ThreeJsConfig.camera);
                            this.UpdateFun()
                        })
                })

        },
        //所有绘制图形方法
        AllDrawFun() {
            this.OnWindowResize()
            this.DblclickFullscreenFun()
            this.CreatePlaneGeometry()
            this.CreateBoxGeometry()
            this.CreateLine()
        },
        //设置动画
        UpdateFun() {
            this.ThreeJsConfig.PlaneGeometryTexture.offset.x += 0.05;
            this.ThreeJsConfig.renderer.render(this.ThreeJsConfig.scene, this.ThreeJsConfig.camera);
            this.RequestAnimationFrameVal = requestAnimationFrame(() => {
                this.UpdateFun()
            })
        },
        //销毁
        dispose() {
            if (this.MyThreeJsContainer) {
                this.CancelAnimationFun()
                this.MyThreeJsContainer.parentNode.removeChild(this.MyThreeJsContainer);
                this.MyThreeJsContainer = null

            }
        },
        //取消动画
        CancelAnimationFun() {
            cancelAnimationFrame(this.RequestAnimationFrameVal)
            this.RequestAnimationFrameVal = null
        },
        //画布自适应
        OnWindowResize() {
            //监听画面变化,更新渲染画面,(自适应的大小)
            window.addEventListener('resize', () => {
                this.ThreeJsConfig.WBGLCanvasWidth = this.MyThreeJsContainer.getBoundingClientRect().width
                this.ThreeJsConfig.WBGLCanvasHeight = this.MyThreeJsContainer.getBoundingClientRect().height
                this.WindowResizeResetViewFun()
            })
        },
        WindowResizeResetViewFun() {
            //更新摄像机的宽高比
            this.ThreeJsConfig.camera.aspect = this.ThreeJsConfig.WBGLCanvasWidth / this.ThreeJsConfig.WBGLCanvasHeight
            //更新摄像机的投影矩阵
            this.ThreeJsConfig.camera.updateProjectionMatrix()
            //设置渲染器的像素比
            // this.ThreeJsConfig.renderer.setPixelRatio(window.devicePixelRatio);
            this.ThreeJsConfig.renderer.setPixelRatio(2);
            //更新渲染器宽度和高度
            this.ThreeJsConfig.renderer.setSize(this.ThreeJsConfig.WBGLCanvasWidth, this.ThreeJsConfig.WBGLCanvasHeight)
            console.log("画面变化了")
        },
        //画布全屏
        DblclickFullscreenFun() {
            window.addEventListener("dblclick", () => {
                if (document.fullscreenElement) {
                    document.exitFullscreen();
                } else {
                    //document.documentElement.requestFullscreen();
                    this.ThreeJsConfig.renderer.domElement.requestFullscreen();
                }
            })
        },
        //绘制几何图形
        CreatePlaneGeometry() {
            const planeGeometry = new THREE.PlaneGeometry(50, 50, 1, 1);
            const planeMaterial = new THREE.MeshLambertMaterial({
                color: 0x080631,
                transparent: true,
                opacity: 0.8
            });
            const texLoader = new THREE.TextureLoader();
            this.ThreeJsConfig.PlaneGeometryTexture = texLoader.load(require('@/assets/img/tube.png'));
            const material = new THREE.MeshLambertMaterial({
                map: this.ThreeJsConfig.PlaneGeometryTexture,
            });
            this.ThreeJsConfig.PlaneGeometryTexture.wrapS = THREE.RepeatWrapping;
            this.ThreeJsConfig.PlaneGeometryTexture.repeat.x = 50;
            const plane = new THREE.Mesh(planeGeometry, material);
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.set(0, -2, 0);
            this.ThreeJsConfig.scene.add(plane);
        },
        CreateBoxGeometry() {
            const geometry = new THREE.BoxGeometry(1, 1, 1);
            this.ThreeJsConfig.BoxGeometryCubes = [
                this.makeInstance(geometry, 0x8844aa, -2),
                this.makeInstance(geometry, 0x44aa88, 0),
                this.makeInstance(geometry, 0xaa8844, 2),
            ];

        },
        makeInstance(geometry, color, x) {
            const material = new THREE.MeshPhongMaterial({ color });
            const cube = new THREE.Mesh(geometry, material);
            this.ThreeJsConfig.scene.add(cube);
            cube.position.x = x;
            return cube;
        },
        CreateLine() {
            const material = new THREE.LineBasicMaterial({
                color: 0x0000ff
            });
            const points = [];
            points.push(new THREE.Vector3(- 10, 0, 0));
            points.push(new THREE.Vector3(0, 10, 0));
            points.push(new THREE.Vector3(10, 0, 0));
            const geometry = new THREE.BufferGeometry().setFromPoints(points);
            const line = new THREE.Line(geometry, material);
            line.rotation.x = -0.5 * Math.PI;
            line.position.set(0, -2, 0);
            this.ThreeJsConfig.scene.add(line);

        },
    }
}
</script>

<style lang="scss" scoped>
.SimpleExampleViewPage {
    display: flex;
    flex-flow: row nowrap;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;

    .SimpleExampleViewPageOutbox {
        width: 60%;
        height: 60%;
        border: 2px red dashed;

        .mythreedemojsdiv {
            width: calc(100% - 0px);
            height: calc(100% - 0px);
        }
    }
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_37312180/article/details/131170129