vue + threejs 给3D模型添加label标签(dom的方式)

2023-11-19

 webGL.js封装的代码。

const THREE = window.THREE;
// webGL对象配置
export const webglOBJ = {
  renderDom: null,
  Scene: null, // 场景 
  camera: null, // 摄像头
  renderer: null, // 渲染器
  senceAdd (objList = []) {
    objList.forEach(v => {
      webglOBJ.Scene.add(v);
    });
  },
  // 创建场景
  createSence (renderDom) {
    this.renderDom = renderDom;
    webglOBJ.Scene = new THREE.Scene();
    return webglOBJ.Scene;
  },
  // 创建摄像机
  createCamera ({innerWidth, innerHeight, position} = {}) {
    const { width, height } = this.renderDom.getBoundingClientRect();
    let camera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000);
    camera.position.x = -50;
    camera.position.y = 30;
    camera.position.z = 50;
    camera.lookAt(webglOBJ.Scene.position); // 视角
    webglOBJ.camera = camera; // 视角
    return webglOBJ.camera;
  },
  createRenderer () {
    let renderer = new THREE.WebGLRenderer();
    const {width, height} = this.renderDom.getBoundingClientRect();
    renderer.setSize(width, height);
    renderer.setClearColor(new THREE.Color(0xcccccc));
    renderer.shadowMap.enabled = true;
    this.renderDom.appendChild(renderer.domElement);
    webglOBJ.renderer = renderer;
    return webglOBJ.renderer;
  },
  createPlane (textureLoaderUrl, textureNormalUrl) {
    let planeGeometry = new THREE.PlaneGeometry(60, 60, 1, 1); // 平面网格
    let textureLoader = new THREE.TextureLoader();
    let texture = textureLoader.load(textureLoaderUrl);
    let textureNormal = textureLoader.load(textureNormalUrl);
    // 加载高光贴图
    let planeMaterial = new THREE.MeshPhongMaterial({
      // specular: 0xff0000,//高光部分的颜色
      shininess: 30, //高光部分的亮度,默认30
      map: texture, // 普通纹理贴图
      roughness: 0.3,
      lightMap: textureNormal,
      // normalMap: textureNormal, //法线贴图
      bumpScale: 3
    }); // 材质对象Material
    // let planeMaterial = new THREE.MeshLambertMaterial({color: 0xcccccc});
    let plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.rotation.x = -0.5 * Math.PI;
    plane.position.x = 0;
    plane.name = '平面物体ID=' + 1;
    plane.position.y = 0;
    plane.position.z = 0;
    plane.receiveShadow = true;
    return plane;
  },
  createBoxGeometry (textureLoaderUrl, {x, y, z}) {
    // 创建立方体
    let textureLoader = new THREE.TextureLoader();
    let textureNormal = textureLoader.load(textureLoaderUrl);
    let boxGeometry = new THREE.BoxGeometry(10, 10, 10, 200);
    let texture1 = textureLoader.load(textureLoaderUrl);
    let boxGeometryMaterial = new THREE.MeshLambertMaterial({
      // specular: 0xff0000,//高光部分的颜色
      shininess: 10, //高光部分的亮度,默认30
      normalScale: new THREE.Vector2(2.2, 2.2),
      map: texture1, // 普通纹理贴图
      normalMap: textureNormal, //法线贴图
      bumpMap: textureNormal,
      bumpScale: 0.3
    });
    let box = new THREE.Mesh(boxGeometry, boxGeometryMaterial);
    box.name = '正方物体ID=' + 2;
    box.position.x = x;
    box.position.y = y;
    box.position.z = z;
    box.castShadow = true;
    return box;
  },
  // 点光源
  createSpotLight () {
    // 点光源
    let spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(-60, 40, -20);
    spotLight.castShadow = true;
    return spotLight;
  },
  // 平行光
  createDirectionalLight (target) {
    // 平行光
    let directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    // 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
    directionalLight.position.set(-90, 80, -20);
    // 方向光指向对象网格模型mesh2,可以不设置,默认的位置是0,0,0
    // directionalLight.target = target;
    return directionalLight;
  },
  // 环境光
  createAmbient (color = 0x444444) {
    let ambient = new THREE.AmbientLight(color);
    // ambient.castShadow = true;
    return ambient;
  },
  createDatGui () {
    let gui = {
      bump: 0.03,
      animation: false,
    };
    let datGui = new dat.GUI();
    //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
    datGui.add(gui, "bump", -1, 1).onChange(function (e) {
      box.material.bumpScale = e;
    });
    datGui.add(gui, "animation");
    return datGui;
  },
  // 创建控制轴
  createControls () {
    let controls = new THREE.OrbitControls(webglOBJ.camera, webglOBJ.renderDom);
    return controls;
  },
  // 创建帮助
  createAxisHelper () {
    let axisHelper = new THREE.AxisHelper(250);
    return axisHelper;
  },
  // 初始化webGL对象
  webglRender (Scene, camera) {
    webglOBJ.renderer.render(Scene, camera);
    window.requestAnimationFrame(webglOBJ.webglRender);
  }
};

/**
 * 添加标签:dom方式
 * @param {*} targePosition :需要传递当前标签的位置
 * @param {*} targetId :标签对应的dom的唯一ID,暂且用时间戳代替,避免重复
 * @param {*} innerHTML :标签对应html
 */
export function labelTag (camera, targePosition, targetId, innerHTML, webGLdom) {
  const { width, height } = webGLdom.getBoundingClientRect();
  let worldVector = new THREE.Vector3(targePosition.x, targePosition.y, targePosition.z);
  let vector = worldVector.project(camera);
  let halfWidth = width / 2,
    halfHeight = height / 2;
  let x = Math.round(vector.x * halfWidth + halfWidth);
  let y = Math.round(-vector.y * halfHeight + halfHeight);
  /**
   * 更新立方体元素位置
   */
  let div = document.getElementById(targetId);
  div.style.left = x + 'px';
  div.style.top = y + 'px';
  // div.innerHTML = `uuid:${innerHTML.uuid}`;
}

vue中引用: 

<template>
<div>
  <div class="three-box_wrapper"></div>
  <div :id="`sign${idx + 1}`" style="position: absolute;" v-for="(v, idx) in labels" :key="idx">
    <div class="sign" :uuid="v.uuid">
      <div class="name">我是标签1</div>
      <div class="data">数据: {{v.uuid}}</div>
    </div>
  </div>
</div>
</template>

<script>
import {webglOBJ, labelTag} from '@/utils/webGL/webGL.js';
export default {
  name: 'threeBox',
  data () {
    return {
      labels: []
    };
  },
  mounted () {
    this.int();
  },
  methods: {
    createLabel () {

    },
    int () {
      const imgBG = require('./img.jpg');
      const webGLdom = document.querySelector('.three-box_wrapper');
      const sence = webglOBJ.createSence(webGLdom);
      const camera = webglOBJ.createCamera();
      const renderer = webglOBJ.createRenderer();
      const plane = webglOBJ.createPlane(imgBG, imgBG);
      const boxGeometry = webglOBJ.createBoxGeometry(imgBG, {x: 10, y: 5, z: 10});
      const boxGeometry1 = webglOBJ.createBoxGeometry(imgBG, {x: -10, y: 5, z: 10});
      const spotLight = webglOBJ.createSpotLight();
      const directionalLight = webglOBJ.createDirectionalLight(boxGeometry);
      const ambient = webglOBJ.createAmbient();
      const datGui = webglOBJ.createDatGui();
      const controls = webglOBJ.createControls();
      const axisHelper = webglOBJ.createAxisHelper();
      // 将对象添加到场景中去
      webglOBJ.senceAdd([plane, boxGeometry, boxGeometry1, spotLight, directionalLight, ambient, datGui, controls, axisHelper]);
      // webglOBJ.webglRender(sence, camera, renderer);
      console.log(sence, 'sence');
      const vm = this;
      function render(html) {
        vm.labels = sence.children.filter(v => v.type == 'Mesh');
        vm.$nextTick(() => {
          sence.children.forEach((val, idx) => {
            if (val.type == 'Mesh') {
              const {x, y, z} = val.position;
              labelTag(camera, {x,  y, z}, `sign${idx + 1}`, val, webGLdom);
            }
          });
        });

        renderer.render(sence, camera);
        requestAnimationFrame(render);
      };
      render();

      // 监听点击事件查看点击的元素
      let raycaster = new THREE.Raycaster();
      let mouse = new THREE.Vector2();
      // 点击了哪个模型
      function clickEvent() {
        if (event.target.tagName == 'CANVAS') {
          mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
          sence.updateMatrixWorld(true);
          // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
          raycaster.setFromCamera(mouse, camera);
          // 获取raycaster直线和所有模型相交的数组集合
          let intersects = raycaster.intersectObjects(sence.children, true);
          if (intersects[0]) {
            console.log(intersects[0]);
          }
        }
      }
      window.addEventListener('click', clickEvent, false);
    }
  }
};
</script>

<style lang="scss" scoped>
  .three-box_wrapper {
    position: relative;
    width: 100%;
    height: 800px;
    border: 1px solid #ccc;
  }
  div[id *= "sign"] {
    width: 250px;
    height: 100px;
    background: rgba(0, 0, 0, .65);
    .sign{
      div {
        color: #fff;
        text-align: left;
        padding: 0 5px;
      }
    }
  }
</style>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue + threejs 给3D模型添加label标签(dom的方式) 的相关文章

  • 使用本机 JavaScript 获取过渡中的 CSS 值

    这个问题之前被问过 但答案使用了 jQuery here https stackoverflow com q 8920934 3186555 因此 我将调整问题以专门询问native解决方案 to 最小化依赖关系 假设您有一个 div 然后
  • React + Semantic-UI:在 UI MODAL 中使用表单

    在没有 React 的普通旧 Semantic UI 中 我已经能够毫无问题地将表单放入 Modal 中 使用 Semantic UI React 版本 我能够在模态中显示表单 但它并没有按照我期望的方式工作 例如 模态框显示后 模态框内的
  • ExpressJS - DELETE 请求后 res.redirect

    我一直在寻找如何执行此操作 我正在尝试在发出删除请求后重定向 这是我正在使用的代码没有重定向 exports remove function req res var postId req params id Post remove id p
  • 如何按字母顺序排序并先小写排序

    如何获得以下排序的结果Food to Eat然后是 食物123 显然 第二个较低的 o 应该将 要吃的食物 带到排序后的第一个项目中 我很惊讶这个问题不容易通过谷歌找到答案 这个壮举没有包含在 javascript 标准中也让我感到惊讶 F
  • glClipPlane - webGL 中有等效的吗?

    我有一个 3D 网格 是否有可能像这样呈现剖面图 剪辑 glClipPlane在OpenGL中 我正在使用 Three js r65 我添加的最新着色器是 片段着色器 uniform float time uniform vec2 reso
  • Nodejs 一个接一个地运行异步函数

    我是 JS nodejs 的新手 所以如果我不能提出切中要害的问题 请原谅我 所以基本上 如果我有两个异步函数 async function init async function main 如何确保在 init 完成其异步请求后调用 ma
  • 如何设置视频文件的预览,从输入类型='文件'中选择

    在我的模块之一中 我需要从 input type file 浏览视频 之后我需要在开始上传之前显示选定的视频 我使用基本的 HTML 标签来显示 但它不起作用 这是代码 document on change file multi video
  • 通过Javascript捕获右键单击,无需节点

    当使用英语以外的任何其他语言时 Flash 播放器在 Firefox Chrome 中使用 wmode window 以外的任何内容时都会出现错误 此错误已报告但尚未修复 http bugs adobe com jira browse FP
  • 使用replace()清除减号和点输入类型数字字段

    I use replace 从输入字段中删除非数字字符 如下所示
  • CORS 在 jquery 中工作正常,但在 angularjs 中不行

    我的服务器端是php mysql 我正在另一个域的 Web 服务中进行 Ajax 调用 其中启用了 的访问控制 var postUrl http logical brains com elance clone test login php
  • Highcharts 对堆积条形图进行排序

    我没有看到任何与我在 Highcharts 中遇到的确切场景相匹配的解决方案 因此我将我的发现发布在这里 我在 Highcharts 中有一个堆积条形图 需要按值从大到小对条形图进行排序并维护它们的类别关系 通常 首选解决方案是在将数据发送
  • 单击导航项锚链接时如何关闭切换菜单

    请看我的FIDDLE http jsfiddle net ayhpp8ax 我有一个带有 响应式 导航菜单 带有指向页面上元素的锚链接 的 1 页网站 当浏览器视口小于特定宽度 在我的情况下为 767px 时 使用此 javascript
  • Angular UI 模式的范围问题

    我无法理解 使用角度 UI 模式的范围 虽然这里不是很明显 但我已经正确设置了模块和所有内容 据我所知 但这些代码示例尤其是我发现错误的地方 index html 其中重要部分 div class btn group div
  • 在 HTML5 Javascript 中将 BlobBuilder 转换为字符串

    function blobToString blob var reader new FileReader var d reader onloadend function d callback reader result console lo
  • 可能未处理的承诺拒绝(id 0)类型错误 GET 或 HEAD 请求不允许主体

    import React from react import FlatList ActivityIndicator Text View from react native export default class FetchExample
  • Jquery 悬停卡

    我在用着http designwithpc com Plugins Hovercard http designwithpc com Plugins Hovercard 但我不知道如何在悬停卡上声明 var 每个工作描述都有自己的 ID 当悬
  • JavaScript 添加布尔值

    console log true true 2 console log typeof true true number console log isNaN true true false 为什么两个布尔类型相加会产生一个数字 我有点理解 如
  • 在 Internet Explorer 中使用什么来监视 jscript 内存使用情况

    我们正在调试 GWT 应用程序 在 Firefox 中运行正常 在 IE6 0 中开始运行正常 但一段时间后 它就会崩溃并开始爬行 经过一些测试后 我们怀疑存在一些内存问题 使用了太多内存 内存泄漏等 除了使用taskmanager和pro
  • 位置特征检测:固定

    我正在尝试找到一个脚本来检测设备是否放置position fixed元素相对于视口而不是整个文档 目前 标准桌面浏览器和 Mobile Safari 适用于 iOS 5 都是这样做的 而 Android 设备则相对于整个文档放置固定元素 我
  • 如何在没有 jQuery 的情况下删除 Javascript 中的元素

    我试图通过以下方式从 DOM 中删除 Div a 标签嵌套在其中 我想我正在寻找的是 jQuery 的纯 Javascript 版本 div remove 这是html设置 div a href Click me to remove the

随机推荐

  • g2o的基本使用

    参考 https www jianshu com p e16ffb5b265d 参考 https zhuanlan zhihu com p 36889150 图是一种数据结构 在图优化中 用顶点 vertex 表示优化变量 用边 edge
  • Smali--Dalvik虚拟机指令语言-->【android_smali语法学习一】

    最近一周在研究rom移植 所以就对Smali语言学习了一下 Smali语言其实就是Davlik的寄存器语言 Smali语言就是android的应用程序 apk通过apktool反编译出来的都有一个smali文件夹 里面都是以 smali结尾
  • 基于当前系统制作docker镜像

    1 通过tar 备份目录 tar cvpf home buildrpm tar directory exclude proc exclude sys exclude dev exclude run root localhost home l
  • 不能安装64位office提示已安装32位的

    问题描述 安装64位office办公软件的时候提示已经安装32位的office办公软件所以无法继续安装 但实际上之前安装的32位的office办公软件已经卸载了 问题现象截图如下 解决办法 从问题描述中 我们其实已经能够看出问题原因了 类似
  • React的超详细讲解

    React React的重点 webpack webpack 是一个现代 JavaScript 应用程序的静态模块打包器 module bundler 当 webpack 处理应用程序时 它会递归地构建一个依赖关系图 dependency
  • 虚幻引擎程序化资源生成框架PCG 之 UPCGBlueprintElement源码笔记(一)

    UPCGBlueprintElement是PCGGraph中自定义节点的基类 但官方目前还没有给出详细的文档 所以从源代码里找点答案 文章目录 可覆盖函数 Override Functions Excute 和 Excute with Co
  • web.xml加载顺序

    web xml加载顺序 应用服务器启动时web xml加载过程 至于这些节点在xml文件中的前后顺序没有关系 不过有些应用服务器 我曾碰到过的 websphere就严格要求web xml的节点顺序 否则部署不成功 所以还是赞成按照web x
  • CSS 样式穿透

    1 穿透语法 如果给样式中声明scop 那么页面的类会增加data 562e3wue8等属性 此时就需要用到 gt gt gt 或者 deep 或者 v deep 以后用后两个比较多 如果在样式类前面 v deep 则会自动找到 data
  • 快速搭建一个自己的服务器详解(java环境)

    一 服务器的购买 1 我选择的是阿里云的服务器 学生价9 5元一个月 百度直接搜索阿里云 然后点击右上角登录 推荐大家用支付宝扫码登录 方便快捷 阿里云官网的东西比较多 登录后我找了很久也没有找到学生服务器在哪里卖 最后在咨询里找到了这个网
  • 喜爱夜蒲3_百度百科

    喜爱夜蒲3 百度百科 喜爱夜蒲3
  • LeetCode707.设计链表

    题目描述 707 设计链表 力扣 LeetCode 这道题用单向链表和双向链表都能写 因为对双向链表不是很熟 所以就用双向链表来写了 由于初始化的链表并没有放入任何元素 所以这个结点就当成哑结点来处理 而且这样对之后的增删操作也更便利 C语
  • 通配符的使用

    通配符是一种特殊语句 主要有星号 和问号 用来模糊搜索文件 当查找文件夹时 可以使用它来代替一个或多个真正字符 当不知道真正字符或者懒得输入完整名字时 常常使用通配符代替一个或多个真正的字符 SQL 通配符 在搜索数据库中的数据时 SQL
  • java最大线程数

    Xms 初始堆大小 如 Xms256m Xmx 最大堆大小 如 Xmx512m Xmn 新生代大小 通常为 Xmx 的 1 3 或 1 4 新生代 Eden 2 个 Survivor 空间 实际可用空间为 Eden 1 个 Survivor
  • 华为OD机试 - 经典屏保(Java)

    题目描述 DVD机在视频输出时 为了保护电视显像管 在待机状态会显示 屏保动画 如下图所示 DVD Logo在屏幕内来回运动 碰到边缘会反弹 请根据如下要求 实现屏保Logo坐标的计算算法 屏幕是一个800 600像素的矩形 规定屏幕的左上
  • PermissionError: [WinError 5] 拒绝访问。解决办法

    PermissionError WinError 5 拒绝访问 问题描述 解决办法 一 找到programdata下anaconda3的python 二 进入Users的权限 将除了特殊权限外 全部挂上 三 在返回到anaconda3的目录
  • Nginx-简介

    用Python语言开发的站点使用的Web服务器主要有Nginx Apache以及淘宝的Tengine Nginx是由Igor Sysoev在2004年发布的一个开源 高性能的HTTP服务器和反向代理 它还可以用来作为IMAP POP3的代理
  • K8s基础6——应用配置管理方案、调度策略、污点和污点容忍

    文章目录 一 应用配置管理方案 1 1 ConfigMap 1 1 1 注入变量 1 1 2 挂载数据卷 1 2 Secret 1 2 1 数据卷挂载 1 2 2 变量注入 二 调度策略 2 1 nodeSelector定向调度 2 1 1
  • Github上 10 个开源免费且优秀的后台控制面板

    Web 开发中几乎的平台都需要一个后台管理 但是从零开发一套后台控制面板并不容易 幸运的是有很多开源免费的后台控制面板可以给开发者使用 那么有哪些优秀的开源免费的控制面板呢 我在 Github 上收集了一些优秀的后台控制面板 并总结得出 T
  • HTTP协议(下)

    前面我介绍了什么是HTTP协议 以及HTTP的协议格式 接下来我介绍一下如何使用代码构造出HTTP请求 以及在介绍一下HTTPS 目录 一 通过代码构造HTTP请求 1 基于HTML JS 1 1 基于form表单 1 2 基于ajax 2
  • vue + threejs 给3D模型添加label标签(dom的方式)

    webGL js封装的代码 const THREE window THREE webGL对象配置 export const webglOBJ renderDom null Scene null 场景 camera null 摄像头 rend