three.js的demo例子-STL加载对象组件

news2024/12/28 4:05:36

three.js的demo例子-STL加载对象组件

提示:demo示例中所涉及到的three.js安装插件方法这里就不单个说明了哈,有需要的网上有很多教程


文章目录

  • three.js的demo例子-STL加载对象组件
  • 效果展示
  • 插件
  • 模型
  • 一、HTML部分
  • 二、script部分
    • 1.引入库
    • 2.初始化数据
    • 3.监听鼠标
    • 4.watch监听
    • 5.模型对象
  • 三、dat.gui可视化工具
  • 四、gsap动画库
  • 五、全部代码(可随意copy)
  • 唠叨


效果展示

three.js-example_demo1


插件

提示:这里涉及到的插件:

  • three.js (3D组件) ;官网:three.js文档
  • element ; 官网:element文档
  • STLLoader (stl模型加载器)
  • OrbitControls (轨道控制器)
  • gsap (动画库) ;官网:gsap文档或者tweenmax动画库中文api
  • dat.gui (右上角的提示,可自由设置属性,这里设置了颜色) ;dat.GUI的GitHub:dat.gui的仓库
    在这里插入图片描述

模型

demo中所有用到都是从网上找的类型为*.stl文件,大家可以从在网站或者three.js的官网(官网three.js-dev下载地址在最后)中扒模型尝试一下。
以下是three.js支持的模型文件类型:

  • *.obj
  • *.mtl
  • *.dae
  • *.ctm
  • *.ply
  • *.stl
  • *.wrl
  • *.vtk

提示:以下是本篇文章正文内容

一、HTML部分

<div style="width:100%;height:100%;">
        <!-- 画布 -->
        <canvas id="workshop" width="1200px" height="935px"></canvas>
        <!-- element组件实现弹框效果 -->
   <el-dialog title="人员信息" :visible.sync="messageVisible" width="40%" style="z-index: 5000">
        <span slot="footer" class="dialog-footer">
           <el-button @click="messageVisible = false" style="padding: 12px 20px;">取 消</el-button>
        </span>
   </el-dialog>
</div>

二、script部分

1.引入库

import * as THREE from 'three';
// import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";//引入(轨道控制器)可以使得相机围绕目标进行轨道运动
import gsap from 'gsap';//导入动画库
import * as dat from 'dat.gui'// 导入dat.gui

2.初始化数据

demo为了方便用的是全局定义属性

var condition8 = false;
var renderer = null;
var canvas = null;
let group = new THREE.Group();//用来存放外部引入的模型
const mouse = new THREE.Vector2();
let selectObject, INTERSECTED;

// #region 模型部分
/**工作台 */
var material1 = null;
var mesh1 = null;
var loader = new STLLoader();
/**传送带 */
var material2 = null;
var mesh2 = null;
var loader2 = new STLLoader();
/**传送带2 */
var material3 = null;
var mesh3 = null;
var loader3 = new STLLoader();
/**称重 */
var material4 = null;
var mesh4 = null;
var loader4 = new STLLoader();
/**产品 */
var material5 = null;
var mesh5 = null;
var loader5 = new STLLoader();
/**料架 */
var material6 = null;
var mesh6 = null;
var loader6 = new STLLoader();
/**人员 */
var material7 = null;
var mesh7 = null;
var loader7 = new STLLoader();
/**LED绿 */
var material8 = null;
var mesh8 = null;
var loader8 = new STLLoader();
/**摄像头 */
var material11 = null;
var mesh11 = null;
var loader11 = new STLLoader();
// #endregion

// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// const camera = new CinematicCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置
camera.position.set(-10, 5, 10);
// lookAt设置必须统一设置
camera.lookAt(new THREE.Vector3(10,10,20));
// 在场景中添加相机
scene.add(camera);

3.监听鼠标

需要添加监听事件,监听鼠标的状态

/**监听鼠标点击的对象 */
document.addEventListener('dblclick', this.onMouseDblclick, false);
/**监听鼠标移入对象 */
document.addEventListener('mousemove', this.onMouseenter, false);

这里可以举一反三,通过鼠标监听获取当前的mesh对象,并对应做出一些逻辑方法,譬如双击可改变颜色、鼠标移入可使对应的对象变色功能等

/**鼠标双击时 */
        onMouseDblclick(event) {
            //获取raycaster和所有模型相交的数组,其中的元素按照距离排序,越近的越靠前
            let intersects = this.getIntersects(event);
            console.log('intersects', intersects);

            //获取选中最近的Mesh对象
            //instance坐标是对象,右边是类,判断对象是不是属于这个类的
            if (intersects.length !== 0 && intersects[0].object.type === 'Mesh' && intersects[0].object.name === 'peple01') {
                intersects[0].object.material.color.set(0x00FF00);//给选中的模型换成绿色
                // console.log(intersects[0].object.material.color);
                selectObject = intersects[0].object;
                console.log("selectObject", selectObject);//后期可根据position位置判断人的信息
                this.messageVisible = true;//显示弹框
            } else {
                console.log('未选中 人员Mesh!');
            }
        },
        getIntersects(event) {
            event.preventDefault();// 阻止默认的点击事件执行, https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault
            //console.log("event.clientX:" + event.clientX);
            //console.log("event.clientY:" + event.clientY);

            //声明 rayCaster 和 mouse 变量
            let rayCaster = new THREE.Raycaster();
            let mouse = new THREE.Vector2();

            //通过鼠标点击位置,计算出raycaster所需点的位置,以屏幕为中心点,范围-1到1
            mouse.x = ((event.clientX - canvas.getBoundingClientRect().left) / canvas.offsetWidth) * 2 - 1;
            mouse.y = -((event.clientY - canvas.getBoundingClientRect().top) / canvas.offsetHeight) * 2 + 1; //这里为什么是-号,没有就无法点中

            //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
            rayCaster.setFromCamera(mouse, camera);

            //获取与射线相交的对象数组, 其中的元素按照距离排序,越近的越靠前。
            //+true,是对其后代进行查找,这个在这里必须加,因为模型是由很多部分组成的,后代非常多。
            let intersects = rayCaster.intersectObjects(group.children, true);

            //返回选中的对象
            return intersects;
        },
        /**鼠标移入时 */
        onMouseenter(event) {
            event.preventDefault();

            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
        },

4.watch监听

这里使用watch监听弹框,根据弹框的状态给人物赋值状态

// 监听弹框,若弹框关闭 则返回原来的颜色
        messageVisible: {
            handler(newName, oldName) {
                if (!newName) {
                    if (selectObject.name == 'peple01') {
                        material7.color = new THREE.Color(0xe0b884)
                    }
                }
            },
            deep: true, //为true,表示深度监听,这时候就能监测到a值变化
        }

5.模型对象

这里以工作台workbench.stl模型为例子,将所有模型都添加至group中,为了方便后期获取物体的材质信息

// 工作台
        loadFun1() {
        	loader= new STLLoader();//用于实现加载器的基类
            loader.load('static/stls/workshop/workbench.stl', geometry => {
                // 创建材质
                material1 = new THREE.MeshLambertMaterial({//材质,一种非光泽表面的材质,没有镜面高光
                    color: 0xc1c1c1,
                    // opacity: 1,//设置透明度,默认为1
                });
                mesh1 = new THREE.Mesh(geometry, material1);//将模型物体和材质加载至mesh中
                mesh1.scale.set(-0.004, 0.004, 0.004);//设置模型的大小缩放
                mesh1.translateZ(-3)//设置z轴移动位置
                // scene.add(mesh1);

                group.add(mesh1);//将mesh网格添加至group中
                scene.add(group);//将group添加至场景中
            });
        },

三、dat.gui可视化工具

推荐博客:gui工具的使用
这里给了五种常用的功能,如下代码所示。
demo示例中用到了使用dat.gui工具改变物体颜色(是下面代码中的2.)

const gui = new dat.GUI();//创建一个

/**1.移动动画*/
// 0-5范围内,间隔0.01
gui.add(cube.position, "x")
    .min(0).max(5)
    .step(0.01)
    .name("移动x轴")
    .onChange((value) => {  //移动时会被触发,值被改变时
        console.log("值被修改:", value);
    }).onFinishChange((value) => {//鼠标抬起时
        console.log("完全停下来:", value);
    });
    
/* 2.修改物体的颜色*/
const params = {
    color: "#ffff00",
    fn: () => {
        //让立方体运动起来
        gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 })
    }
}
gui.addColor(params, "color").onChange((value) => {
    console.log("值被修改:", value);
    cube.material.color.set(value); //cube是mesh对象
})

/**3.置选项框*/
gui.add(cube, "visible").name("是否显示");

/**4.设置文件夹 */
var folder = gui.addFolder("设置立方体");
folder.add(cube.material,"wireframe");

/**5.设置按钮点击触发某个事件 */
folder.add(params, "fn").name("让物体运动")

四、gsap动画库

动画库可以使物体自主运动,让页面看着不那么干涩,以下是对gsap.to(此方法用于创建一个从当前属性到指定目标属性的动画对象)对象常用属性介绍。

// 设置动画
/**duration: 5 移到位置需要5秒的时间 ; ease:控制速度(inOut:交叉轨道;out:外部轨道;in:内部轨道) */
// gsap.to(cube.position, { x: 5, duration: 5, ease: "power1.inOut" });
// gsap.to(cube.rotation, { x: 2 * Math.PI, duration: 5, ease: "power1.inOut" })//旋转
/**动画回调函数 */
var animate1 = gsap.to(cube.position, {
    x: 5, 
    duration: 5,//动画时长
    ease: "power1.inOut",
    repeat: 2, //设置重复次数,无限循环为-1
    yoyo: true,//设置往返
    delay: 2,//设置延迟2s
    onComplete: () => {
        console.log("动画完成");
    },
    onStart: () => {
        console.log("动画开始");
    }
});
/**鼠标双击监听控制动画的暂停/开始*/
window.addEventListener("dblclick", () => {//监听鼠标双击
    console.log("animate1", animate1);
    if (animate1.isActive()) {
        animate1.pause();//暂停
    } else {
        animate1.resume();//恢复
    }
})

demo中用到的动画库:mesh5.position对象里有x、y、z,这里仅对x和y做了设置

gsap.to(mesh5.position, {
     keyframes: [
     {
         delay: 0,
         x: -2,
         y: 2.85,
         duration: 5,
      },
      {
         delay: 1,
         x: 6,
         y: 2.85,
         duration: 5,
      }
      ],
      repeat: 1,//动画执行次数
      onComplete: this.myFunction
});
gsap.defaultOverwrite = "auto"

五、全部代码(可随意copy)

<!-- 工站的例子 -->
<template>
    <div style="width:100%;height:100%;">
        <canvas id="workshop" width="1200px" height="935px"></canvas>
        <!-- 新增车间、产线、工站部分 -->
        <el-dialog title="人员信息" :visible.sync="messageVisible" width="40%" style="z-index: 5000">
            <span slot="footer" class="dialog-footer">
                <el-button @click="messageVisible = false" style="padding: 12px 20px;">取 消</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
// import './js/workStation'
import * as THREE from 'three';
// import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";//引入(轨道控制器)可以使得相机围绕目标进行轨道运动
import gsap from 'gsap';//导入动画库
import * as dat from 'dat.gui'// 导入dat.gui
import { CinematicCamera } from 'three/examples/jsm/cameras/CinematicCamera.js';
// export { Color } from '@/src/assets/math/Color.js';

var condition8 = false;
var renderer = null;
var canvas = null;
let group = new THREE.Group();//用来存外部引入的模型
const mouse = new THREE.Vector2();
let selectObject, INTERSECTED;

// #region
/**工作台 */
var material1 = null;
var mesh1 = null;
var loader = new STLLoader();
/**传送带 */
var material2 = null;
var mesh2 = null;
var loader2 = new STLLoader();
/**传送带2 */
var material3 = null;
var mesh3 = null;
var loader3 = new STLLoader();
/**称重 */
var material4 = null;
var mesh4 = null;
var loader4 = new STLLoader();
/**产品 */
var material5 = null;
var mesh5 = null;
var loader5 = new STLLoader();
/**料架 */
var material6 = null;
var mesh6 = null;
var loader6 = new STLLoader();
/**人员 */
var material7 = null;
var mesh7 = null;
var loader7 = new STLLoader();
/**LED绿 */
var material8 = null;
var mesh8 = null;
var loader8 = new STLLoader();
/**摄像头 */
var material11 = null;
var mesh11 = null;
var loader11 = new STLLoader();
// #endregion

// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// const camera = new CinematicCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置
camera.position.set(-10, 5, 10);
// lookAt设置必须统一设置
camera.lookAt(new THREE.Vector3(10,10,20));
// 在场景中添加相机
scene.add(camera);

export default {
    components: {},
    data() {
        return {
            messageVisible: false,
        };
    },
    props: {},
    computed: {},
    mounted() {
        /**监听鼠标点击的对象 */
        document.addEventListener('dblclick', this.onMouseDblclick, false);
        /**监听鼠标移入对象 */
        document.addEventListener('mousemove', this.onMouseenter, false);
        this.initFun();
        this.render();
        this.loadFun1();// 工作台
        this.loadFun2();// 传送带
        this.loadFun3();// 传送带2
        this.loadFun4();// 称重
        this.loadFun5();// 产品
        this.loadFun6();// 料架
        this.loadFun7();// 人员
        this.loadFun8();// LED
        this.loadFun11();// 摄像头
        // 监听画面变化,更新渲染画面
        window.addEventListener("resize", () => {
            console.log("画面变化了");
            // 更新摄像头
            camera.aspect = window.innerWidth / window.innerHeight;
            // 更新摄像机的投影举证
            camera.updateProjectionMatrix();
            // 更新渲染器
            renderer.setSize(window.innerWidth, window.innerHeight);
            // 设置渲染器的像素比
            renderer.setPixelRatio(window.devicePixelRatio);
        })
    },
    methods: {
        initFun() {
            // 环境光
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.6) // 创建环境光
            scene.add(ambientLight) // 将环境光添加到场景
            const spotLight = new THREE.SpotLight(0xffffff) // 创建聚光灯
            spotLight.position.set(15, 15, 15)
            // spotLight.castShadow = true
            scene.add(spotLight);

            /**右上角gui配置 */
            const gui = new dat.GUI();
            /* 修改物体的颜色 == 红色led灯*/
            const params = {
                color: "#118fdd",
            }
            gui.addColor(params, "color").onChange((value) => {
                mesh8.material.color.set(value);
            })
            console.log("mesh8", mesh8);

            // 初始化渲染器
            console.log("document.getElementById('workshop')", document.getElementById('workshop'));
            // const renderer = new THREE.WebGLRenderer();
            renderer = new THREE.WebGLRenderer({
                canvas: document.getElementById('workshop')
            });

            canvas = renderer.domElement;
            // // 设置渲染的尺寸大小
            renderer.setSize(window.innerWidth, window.innerHeight);
            // 将webgl渲染的canvas内容添加到body
            document.body.appendChild(renderer.domElement);
            // // 使用渲染器,通过相机将场景渲染进去
            // renderer.render(scene,camera);

            /**创建轨道控制器*/
            const controls = new OrbitControls(camera, renderer.domElement);//renderer.domElement 指的是场景将被渲染的<canvas> 元素
            // controls.target = new THREE.Vector3(5, 5, 20);

            // 添加坐标轴辅助器
            const axesHelper = new THREE.AxesHelper(5); //用于简单模拟3个坐标轴的对象 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
            scene.add(axesHelper);

            //网格线绘制
            var grid = new THREE.GridHelper(24, 24, 0x444444, 0x888888);
            grid.material.opacity = 0.4;
            grid.material.transparent = true;
            grid.rotation.x = Math.PI;
            grid.position.y = -2.5;
            scene.add(grid);

            let clock = new THREE.Clock();
        },
        render() {
            renderer.render(scene, camera);
            // // 渲染下一帧的时候就会渲染render函数
            requestAnimationFrame(this.render);//请求动画帧
        },
        /**鼠标双击时 */
        onMouseDblclick(event) {
            //获取raycaster和所有模型相交的数组,其中的元素按照距离排序,越近的越靠前
            let intersects = this.getIntersects(event);
            console.log('intersects', intersects);

            //获取选中最近的Mesh对象
            //instance坐标是对象,右边是类,判断对象是不是属于这个类的
            if (intersects.length !== 0 && intersects[0].object.type === 'Mesh' && intersects[0].object.name === 'peple01') {
                intersects[0].object.material.color.set(0x00FF00);//给选中的模型换成绿色
                // console.log(intersects[0].object.material.color);
                selectObject = intersects[0].object;
                console.log("selectObject", selectObject);//后期可根据position位置判断人的信息
                this.messageVisible = true;//显示弹框
            } else {
                console.log('未选中 人员Mesh!');
            }
        },
        getIntersects(event) {
            event.preventDefault();// 阻止默认的点击事件执行, https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault
            //console.log("event.clientX:" + event.clientX);
            //console.log("event.clientY:" + event.clientY);

            //声明 rayCaster 和 mouse 变量
            let rayCaster = new THREE.Raycaster();
            let mouse = new THREE.Vector2();

            //通过鼠标点击位置,计算出raycaster所需点的位置,以屏幕为中心点,范围-1到1
            mouse.x = ((event.clientX - canvas.getBoundingClientRect().left) / canvas.offsetWidth) * 2 - 1;
            mouse.y = -((event.clientY - canvas.getBoundingClientRect().top) / canvas.offsetHeight) * 2 + 1; //这里为什么是-号,没有就无法点中

            //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
            rayCaster.setFromCamera(mouse, camera);

            //获取与射线相交的对象数组, 其中的元素按照距离排序,越近的越靠前。
            //+true,是对其后代进行查找,这个在这里必须加,因为模型是由很多部分组成的,后代非常多。
            let intersects = rayCaster.intersectObjects(group.children, true);

            //返回选中的对象
            return intersects;
        },
        /**鼠标移入时 */
        onMouseenter(event) {
            event.preventDefault();
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
        },
        // 工作台
        loadFun1() {
            loader.load('static/stls/workshop/workbench.stl', geometry => {
                // 创建材质
                material1 = new THREE.MeshLambertMaterial({
                    color: 0xc1c1c1,
                    // opacity: 1,//设置透明度
                });
                mesh1 = new THREE.Mesh(geometry, material1);
                mesh1.scale.set(-0.004, 0.004, 0.004);
                mesh1.translateZ(-3)
                // scene.add(mesh1);

                group.add(mesh1)
                scene.add(group);
            });
        },
        // 传送带
        loadFun2() {
            loader2.load('static/stls/workshop/FB15.stl', geometry => {
                // 创建材质
                material2 = new THREE.MeshLambertMaterial({
                    color: 0x002b37,
                    // opacity:1,//设置透明度
                });
                mesh2 = new THREE.Mesh(geometry, material2);
                mesh2.scale.set(-0.02, 0.004, 0.004);
                mesh2.translateZ(1.5)
                mesh2.translateY(2.5)
                // scene.add(mesh2);

                group.add(mesh2)
                scene.add(group);
            });
        },
        // 传送带2
        loadFun3() {
            loader3.load('static/stls/workshop/FB15.stl', geometry => {
                // 创建材质
                material3 = new THREE.MeshLambertMaterial({ color: 0x002b37 });
                mesh3 = new THREE.Mesh(geometry, material3);
                mesh3.scale.set(-0.02, 0.004, 0.004);
                mesh3.translateZ(3.5)
                mesh3.translateY(2.5)
                // scene.add(mesh3);

                group.add(mesh3)
                scene.add(group);
            });
        },
        // 称重
        loadFun4() {
            loader4.load('static/stls/workshop/SCALE.stl', geometry => {
                // 创建材质
                material4 = new THREE.MeshLambertMaterial({ color: 0x00d6e1 });
                mesh4 = new THREE.Mesh(geometry, material4);
                mesh4.rotation.y = 0.5 * Math.PI;
                mesh4.scale.set(-0.009, 0.02, 0.009);
                mesh4.translateY(1)
                mesh4.translateX(-2.3)
                // scene.add(mesh4);
                // material4.visible =false;
                console.log("material4", material4);

                group.add(mesh4)
                scene.add(group);
            });
        },
        // 产品
        loadFun5() {
            loader5.load('static/stls/workshop/product.stl', geometry => {
                // 创建材质
                material5 = new THREE.MeshLambertMaterial({
                    color: 0x28496f,
                    opacity: 0.4,
                    transparent: true,
                });
                console.log("material5",material5);
                mesh5 = new THREE.Mesh(geometry, material5);
                // mesh.rotation.y = 0.5 * Math.PI;
                mesh5.scale.set(-0.02, 0.009, 0.009);
                mesh5.translateZ(2.5)
                mesh5.translateY(2.85)
                mesh5.translateX(-5)
                // scene.add(mesh5);

                group.add(mesh5)
                scene.add(group);

                // 添加动画
                console.log("mesh5===", mesh5);
                console.log("mesh5.position", mesh5.position);
                gsap.to(mesh5.position, {
                    keyframes: [
                        {
                            delay: 0,
                            x: -2,
                            y: 2.85,
                            duration: 5,
                        },
                        {
                            delay: 1,
                            x: 6,
                            y: 2.85,
                            duration: 5,
                        }
                    ],
                    repeat: 1,//动画执行次数
                    onComplete: this.myFunction
                });
                gsap.defaultOverwrite = "auto"
            });
        },
        myFunction() {
            console.log("运动结束啦");
        },
        // 料架
        loadFun6() {
            loader6.load('static/stls/workshop/Warehouse.stl', geometry => {
                // 创建材质
                material6 = new THREE.MeshLambertMaterial({ color: 0x91b9f7 });
                mesh6 = new THREE.Mesh(geometry, material6);
                mesh6.rotation.x = 1.5 * Math.PI;
                mesh6.scale.set(-0.002, 0.002, 0.002);
                mesh6.translateZ(-2)
                mesh6.translateY(-62.5) //z轴
                mesh6.translateX(-10.65)//x轴
                // scene.add(mesh6);

                group.add(mesh6)
                scene.add(group);
            });
        },
        // 人员
        loadFun7() {
            loader7.load('static/stls/workshop/man.stl', geometry => {
                // 创建材质
                material7 = new THREE.MeshLambertMaterial({ color: 0xe0b884 });
                mesh7 = new THREE.Mesh(geometry, material7);
                mesh7.rotation.y = Math.PI;
                mesh7.scale.set(-0.003, 0.003, 0.003);
                mesh7.translateZ(-5)
                mesh7.translateY(1)
                mesh7.name = "peple01"
                console.log("mesh7", mesh7);
                // scene.add(mesh7);

                group.add(mesh7)
                scene.add(group);
            });
        },
        // LED
        loadFun8() {
            loader8 = new STLLoader();
            loader8.load('static/stls/workshop/led.stl', geometry => {
                // 创建材质
                // if (condition8) {
                //     material8 = new THREE.MeshPhongMaterial({ color: 0x66ff65 });
                // } else {
                //     material8 = new THREE.MeshPhongMaterial({ color: 0x2ece06 });
                // }
                material8 = new THREE.MeshLambertMaterial({ color: 0x29db6f });
                mesh8 = new THREE.Mesh(geometry, material8);
                console.log("mesh8",mesh8);
                mesh8.rotation.y = 0.5 * Math.PI;
                mesh8.scale.set(-0.08, 0.08, 0.08);
                mesh8.translateZ(3.3)//x
                mesh8.translateY(6.2) //y
                mesh8.translateX(0.5)//z
                setTimeout(() => {
                    this.getMeshFun(material8);
                }, 2000);
                scene.add(mesh8);

                group.add(mesh8)
                scene.add(group);
            });
        },
        getMeshFun(data) {
            // material8.color = "0x118fdd"
            // 创建颜色对象
            const color = new THREE.Color(0x118fdd)  //默认是纯白色0xffffff
            material8.color = color;
            // return 0x118fdd
        },
        // 摄像头
        loadFun11() {
            loader11.load('static/stls/workshop/camera.stl', geometry => {
                // 创建材质
                material11 = new THREE.MeshLambertMaterial({ color: 0x858585 });
                mesh11 = new THREE.Mesh(geometry, material11);
                mesh11.rotation.x = -0.25 * Math.PI;
                mesh11.scale.set(-0.009, 0.009, 0.009);
                mesh11.translateZ(4)
                mesh11.translateY(3.5)
                mesh11.translateX(0)
                // scene.add(mesh11);

                group.add(mesh11)
                scene.add(group);
            });
        },
    },
    watch: {
        // 监听弹框,若弹框关闭 则返回原来的颜色
        messageVisible: {
            handler(newName, oldName) {
                if (!newName) {
                    if (selectObject.name == 'peple01') {
                        material7.color = new THREE.Color(0xe0b884)
                    }
                }
            },
            deep: true, //为true,表示深度监听,这时候就能监测到a值变化
        }
    }
}
</script>
<style scoped>
* {
    margin: 0;
    padding: 0;
}
</style>

到此本篇正文就结束啦,内容太多,我已经尽量在代码里注释了,讲的不详细之处请多多包涵


唠叨

我喜欢研究three.js官网给的一些demo,觉得很有意思,而且可以直接下载项目下来琢磨,看他们封装的代码都很高级,也会学到不少,我的这个demo看着太low了,之后若是有时间写出超级酷的3D页面,就再花一下午时间写个博客分享记录吧。
附上three.js的官网源码:three.js-dev

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/403766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

卷王都在偷偷准备金三银四了...

年终奖没发&#xff1b; 简历石沉大海&#xff1b; 发消息只读不回 打开某招聘&#xff0c;看了看岗位&#xff0c;这个厂还不错&#xff0c;可是要求好高&#xff0c;我啥都不会。 “哎&#xff0c;算了&#xff0c;我简历还没更新呢&#xff0c;我躺到6月份拿到年终奖再跑…

【动态规划】多重背包问题,分组背包问题

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

名创优品业绩狂飙,手握哪些王牌?

撰稿 | 多客 来源 | 贝多财经 2023年注定是名创优品(NYSE:MNSO、HKEX:9896)发展史上具有重要意义的一年&#xff0c;不仅是创立的10周年&#xff0c;也是全球品牌战略升级的开局之年。 2月28日&#xff0c;名创优品公布了2023财年第二财季未经审计财务报告。得益于全球化战略…

机器学习笔记之狄利克雷过程(六)预测任务求解

机器学习笔记之狄利克雷过程——预测任务求解引言回顾&#xff1a;基于狄利克雷过程的预测过程预测任务的求解过程引言 上一节引出了基于狄利克雷过程的预测任务&#xff0c;本节将对该预测任务进行求解。 回顾&#xff1a;基于狄利克雷过程的预测过程 在已知隐变量样本集合…

Windows 环境安装Scala详情

为了进一步学习Spark&#xff0c;必须先学习Scala 编程语言。首先开始Scala 环境搭建。温馨提示&#xff1a;本文是基于Windows 11 安装Scala 2.13.1 版本第一步&#xff1a;确保本机已经正确安装JDK1.8 环境第二步&#xff1a;Scala 官网下载我们所属scala版本文件。Scala 官网…

JavaScript(WebAPI)

目录 1.什么是Web API? 2.DOM和DOM树 3.获取元素 4.事件 5.操作元素 获取/修改元素内容 1.innerText 2. innerHTML 获取/修改元素属性 获取/修改表单元素属性 获取/修改样式属性 1.修改内联样式 2.修改元素应用的CSS类名 6.操作节点 新增节点 删除节点 7.案例…

Vue3的composition API—setup函数, ref函数,reactive函数

1、Setup 函数 1.setup 是vue3中的一个配置项 2、setup是所有组件所需要的数据和方法都需要配置到setup中的 3、setup两种返回值&#xff1a; 若返回一个对象 若返回一个渲染函数 mian.js文件 注意&#xff1a;尽量不与Vue2混用 setup中无法访问vue2中的配置 不能是async函数…

Optional--Java8新特性最佳实践

Optional是在 Java8中引入的新特性之一。使用Optional类包装数据&#xff0c;可以避免经典的空检查和一些try-catch代码块。也能够通过链式方法调用&#xff0c;写出更流畅的函数式编程的代码。另一方面&#xff0c;滥用Optional也会导致性能低下和代码混乱。过往项目业务中有大…

【Linux】旋转锁 | 读写锁

在之前的线程学习中&#xff0c;用到的锁都是挂起等待锁&#xff0c;如果申请不到锁&#xff0c;那就会在锁中等待&#xff1b; 自旋锁则不大相似 文章目录1.自旋锁1.1 概念1.2 接口1.2.1 pthread_spin_init/destroy1.2.2 pthread_spin_lock1.2.3 pthread_spin_unlock2.读写锁…

VIO优化中不客观自由度 (gauge freedom) 的处理 (gauge handle)

文章目录1. 不可观的解释2. 几种不同的gauge handle处理方式2.1. free gauge方式2.2. fix gauge方式2.3. prior gauge方式2.4. g2o tutorial方式3.不同方式的协方差矩阵1. 不可观的解释 这篇论文 中对VIO的4-DOF不可观的定义如下&#xff0c;可以看到这种不可观就是如果对最后…

gerrit操作和jinkens编译合入代码

gerrit 先 查看自己的push 找到后添加reviewer 填写邮箱开头就可以出来 记得1 然后send 让人review 编译不过&#xff0c;gerrit上查看 1.是不是checkstyle问题 2.编译不过&#xff0c;去jinkens查看 先retrigger重新编译 如果发现多次编译失败 则要看下console output 查…

【ONE·Data || 顺序表】

总言 数据结构基础&#xff1a;顺序表模拟实现。    文章目录总言1、顺序表各接口功能实现描述1.1、如何创建一个顺序表&#xff1f;1.2、如何初始化顺序表&#xff1a;SLInit1.3、顺序表的尾插、头插1.3.1、顺序表尾插1.0&#xff1a;SLPushBack1.3.2、顺序表头插1.0&#x…

网络连接的三种模式

文章目录前言一、三种连接模式介绍二、三种网络连接模式的区别前言 在进行虚拟机配置时&#xff0c;网络连接分为三种模式&#xff1a;桥接模式&#xff0c;NAT模式&#xff0c;主机模式 一、三种连接模式介绍 张三、李四、王五在同一个网段&#xff0c;所以他们之间可以相互…

数据结构---双链表

专栏&#xff1a;数据结构 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;从零开始&#xff0c;数据结构&#xff01;&#xff01; 双链表前言双链表各接口的实现为要插入的值开辟一块空间BuyLN初始化LNInit和销毁LNDestory打印链表中的值LNPrint尾插LNPushBack和尾删LNPop…

vue2+elementUI完成添加学生删除学生案列

效果图&#xff1a; 点击添加学生按钮&#xff0c;弹出Dialog,收集用户信息&#xff1a; el-table中自定义复选框&#xff0c;选中一行&#xff0c;可以点击删除 代码区域&#xff1a;就一个HTML文件 <!DOCTYPE html> <html lang"en"> <head>&…

Flume基操

Flume概述 Flume 定义 Flume 是 Cloudera 提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统。Flume 基于流式架构&#xff0c;灵活简单。 Flume最主要的作用就是&#xff0c;实时读取服务器本地磁盘的数据&#xff0c;将数据写入到…

带恒温冷藏功能的便携式自动采样器——可用于毒情监测

污水采样在验毒的工作流程中是怎样进行的呢&#xff1f; 污水采样&#xff1a;每个季度采样一次。例如在某市48家污水处理厂54个进水口采取水样&#xff0c;用便携式水质自动采样器连续采样7天&#xff0c;一天采样12次成为一个混合样。也就是说&#xff0c;一次采样的话&…

如何在 VS Code 中安装运行、编写C语言程序

1.下载 安装VS Code 去官网下载&#xff1a;https://code.visualstudio.com/Download 直接下载&#xff0c;安装即可。 2.安装VS code中2个插件 打开软件运行&#xff0c;在扩展商店中分别搜索安装 C/C 和 code runner 插件 3.下载mingb64 官网下载 https://sourceforge…

消息队列MQ用来做什么的,市场上主流的四大MQ如何选择?RabbitMQ带你HelloWorld!

文章目录MQ用来做什么的MQ会有什么样的麻烦MQ消息队列模式分类MQ消息队列常用协议市场主流四大MQRabbitMQ项目开发RabbitMQ中的组成部分MQ用来做什么的 省流 &#xff1a;系统解耦、异步调用、流量削峰 系统解耦 首先举例下面这个场景&#xff0c;现有ABCDE五个系统&#xff…

小黑子—Java从入门到入土过程:第二章

Java零基础入门2.0Java系列第二章1. 注释和关键字2. 字面量3. 变量3.1 基本用法3.2 使用方式3.3 注意事项4. 变量练习5. 计算机中的数据存储5.1 计算机的存储规则5.2 进制5.3 进制间转换二进制转十八进制转十十六进制转十十进制转其他进制6. 数据类型7. 定义变量的练习8. 标识符…