您现在的位置是:首页 > 正文

Vue-Threejs学习

2024-02-01 03:12:08阅读 2

最近在学习threejs,探索3D开发,主要记录一下学习的过程及遇到的问题,以后续查看,目前主要涉及的也就几个知识点,纹理贴图、2D标签、挖洞、简单动画(开关门)、引入Etharts图表,还未涉及到其它知识点。

最新效果图2020-12-16

在这里插入图片描述
可以打开的门
标签

货架,暂时还不能交互
插入Echarts图表
后台创建的3D对象数据
3d对象编辑界面
材质属性贴图信息

前端代码

import { remoteCallAjaxService } from '@/assets/baseJs/ajaxservice'
import { transtoTree, isNull } from '@/assets/baseJs/Utils'
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer"
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass"
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass"
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass"
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader"
import TWEEN from "tween.js";
import $ from "jquery";

const ThreeBSP = require('three-js-csg')(THREE)
export default {
    name: 'ThreeTest',
    data() {
        return {
            camera: null,
            scene: null,
            renderer: null,
            labelRenderer: null,
            mesh: null,
            pk_h3dscene: null,
            composer: null,
        }
    },
    methods: {
        init() {
            this.test()
            let param = {
                param: JSON.stringify({}),
            }
            //从后台获取场景后开始渲染
            remoteCallAjaxService("h3d.h3dscene", "queryH3dscenes", param).then(response => {
                if (response) {
                    let container = document.getElementById('container')
                    this.scene = new THREE.Scene()
                    let h3dscene = response[0];
                    this.pk_h3dscene = h3dscene.pk_h3dscene;
                    let h3dcameras = h3dscene.cameras;
                    //场景所使用的相机
                    if (h3dcameras) {
                        let camera = h3dcameras[0].pk_h3dcamera_ref;
                        this.camera = new THREE.PerspectiveCamera(camera.fov, window.innerWidth / window.innerHeight, camera.near, camera.far);
                        // this.camera.position.set(parseInt(camera.x), parseInt(camera.y), parseInt(camera.y));
                        this.camera.position.x = camera.x;
                        this.camera.position.y = camera.y
                        this.camera.position.z = camera.z;
                        let lookx = parseFloat(camera.lookatx);
                        let looky = parseFloat(camera.lookaty);
                        let lookz = parseFloat(camera.lookatz);
                        // this.camera.lookAt(new THREE.Vector3(0, 0, 0));
                        // this.camera.position.set(0, 800, 1500);
                        this.camera.lookAt(lookx, looky, lookz);
                        // this.camera.lookAt(new THREE.Vector3(0, 0, 0));
                        // this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
                    }

                    this.initH3dobjs();
                    // 一个测试立方体
                    let geometry = new THREE.BoxGeometry(100, 100, 100)
                    let material = new THREE.MeshNormalMaterial()
                    this.mesh = new THREE.Mesh(geometry, material)
                    this.mesh.position.set(0, 500, 0);
                    this.scene.add(this.mesh)

                    // var point = new THREE.PointLight(0xffffff);
                    // point.position.set(400, 200, 300); //点光源位置
                    // // 通过add方法插入场景中,不插入的话,渲染的时候不会获取光源的信息进行光照计算
                    // this.scene.add(point);

                    // 光源,模拟远处类似太阳的光源
                    var directionalLight = new THREE.DirectionalLight(0xffffff, 0.2);
                    directionalLight.color.setHSL(0.1, 1, 0.95);
                    directionalLight.position.set(0, 200, 0).normalize();
                    this.scene.add(directionalLight);
                    // 环境光
                    var ambient = new THREE.AmbientLight(0xffffff, 0.8); //AmbientLight,影响整个场景的光源
                    ambient.position.set(0, 0, 0);
                    this.scene.add(ambient);

                    this.renderer = new THREE.WebGLRenderer({ antialias: true })
                    this.renderer.setSize(window.innerWidth, window.innerHeight)
                    this.renderer.setClearColor(0x4682B4, 1.0);
                    container.appendChild(this.renderer.domElement)

                    this.labelRenderer = new CSS2DRenderer();
                    this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
                    this.labelRenderer.domElement.style.position = "absolute";
                    this.labelRenderer.domElement.style.top = 0;
                    this.labelRenderer.domElement.style.pointerEvents = 'none';
                    container.appendChild(this.labelRenderer.domElement);

                    this.animate()
                    this.initControls();

                    this.composer = this.ThreeJs_Composer(
                        this.renderer,
                        this.scene,
                        this.camera
                    );
                }
            })
            // 加载文字
            // this.initTextTest()
            this.testEcharts()

        },
        initH3dobjs() {
            let param = {
                param: JSON.stringify({ pk_h3dscene: this.pk_h3dscene }),
            }
            //从后台获取场景后开始渲染
            remoteCallAjaxService("h3d.h3dobj", "queryByH3dscenePk", param).then(h3dobjs => {
                if (h3dobjs) {
                    let h3dobjTree = transtoTree(h3dobjs, 'pk_h3dobj', 'pk_parent', 'children');
                    // this.loadH3dobj(h3dobjTree[0], this.scene);
                    for (let i = 0; h3dobjTree && i < h3dobjTree.length; i++) {
                        this.loadH3dobj(h3dobjTree[i], this.scene);
                    }
                }
            })
        },
        loadH3dobj(h3dobj, parent, parenth3dobj) {
            let h3dtype = h3dobj.h3dtype;
            if (h3dtype && h3dtype === 'BoxGeometry') {
                let mesh = this.create3dObject(parenth3dobj, h3dobj);
                if (h3dobj.children && h3dobj.children.length > 0) {
                    let childs = h3dobj.children;
                    // 先进行打洞
                    let bspChilds = []
                    childs.forEach(child => {
                        if (child.bsp) {
                            bspChilds.push(this.create3dObject(h3dobj, child));
                        }
                    });
                    if (bspChilds && bspChilds.length > 0) {
                        mesh = this.createBsp(h3dobj, mesh, bspChilds)
                    }
                    // 打洞之后,需要添加非打洞对象,及打洞对象的下级对象(将打洞对象作为上级的子对象)
                    childs.forEach(child => {

                        if (child.bsp != true) {
                            this.loadH3dobj(child, mesh, h3dobj);
                        }
                        else {
                            let grandsons = child.children
                            if (grandsons && grandsons.length > 0) {
                                // 处理打洞对象的子对象,需要将打洞对象设置为透明,再次添加到打洞后的对象上,再添加其子对象
                                let childobj = this.create3dObject(null, child, true);
                                mesh.add(childobj)
                                grandsons.forEach(grandson => {
                                    this.loadH3dobj(grandson, childobj, child)
                                })
                            }
                        }
                    });
                }
                if (h3dobj.axeshelper) {
                    var axes0 = new THREE.AxesHelper(3000); // 坐标轴
                    axes0.name = "axes";
                    mesh.add(axes0);
                }
                mesh.showlabelonclick = h3dobj.showlabelonclick
                mesh.name = h3dobj.name

                if (mesh.name === '墙面北') {
                    var echarts = require('echarts');
                    // 基于准备好的dom,初始化echarts实例
                    var myChart = echarts.init($("<canvas width='512' height='512'></canvas>")[0]);
                    // 绘制图表
                    myChart.setOption({
                        title: {
                            text: 'ECharts 入门示例'
                        },
                        tooltip: {},
                        xAxis: {
                            data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
                        },
                        yAxis: {},
                        series: [{
                            name: '销量',
                            type: 'bar',
                            data: [5, 20, 36, 10, 10, 20]
                        }]
                    });
                    let _this = this
                    myChart.on('finished', function () {
                        var spriteMap = new THREE.TextureLoader().load(myChart.getDataURL());

                        var spriteMaterial = new THREE.MeshPhongMaterial({
                            transparent: true,
                            map: spriteMap,
                            side: THREE.DoubleSide
                        });

                        var sprite = new THREE.Sprite(spriteMaterial);
                        sprite.scale.set(150, 150, 1)
                        sprite.position.set(0, 10, 10);
                        mesh.add(sprite);

                    });
                }

                parent.add(mesh)
            }
        },
        create3dObject(parenth3dobj, h3dobj, virtual) {
            // 材质名称
            let materialName = h3dobj.h3dmatcate;
            let attrs = h3dobj.h3dobjattrs;
            let width = this.getAttribute(attrs, 'width');
            let height = this.getAttribute(attrs, "height");
            let depth = this.getAttribute(attrs, 'depth');
            if (virtual && virtual === true) {
                width = 0.0000001
                height = 0.0000001
                depth = 0.0000001
            }

            if (virtual) {
                let group = new THREE.Group();
            }

            let geometry = new THREE.BoxGeometry(width, height, depth)

            let parentTx = parenth3dobj ? parenth3dobj.translatex : 0
            let parentTy = parenth3dobj ? parenth3dobj.translatey : 0
            let parentTz = parenth3dobj ? parenth3dobj.translatez : 0

            let translatex = h3dobj.translatex
            let translatey = h3dobj.translatey
            let translatez = h3dobj.translatez
            geometry.translate(translatex, translatey, translatez)
            let param = {};
            // 纹理贴图
            let h3dobjmaps = h3dobj.h3dobjmap;
            if (h3dobjmaps && h3dobjmaps.length > 0) {
                let h3dobjmap = h3dobjmaps[0];
                let resourceurl = h3dobjmap.resourceurl
                var img_floor = require('../../assets/' + resourceurl);
                // 加载树纹理贴图
                var texture = new THREE.TextureLoader().load(img_floor);
                // 设置阵列
                texture.wrapS = THREE.RepeatWrapping;
                texture.wrapT = THREE.RepeatWrapping;
                // uv两个方向纹理重复数量
                texture.repeat.set(h3dobjmap.repeatx, h3dobjmap.repeaty);
                param = {
                    map: texture,
                    side: THREE.DoubleSide
                }
                // material = new THREE.MeshBasicMaterial({
                //     map: texture,
                //     side: THREE.DoubleSide
                // });
            }
            // 材质属性
            let h3dobjmats = h3dobj.h3dobjmats;
            if (h3dobjmats && h3dobjmats.length > 0) {
                for (let i = 0; i < h3dobjmats.length; i++) {
                    param[h3dobjmats[i].attrname] = h3dobjmats[i].attrvalue
                }
            }
            //如果是打洞对象,设置为透明
            // if (h3dobj.bsp === true) {
            //     param.transparent = true
            //     param.opacity = 0
            // }

            let material = this.createMaterial(materialName, param);
            if (virtual)
                material = new THREE.MeshBasicMaterial();
            let mesh = new THREE.Mesh(geometry, material)
            //如果是挖洞对象,需要结合上级位置信息,和上级保存同一个定位基点
            let parentx = h3dobj.bsp ? (parenth3dobj ? parenth3dobj.x : 0) : 0;
            let parenty = h3dobj.bsp ? (parenth3dobj ? parenth3dobj.y : 0) : 0;
            let parentz = h3dobj.bsp ? (parenth3dobj ? parenth3dobj.z : 0) : 0;

            let px = parentx + h3dobj.x - translatex + parentTx
            let py = parenty + h3dobj.y - translatey + parentTy;
            let pz = parentz + h3dobj.z - translatez + parentTz;
            mesh.position.set(px, py, pz)

            let tx = h3dobj.rotationx;
            let ty = h3dobj.rotationy;
            let tz = h3dobj.rotationz;
            if (tx != 0 || ty != 0 || tz != 0)
                mesh.rotation.set(eval(tx), eval(ty), eval(tz))
            mesh.visible = h3dobj.isvisiable
            if (h3dobj.showlabel) {
                var labelDiv = document.createElement("div");
                labelDiv.className = "label";
                labelDiv.textContent = h3dobj.name + "(width:" + width + ")(height:" + height + ")(depth:" + depth + ")(X:" + px + ",Y:" + py + ",Z:" + pz + ")";
                // labelDiv.style.marginTop = "-1em";
                var lable2D = new CSS2DObject(labelDiv);
                lable2D.name = "标签";
                lable2D.position.z = h3dobj.z
                lable2D.position.x = 0
                lable2D.position.y = 0
                lable2D.position.z = 0
                mesh.add(lable2D);
            }
            mesh.name = h3dobj.name
            return mesh;
        },
        ThreeJs_Composer(_renderer, _scene, _camera) {
            let raycaster = new THREE.Raycaster();
            let mouse = new THREE.Vector2();
            let composer = new EffectComposer(_renderer);
            let renderPass = new RenderPass(_scene, _camera);
            let selectedObjects = [];
            composer.addPass(renderPass);
            let outlinePass = new OutlinePass(
                new THREE.Vector2(window.innerWidth, window.innerHeight),
                _scene,
                _camera
            );
            outlinePass.edgeStrength = 5; //包围线浓度
            outlinePass.edgeGlow = 1; //边缘线范围
            outlinePass.edgeThickness = 1.0; //边缘线浓度
            outlinePass.pulsePeriod = 0; //包围线闪烁频率
            outlinePass.usePatternTexture = false// 使用纹理
            outlinePass.visibleEdgeColor.set("#ffffff"); //包围线颜色
            outlinePass.hiddenEdgeColor.set("#190a05"); //被遮挡的边界线颜色
            composer.addPass(outlinePass);
            let effectFXAA = new ShaderPass(FXAAShader);
            effectFXAA.uniforms["resolution"].value.set(
                1 / window.innerWidth,
                1 / window.innerHeight
            );
            effectFXAA.renderToScreen = true;
            composer.addPass(effectFXAA);
            let door_state_left1 = true; //默认是门是关闭的
            let door_state_right1 = true; //默认是门是关闭的
            window.addEventListener("click", onMouseClick);
            window.addEventListener("dblclick", onMouseDblClick);

            function onMouseClick(event) {
                var x, y;
                if (event.changedTouches) {
                    x = event.changedTouches[0].pageX;
                    y = event.changedTouches[0].pageY;
                } else {
                    x = event.clientX;
                    y = event.clientY;
                }
                mouse.x = (x / window.innerWidth) * 2 - 1;
                mouse.y = -(y / window.innerHeight) * 2 + 1;
                raycaster.setFromCamera(mouse, _camera);
                var intersects = raycaster.intersectObjects([_scene], true);
                if (intersects.length == 0) {
                    $("#label").attr("style", "display:none;"); //隐藏说明性标签
                    return;
                }
                if (intersects[0].object.name == "地面" || intersects[0].object.name == "" || intersects[0].object.name == "墙面") {
                    $("#label").attr("style", "display:none;"); //隐藏说明性标签
                    selectedObjects.pop();
                } else {
                    if (intersects[0].object.showlabelonclick) {
                        $("#label").attr("style", "display:block;"); // 显示说明性标签
                        $("#label").css({ left: x, top: y + 40 }); // 修改标签的位置
                        $("#label").text(intersects[0].object.name); // 显示模型信息
                    }
                    selectedObjects.pop();
                    selectedObjects.push(intersects[0].object);
                    outlinePass.selectedObjects = selectedObjects; //给选中的线条和物体加发光特效
                }

                // TWEEN.Easing.Elastic.Out带抖动效果的,会超出预设的角度
                if (intersects[0].object.name === "左门") {
                    if (door_state_left1) {
                        new TWEEN.Tween(intersects[0].object.rotation)
                            .to(
                                {
                                    y: -0.55 * Math.PI,
                                },
                                2000
                            )
                            .easing(TWEEN.Easing.Quadratic.Out)
                            .onComplete(function () { })
                            .start();
                        door_state_left1 = false;
                    } else {
                        new TWEEN.Tween(intersects[0].object.rotation)
                            .to(
                                {
                                    y: 0,
                                },
                                2000
                            )
                            .easing(TWEEN.Easing.Quadratic.Out)
                            .onComplete(function () { })
                            .start();
                        door_state_left1 = true;
                    }
                } else if (intersects[0].object.name == "右门") {
                    if (door_state_right1) {
                        new TWEEN.Tween(intersects[0].object.rotation)
                            .to(
                                {
                                    y: 0.55 * Math.PI,
                                },
                                2000
                            )
                            .easing(TWEEN.Easing.Quadratic.Out)
                            .onComplete(function () { })
                            .start();
                        door_state_right1 = false;
                    } else {
                        new TWEEN.Tween(intersects[0].object.rotation)
                            .to(
                                {
                                    y: 0,
                                },
                                2000
                            )
                            .easing(TWEEN.Easing.Quadratic.Out)
                            .onComplete(function () { })
                            .start();
                        door_state_right1 = true;
                    }
                }
            }
            function onMouseDblClick(event) {
                var x, y;
                if (event.changedTouches) {
                    x = event.changedTouches[0].pageX;
                    y = event.changedTouches[0].pageY;
                } else {
                    x = event.clientX;
                    y = event.clientY;
                }
                mouse.x = (x / window.innerWidth) * 2 - 1;
                mouse.y = -(y / window.innerHeight) * 2 + 1;
                raycaster.setFromCamera(mouse, _camera);
                var intersects = raycaster.intersectObjects([_scene], true);

                if (intersects.length == 0) {
                    return;
                }

                var Msg = intersects[0].object.name.split("$");
                if (Msg[0] == "货物") {
                    var href =
                        "DispatchAction.do?efFormEname=YMIQ083DP&inqu_status-0-storageUnitId=" +
                        Msg[1];
                    EFColorbox({
                        href: href,
                        title: "货物详情",
                        innerWidth: "1200px",
                        innerHeight: "800px",
                        iframe: true,
                        scrolling: false,
                        overlayClose: false,
                    });
                }
            }
        },
        createBsp(srcH3dobj, baseH3dobj, subtractH3dobjs) {
            // var material = new THREE.MeshPhongMaterial({ color: 0x9cb2d1, specular: 0x9cb2d1, shininess: 30, transparent: true, opacity: 1 });
            let material = this.createMaterialV2(srcH3dobj);
            var BSP = new ThreeBSP(baseH3dobj);
            for (var i = 0; i < subtractH3dobjs.length; i++) {
                var less_bsp = new ThreeBSP(subtractH3dobjs[i]);
                BSP = BSP.subtract(less_bsp);
            }
            var result = BSP.toMesh(material);
            result.material.flatshading = THREE.FlatShading;
            result.geometry.computeFaceNormals();  //重新计算几何体侧面法向量
            result.geometry.computeVertexNormals();
            result.material.needsUpdate = true;  //更新纹理
            result.geometry.buffersNeedUpdate = true;
            result.geometry.uvsNeedUpdate = true;
            return result;
        },
        createMaterialV2(h3dobj) {
            let materialName = h3dobj.h3dmatcate;
            let param = {};
            // 纹理贴图
            let h3dobjmaps = h3dobj.h3dobjmap;
            if (h3dobjmaps && h3dobjmaps.length > 0) {
                let h3dobjmap = h3dobjmaps[0];
                let resourceurl = h3dobjmap.resourceurl
                var img_floor = require('../../assets/' + resourceurl);
                // 加载树纹理贴图
                var texture = new THREE.TextureLoader().load(img_floor);
                // 设置阵列
                texture.wrapS = THREE.RepeatWrapping;
                texture.wrapT = THREE.RepeatWrapping;
                // uv两个方向纹理重复数量
                texture.repeat.set(10, 10);
                param = {
                    map: texture,
                    side: THREE.DoubleSide
                }
                // material = new THREE.MeshBasicMaterial({
                //     map: texture,
                //     side: THREE.DoubleSide
                // });
            }
            // 材质属性
            let h3dobjmats = h3dobj.h3dobjmats;
            if (h3dobjmats && h3dobjmats.length > 0) {
                for (let i = 0; i < h3dobjmats.length; i++) {
                    param[h3dobjmats[i].attrname] = h3dobjmats[i].attrvalue
                }
            }
            //如果是打洞对象,设置为透明
            // if (h3dobj.bsp === true) {
            //     param.transparent = true
            //     param.opacity = 0
            // }

            let material = this.createMaterial(materialName, param);
            return material;
        },
        createMaterial(material, param) {

            // var img_floor = require('../../assets/images/h3dimg/floor/floor.png');
            // // 加载树纹理贴图
            // var texture = new THREE.TextureLoader().load(img_floor);
            // // 设置阵列
            // texture.wrapS = THREE.RepeatWrapping;
            // texture.wrapT = THREE.RepeatWrapping;
            // // uv两个方向纹理重复数量
            // texture.repeat.set(10, 10);
            //  material = new THREE.MeshBasicMaterial({
            //         map: texture,
            //         side: THREE.DoubleSide
            //     });
            //     return material;

            if (material === 'MeshBasicMaterial') {
                return new THREE.MeshBasicMaterial(param);
            }
            else if (material === 'MeshPhongMaterial') {
                return new THREE.MeshPhongMaterial(param);
            }
            else if (material === 'MeshLambertMaterial') {
                return new THREE.MeshLambertMaterial(param);
            }
            else if (material === 'MeshStandardMaterial') {
                return new THREE.MeshStandardMaterial(param);
            }
            else {
                return new THREE.MeshBasicMaterial(param);
            }
        },
        getAttribute(attrs, attrname) {
            for (let i = 0; attrs && i < attrs.length; i++) {
                if (attrs[i]['attrname'] === attrname) {
                    return attrs[i].attrvalue
                }
            }
        },
        // 初始化性能插件
        initStats() {
            let stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.body.appendChild(stats.domElement);
            return stats;
        },
        // 初始化轨迹球控件
        initControls() {
            let controls = new OrbitControls(this.camera, this.renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.5;
            // 视角最小距离
            controls.minDistance = 100;
            // 视角最远距离
            controls.maxDistance = 5000;
            // 最大角度
            // controls.maxPolarAngle = Math.PI / 2.2;
        },
        // 窗口变动触发的方法
        onWindowResize() {
            this.camera.aspect = window.innerWidth / window.innerHeight;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(window.innerWidth, window.innerHeight);
        },

        animate() {
            requestAnimationFrame(this.animate)
            this.mesh.rotation.x += 0.01
            this.mesh.rotation.y += 0.02
            this.renderer.render(this.scene, this.camera)
            this.labelRenderer.render(this.scene, this.camera);
            if (!isNull(this.composer)) {
                this.composer.render();
            }
            TWEEN.update();
        },
        testEcharts() {
            var echarts = require('echarts');
            // 基于准备好的dom,初始化echarts实例
            var myChart = echarts.init($("<canvas width='512' height='512'></canvas>")[0]);
            // 绘制图表
            myChart.setOption({
                title: {
                    text: 'ECharts 入门示例'
                },
                tooltip: {},
                xAxis: {
                    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
                },
                yAxis: {},
                series: [{
                    name: '销量',
                    type: 'bar',
                    data: [5, 20, 36, 10, 10, 20]
                }]
            });
            let _this = this
            myChart.on('finished', function () {
                var spriteMap = new THREE.TextureLoader().load(myChart.getDataURL());

                var spriteMaterial = new THREE.SpriteMaterial({
                    transparent: true,
                    map: spriteMap,
                    side: THREE.DoubleSide
                });

                var sprite = new THREE.Sprite(spriteMaterial);
                sprite.scale.set(150, 150, 1)
                sprite.position.set(-100, 180, 0);
                _this.scene.add(sprite);

            });
        },
        initTextTest() {
            let name = "库区1"
            let textposition = "左对齐";
            let x = -150;
            let y = 20;
            let z = 200;
            let width = 100;
            let length = 100;
            let _this = this
            // var fontjson=require('three/examples/fonts/gentilis_bold.typeface.json')
            new THREE.FontLoader().load("/static/fonts/LiSu_Regular.json", function (font) {
                // 加入立体文字
                var text = new THREE.TextGeometry(name, {
                    // 设定文字字体
                    font: font,
                    //尺寸
                    size: 78,
                    //厚度
                    height: 10.01
                });
                text.computeBoundingBox();
                //3D文字材质
                var m = new THREE.MeshStandardMaterial({ color: "#FF0000" });
                var mesh = new THREE.Mesh(text, m)
                if (textposition == "左对齐") {
                    mesh.position.x = x - width / 2 + 10;
                } else if (textposition == "居中") {
                    mesh.position.x = x - 15;
                } else if (textposition == "右对齐") {
                    mesh.position.x = x + width / 2 - 60;
                }
                mesh.position.y = 20;
                mesh.position.z = z + length / 2 - 20;
                mesh.rotation.x = -Math.PI / 2.0;
                _this.scene.add(mesh);
            });
        }
        ,
        test() {
            // const coords = { x: 0, y: 0 } // Start at (0, 0)
            // const tween = new TWEEN.Tween(coords) // Create a new tween that modifies 'coords'.
            //     .to({ x: 300, y: 200 }, 1000) // Move to (300, 200) in 1 second.
            //     .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
            //     .onUpdate(() => {
            //         // Called after tween.js updates 'coords'.
            //         // Move 'box' to the position described by 'coords' with a CSS translation.
            //         // box.style.setProperty('transform', `translate(${coords.x}px, ${coords.y}px)`)
            //     })
            //     .start()
        }
    },
    mounted() {
        this.init()
        window.addEventListener("resize", this.onWindowResize);
        // this.initStats();
    }
}

这个功能也是参考别人写的,只是基于Vue来做的。使用Vue来开发Threejs会遇到各种问题,由于本身只是一个写后端的,对前端知识不太了解,为了解决这些问题也是踩了不少坑。趁有时间来记录一下。
先记录到这里吧,有时间再来详细记录。

网站文章

  • PHP安装Mcrypt扩展

    在使用PHP开发的过程中,为了提供数据传输的安全性,避免不了使用加密函数,除了使用php本身自带的几个函数,php还提供Mhash和Mcrypt2个扩展库。Mcrypt扩展库支撑的加密算法可以看http://mcrypt.sourceforge.net/,这里有对这个接口的详细介绍。 这里介绍2种安装Mcrypt扩展库的方法,算是对自己安装过程中遇到问题的一个总结。 1. 安装Mcrypt

    2024-02-01 03:12:04
  • 计算机二级C语言公共基础知识,以及习题总结(六)数据模型

    计算机二级C语言公共基础知识,以及习题总结(六)数据模型

    数据模型的基本概念 1、数据模型是数据特征的抽象 数据模型描述的内容 (1)数据结构 (2)数据操作 (3)数据约束 数据模型按不同的应用层次分成三种类型 概念数据模型(Conceptual Data...

    2024-02-01 03:11:33
  • selenium 页面加载慢,超时的解决方案

    开发环境:win10-64 python2.7.16 chrome77from selenium import webdriverdriver = webdriver.Chrome(executable_path='chromedriver.exe')driver.get('http://全部加载完成超级慢的网站')user = 'abc...

    2024-02-01 03:11:27
  • Python智力问答小游戏

    Python智力问答小游戏

    在这个Python智力问答小游戏中,我们将提供一系列问题,并编写代码来实现一个简单的问答游戏。玩家将被要求回答一些与Python编程相关的问题,并根据他们的回答来获得得分。接下来,我们需要编写代码来显...

    2024-02-01 03:10:53
  • [EXP公开] CVE-2020-13935: Tomcat WebSocket 拒绝服务漏洞通告

    [EXP公开] CVE-2020-13935: Tomcat WebSocket 拒绝服务漏洞通告

    原创 360CERT [三六零CERT](javascript:void(0)???? 今天 报告编号:B6-2020-110601 报告来源:360CERT 报告作者:360CERT 更新日期:20...

    2024-02-01 03:10:45
  • 常见的语法错误

    1、有缩进 :IndentationError: unexpected indent2、解释器会明确指出错误原因是无法识别的字符“:invalid character ’

    2024-02-01 03:10:37
  • class 文件方法表集合

    class 文件方法表集合

    一点睛 methods:指向常量池索引集合,它完整描述了每个方法的签名。 在字节码文件中,每一个 method_info 项都对应着一个类或者接口中的方法信息。比如方法的访问修饰符(public、pr...

    2024-02-01 03:10:30
  • eCharts工具类

    eCharts工具类

    ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等)...

    2024-02-01 03:10:02
  • 理解React Hooks看这一篇就够了

    理解React Hooks看这一篇就够了

    在React中,Hooks其实就是一个函数,这个函数的命名以use开头、函数return一个结果;React Hooks其实就是封装了一些通用的、公共的方法,就是一些通用的工具。官方Hooks是指Re...

    2024-02-01 03:09:56
  • html前端对象字段去空格,springboot中前台传来的string字符串自动去除前后面的空格...

    服务器后端接收前端传来的字符串带空格,如下现在在后端接收时需要把字符串前后的空格去除掉。解决办法importcom.fasterxml.jackson.databind.Deserialization...

    2024-02-01 03:09:48