three.js 点按钮,相机飞行靠近观察设备

这篇具有很好参考价值的文章主要介绍了three.js 点按钮,相机飞行靠近观察设备。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

效果: 点击按钮或直接点击模型都可以实现运动效果

three.js 点按钮,相机飞行靠近观察设备,three.js,javascript,数码相机,开发语言

three.js 点按钮,相机飞行靠近观察设备,three.js,javascript,数码相机,开发语言

 代码:文章来源地址https://www.toymoban.com/news/detail-801135.html

<template>
  <div>
    <el-container>
      <el-main>
        <div class="box-card-left">
          <div id="threejs" style="border: 1px solid red"></div>
          <div class="box-right">
            <el-button type="primary" @click="lookFor('设备A')">设备A</el-button>
            <el-button type="primary" @click="lookFor('设备B')">设备B</el-button>
            <el-button type="primary" @click="lookAll">整体</el-button>
            <el-button type="primary" @click="saveImg">保存图片</el-button>
          </div>
        </div>
      </el-main>
    </el-container>
  </div>
</template>
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import TWEEN from "@tweenjs/tween.js";

export default {
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      mesh: null,
      geometry: null,
      group: null,
      material: null,
      clock: null,
      mixer: null,
    };
  },
  created() {},
  mounted() {
    this.name = this.$route.query.name;
    this.init();
    // 监听点击事件
    this.addClickEventListener();
  },
  methods: {
    goBack() {
      this.$router.go(-1);
    },
    init() {
      // 创建场景对象
      this.scene = new this.$three.Scene();
      this.group = new this.$three.Group();
      this.createMesh({
        x: 50, y: 50, z: 50, name: '设备A'
      })
      this.createMesh({
        x: -50, y: 50, z: 50, name: '设备B'
      })
      
      this.scene.add(this.group);
      const axesHelper = new this.$three.AxesHelper(150);
      this.scene.add(axesHelper);
      // 创建环境光对象
      const ambientLight = new this.$three.AmbientLight(0xffffff);
      this.scene.add(ambientLight);
      // 创建相机对象
      this.camera = new this.$three.PerspectiveCamera();
      this.camera.position.set(300,300,300);
      this.camera.lookAt(0,0,0);
      // 创建渲染器对象
      this.renderer = new this.$three.WebGLRenderer({
        preserveDrawingBuffer: true // 把画布内容保存为图片时,需要设置为true
      });
      this.renderer.setSize(1000,800);
      this.renderer.render(this.scene, this.camera);
      window.document.getElementById("threejs").append(this.renderer.domElement);

      // 创建相机空间轨道控制器对象
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.addEventListener("change", () => {
        this.renderer.render(this.scene, this.camera);
        console.log(' this.camera.position', this.camera.position.x, this.camera.position.y, this.camera.position.z);
      })
    },
    // 创建网格模型的方法
    createMesh(obj) {
      // 创建立方缓冲几何体对象
      const geometry = new this.$three.BoxGeometry(obj.x, obj.y, obj.z);
      // 创建材质对象
      const material = new this.$three.MeshLambertMaterial({
        color: this.randomColor()
      });
      const mesh = new this.$three.Mesh(geometry, material);
      mesh.position.set(obj.x, obj.y, obj.z);
      mesh.name = obj.name;
      if(this.group) {
        this.group.add(mesh);
      }
    },
    lookFor(name){
      if(this.scene && this.scene.getObjectByName(name)) {
        // 通过 getObjectByName() 方法获取name为设备A的模型
        const equipment_A = this.scene.getObjectByName(name);
        // 创建Vector3类型的位置对象
        const position = new this.$three.Vector3();
        // 获取设置A的世界坐标并赋值到position对象中
        equipment_A.getWorldPosition(position);
        // 向量x,y,z坐标值在position的基础上增加50,
        const position_scalar = position.clone().addScalar(100);
        // 创建TWEEN对象并调用Tween方法
        new TWEEN.Tween({
          x: this.camera.position.x,
          y: this.camera.position.y,
          z: this.camera.position.z,
          px: this.controls.target.x,
          py: this.controls.target.y,
          pz: this.controls.target.z,
        }).to({
          x: position_scalar.x,
          y: position_scalar.y,
          z: position_scalar.z,
          px: equipment_A.position.x,
          py: equipment_A.position.y,
          pz: equipment_A.position.z,
        }, 1000).onUpdate(obj => {
          // 设置相机位置
          this.camera.position.set(obj.x, obj.y, obj.z);
          // 设置控制器指向
          this.controls.target.set(obj.px, obj.py, obj.pz);
          // 更新控制器
          this.controls.update();
        }).start();
        this.loop();
      }
    },
    loop() {
      this.renderer.render(this.scene, this.camera);
      TWEEN.update();
      window.requestAnimationFrame(this.loop);
    },
    lookAll() {
      /**
       * 查看整体的思路:
       * 用包围盒 Box3, 将场景中所有的模型包裹起来,计算出 
       * (box3.min.x + box.max.x) / 2 = centerX
       * (box.min.y + box.max.y) / 2 = centerY
       * (box.min.z + box.max.z) / 2 = centerZ
       * , 计算出 centerX, centerY, centerZ  整体的中心坐标,
       *  为了显示包围盒的边界,可以使用Box3Helper辅助对象;
       * 相机的位置position要从当前位置定位到
       *
       *  */
      // 创建包围盒对象
      const box3 = new this.$three.Box3();
      // 设置包围盒中的对象
      const groupBox = box3.expandByObject(this.group);
      console.log(groupBox);
      const box3Helper = new this.$three.Box3Helper(box3, 0xffffff);
      this.scene.add(box3Helper);
      let max_x = groupBox.max.x;
      let max_y = groupBox.max.y;
      let max_z = groupBox.max.z;
      let min_x = groupBox.min.x;
      let min_y = groupBox.min.y;
      let min_z = groupBox.min.z;
      let center_x = (max_x + min_x) / 2;
      let center_y = (max_y + min_y) / 2;
      let center_z = (max_z + min_z) / 2;
      // 
      let increment_x = Math.abs(max_x) > Math.abs(min_x) ? Math.abs(max_x) : Math.abs(min_y);
      let increment_y = Math.abs(max_y) > Math.abs(min_y) ? Math.abs(max_y) : Math.abs(min_y);
      let increment_z = Math.abs(max_z) > Math.abs(min_z) ? Math.abs(max_z) : Math.abs(min_z);

      new TWEEN.Tween({
        x: this.camera.position.x,
        y: this.camera.position.y,
        z: this.camera.position.z,
        px: this.controls.target.x,
        py: this.controls.target.y,
        pz: this.controls.target.z,
      }).to({
        x: center_x + increment_x * 2,
        y: center_y + increment_y * 2,
        z: center_z + increment_z * 2,
        px: center_x,
        py: center_y,
        pz: center_z,
      },1200).onUpdate(obj => {
        this.camera.position.set(obj.x, obj.y, obj.z);
        this.controls.target.set(obj.px, obj.py, obj.pz);
        this.controls.update();
      }).start();
        this.loop();

    },
    saveImg() {
      const link = document.createElement('a');
      const canvas = this.renderer.domElement;
      link.href = canvas.toDataURL('image/png');
      link.download = 'threejs.png';
      link.click();
    },
    randomColor() {
      const numbers = Array.from({ length: 255 }, (_, i) => i);
      const color = [...numbers];
        // 要生成min-max之间的随机数,公式为:Math.random()*(max-min+1)+min
        let i = Math.floor(Math.random() * (color.length - 0 + 1) + 0);
        let j = Math.floor(Math.random() * (color.length - 0 + 1) + 0);
        let k = Math.floor(Math.random() * (color.length - 0 + 1) + 0);
        return new this.$three.Color(
          "rgb(" +
            i +
            ", " +
            j +
            ", " +
            k +
            ")"
        );
    },
    // 在canvas画布上添加监听点击的事件
    addClickEventListener() {
      // 获取id 是 threejs 的元素;
      const dom = window.document.getElementById("threejs");
      const canvasWidth = dom.clientWidth; // 获取元素的宽度
      const canvasHeight = dom.clientHeight; // 获取元素的高度
      dom.addEventListener("click", e => {
        const x = e.offsetX; // 获取鼠标当前点击的点距离dom元素左上角原点  在x轴方向上的距离
        const y = e.offsetY;// 获取鼠标当前点击的点距离dom元素左上角原点  在y轴方向上的距离
        console.log(x,y);
        // 由于canvas画布上的坐标值与普通2d页面的坐标值是不一样的;
        // 在canvas画布上的坐标轴是以画布的中心点为原点,左右x轴,值 -1 ~ 1,,上下y轴,值-1 ~ 1;
        // 坐标需要进行坐标转换
        const pos_x = (x / canvasWidth) * 2 - 1; // 转换后的x坐标
        const pos_y = -(y / canvasHeight) * 2 + 1; // 转换后的y坐标
        // 创建射线投射器对象(可以在初始化方法中创建,每次点击时创建有些浪费资源)
        const rayCaster = new this.$three.Raycaster();
        // 计算射线(在点击位置创建一条射线,用来拾取模型对象)
        rayCaster.setFromCamera(new this.$three.Vector2(pos_x, pos_y), this.camera);
        const mesh_list = [];
        // traverse 是threejs中的递归遍历方法;找出group中的mesh
        this.group.traverse(obj => {
          if(obj.isMesh) {
            mesh_list.push(obj);
          }
        });
        // 射线交叉计算(计算出与自身射线相交的网格模型)
        const intersects = rayCaster.intersectObjects(mesh_list);
        if(intersects && intersects.length > 0) {
          console.log(   intersects[0]);
          this.lookFor(intersects[0].object.name);
        }
      })
    }
    
  },
};
</script>
//
<style lang="less" scoped>
.box-card-left {
  display: flex;
  align-items: flex-start;
  flex-direction: row;

  width: 100%;

  .box-right {
    img {
      width: 500px;
      user-select: none;
    }
  }
}
</style>

到了这里,关于three.js 点按钮,相机飞行靠近观察设备的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Three.js设置相机lookAt无效

    原因:代码中使用了OrbitControls轨道控件来控制相机,这个目标默认为THREE.Vector3(),也就是(0, 0, 0)世界坐标的原点。使用camera.lookAt会无效。 源代码片段: 解决方法: 将 camera.lookAt(100, 0, 100) 改为: 这篇博文写的很详细: https://blog.csdn.net/ithanmang/article/details/82735273

    2024年02月06日
    浏览(51)
  • Three.js第三章——透视投影相机

            Threejs提供了正投影相机 OrthographicCamera (opens new window) 和透视投影相机 PerspectiveCamera (opens new window) 。         透视投影相机  PerspectiveCamera  本质上就是在模拟人眼观察这个世界的规律。         生活中用相机拍照,你相机位置不同,拍照结果也不同,

    2024年04月29日
    浏览(49)
  • three.js从入门到精通系列教程004 - three.js透视相机(PerspectiveCamera)滚动浏览全景大图

    源码下载地址 three.js从入门到精通系列教程004 - three.js透视相机(PerspectiveCamera)滚动浏览全景大图

    2024年01月23日
    浏览(65)
  • three.js入门二:相机的zoom参数

    环境: threejs:129 (在浏览器的控制台下输入: window.__THREE__即可查看版本) vscode window edge 透视相机或正交相机都有一个zoom参数,它可以用来将相机排到的内容在canvas上缩放显示。 要点: 设置zoom后要调用 camera.updateProjectionMatrix(); zoom默认是1,它的取值就像是手机拍照一样

    2024年02月15日
    浏览(56)
  • three.js 使用 tweenjs绘制相机运动动画

    效果: 代码:  

    2024年01月18日
    浏览(53)
  • Three.JS教程1 环境搭建、场景与相机

    Three.js 是一款基于JavaScript的开源3D图形库,它简化了在Web上创建复杂的3D场景和动画的过程。 Three.js 由Ricardo Cabello(也称为mr.doob)于2010年创建,最初是为了填补WebGL技术在那个时候的不足而设计的。随着WebGL的普及和浏览器性能的提升,Three.js逐渐成为Web上3D图形编程的事实标

    2024年01月25日
    浏览(55)
  • Three.js之相机、渲染器、光源、动画、性能监测

    第一个3D案例—透视投影相机 第一个3D案例—渲染器 … Canvas画布布局和全屏 透视投影相机PerspectiveCamera WebGL渲染器WebGLRenderer 辅助观察坐标系AxesHelper 漫反射网格材质MeshLambertMaterial 点光源PointLight 点光源辅助观察PointLightHelper 环境光AmbientLight 平行光DirectionalLight 平行光辅助观

    2024年02月13日
    浏览(45)
  • Three.js教程:阵列立方体和相机适配体验

    推荐:将NSDT场景编辑器加入你的3D工具链 其他系列工具:NSDT简石数字孪生 本节课通过阵列一片立方体,进一步体验下透视投影相机的投影规律。 for循环创建一列模型 双层for循环创建阵列模型 相机位置拉远,可以看到更大的观察范围 超出视锥体远裁界面的范围的会被剪裁掉

    2024年02月11日
    浏览(56)
  • Three.js 进阶之旅:滚动控制模型动画和相机动画 ?

    声明:本文涉及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修改、非法传播、转载、出版、商用、及进行其他获利行为。 专栏上篇文章《Three.js 进阶之旅:页面*滑滚动-王国之泪》 讲解并实现了如何使用 R3F 进行页面图片*滑滚动,本文内容在上节的基础上,学习

    2024年02月06日
    浏览(52)
  • Three.js使用OrbitControls后修改相机旋转方向无效

            在项目中添加了OrbitControls控制器来控制相机的旋转和平移,但是需要修改初始的相机角度,于是我把相机的角度进行修改,如下: 运行项目后发现相机的位置并没有发生变化。原因是相机旋转和移动被OrbitControls控制器托管了。         方法1.于是我尝试创建一个组

    2024年02月16日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包