three.js加vue2实现.glb渲染,旋转元素,放大缩小,以及元素点击事件

<template>
  <div ref="container" id="container"></div>
</template>

<script>
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

export default {
  data() {
    return {
      camera: {},
      renderer: {},
      controls: null,
    };
  },
  mounted() {
    let that = this;
    var fov = 75; // 拍摄距离,视野角值越大,场景中的物体越小
    let near = 1; // 最小范围
    var far = 1000;
    // 创建场景
    const scene = new THREE.Scene();

    // 创建相机
    const camera = new THREE.PerspectiveCamera(
      fov,
      window.innerWidth / window.innerHeight,
      0.1,
      far
    );
    this.camera = camera;
    // camera.position.set(0, 0, 10); // 设置相机在 z 轴上的位置
    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer = renderer;
    let dom = this.$refs.container;
    this.$refs.container.appendChild(renderer.domElement);
    var cub = new THREE.CubeTextureLoader().load(
      Array(6).fill(require("@/static/3d/img/backb.jpg"))
    );
    cub.encoding = THREE.sRGBEncoding;
    cub.flipY = false;
    scene.background = cub;

    // 添加光源
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 方向光颜色和强度
    directionalLight.position.set(1, 1, 1); // 光源位置
    scene.add(directionalLight);

    // 创建控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    this.controls = controls;
    controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
    controls.dampingFactor = 0.05; // 阻尼系数
    controls.rotateSpeed = 0.1; // 旋转速度

    // 加载3D模型
    const loader = new GLTFLoader();
    loader.load("/3D/house2.glb", (gltf) => {
      scene.add(gltf.scene);
      function animate() {
        requestAnimationFrame(animate);
        controls.update(); // 更新控制器状态
        renderer.render(scene, camera);
      }
      const object = gltf.scene; // 获取加载的3D模型对象
      // 将点击事件绑定到立方体上
      object.traverse((child) => {
        console.log(child.name);
        //child.name可以在three editor中找到
        if (child instanceof THREE.Mesh && child.name === "node_id209") {
          child.userData.onClick = () => {
            // 在这里处理点击事件的逻辑
            alert("您好!");
          };
          child.userData.clickable = true;//将元素设置为可点击
        }
        if (child instanceof THREE.Mesh && child.name === "node_id183") {
          child.userData.onClick = () => {
            // 在这里处理点击事件的逻辑
            alert("别点我的头!");
          };
          child.userData.clickable = true;
          }
      });

      scene.add(object);

      // 添加点击事件监听器
      dom.addEventListener("mousedown", onMouseDown, false);

      function onMouseDown(event) {
        const mouse = new THREE.Vector2();
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        // 创建射线投射器
        const raycaster = new THREE.Raycaster();
        raycaster.setFromCamera(mouse, camera);

        // 检测射线与可点击对象的交互
        const intersects = raycaster.intersectObjects(object.children, true);
        intersects.forEach((intersect) => {
          const { object } = intersect;

          // 检查是否为可点击对象
          if (
            object.userData.clickable &&
            typeof object.userData.onClick === "function"
          ) {
            // 调用点击事件处理函数
            object.userData.onClick();
          }
        });
      }

      animate();
    });

    // 滚轮事件
    dom.addEventListener("mousewheel", mousewheel, false);

    function mousewheel(e) {
      e.preventDefault();
      if (e.deltaY < 0) {
        // 当滚轮向上滚动时
        camera.position.z -= 1; // 向前移动相机
      } else {
        // 当滚轮向下滚动时
        camera.position.z += 1; // 向后移动相机
      }
      renderer.render(scene, camera);
    }

    // 窗口大小改变事件
    window.addEventListener("resize", this.handleResize);
  },
  methods: {
    handleResize() {
      const width = window.innerWidth;
      const height = window.innerHeight;
      this.camera.aspect = width / height;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(width, height);
    },
    beforeDestroy() {
      window.removeEventListener("resize", this.handleResize);
    },
  },
};
</script>

<style>
/* 可以自定义样式 */
#container {
  margin: 0;
  padding: 0;
}
</style>

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值