需求:

1、在场景内添加html元素并动态更新

2、html内容需跟随场景变化

方案:

新加方案:https://www.zhihu.com/question/49929467/answer/118602848

1、在场景内创建一个模型点(多个模型点最好分组,方便管理)

2、获取到模型点

3、创建html元素

4、将html元素绑定到模型位置(将场景的3D坐标转为2D)

5、实时计算元素位置 (显示隐藏)

  1. animate() {
  2. // 动画函数
  3. this.render();
  4. window.requestAnimationFrame(() => this.animate());
  5. TWEEN.update();
  6. this.orbitControls.update();
  7. this.update(); // 更新点
  8. },
  9.  
  10. LoadBox() {
  11. // 创建点。
  12. this.groups = new THREE.Group();
  13. this.groups.name = "btnlist";
  14. for (let index = 0; index < this.nowfloat.length; index++) {
  15. const element = this.nowfloat[index].XYZ;
  16. console.log(element);
  17. let floorGeometry1 = new THREE.PlaneGeometry(1, 1, 1);
  18. var sphereMaterial = new THREE.MeshFaceMaterial({
  19. color: 0xff00ff,
  20. // side: THREE.BackSide,
  21. // visible: false,
  22. });
  23. var floorspheres = new THREE.Mesh(floorGeometry1, sphereMaterial);
  24. floorspheres.position.set(
  25. element.x,
  26. element.y + element.s / 2,
  27. element.z
  28. );
  29. floorspheres.name = this.nowfloat[index].id; //default
  30. this.groups.add(floorspheres);
  31. }
  32. this.buffer_scene.add(this.groups);
  33. // this.render()
  34. },
  35. update() {
  36. // 更新css2D内容位置
  37. let halfWidth = window.innerWidth/2 ;
  38. let halfHeight = window.innerHeight/2;
  39. var btnlist = this.buffer_scene.getObjectByName("btnlist");
  40. if (!btnlist) return;
  41.  
  42. btnlist.traverse((e) => {
  43. var vector = e.position.clone().project(this.buffer_camera);
  44. var htmls = document.getElementsByClassName(e.name)[0];
  45. if (htmls) {
  46. var left = vector.x * halfWidth + halfWidth; // + halfWidth
  47. var top = -vector.y * halfHeight + halfHeight; //+ halfHeight
  48. // console.log(vector.x,vector.y)
  49. if(vector.z >1){
  50. htmls.style = 'display: none;';
  51. }else{
  52. htmls.style = `width:auto;display: flex;position: absolute;left:${
  53. left
  54. }px;top:${top}px`;
  55. }
  56.  
  57. }
  58. });
  59. },

有几种方案

一、直接将文本P成为图片 然后在场景内加载 2D模型将该图片当作模型贴图处理

二、将html内容通过canvas 然后再以模型的方式加载进场景(不做详细解释)

1、创建

  1. getTextCanvas(text){
  2. // 创建贴图文字
  3. var width=512, height=256;
  4. var canvas = document.createElement('canvas');
  5. canvas.width = width;
  6. canvas.height = height;
  7. var ctx = canvas.getContext('2d');
  8. ctx.fillStyle = '#008080';
  9. ctx.fillRect(0, 0, width, height);
  10. ctx.font = 50+'px " bold';
  11. ctx.fillStyle = '#FFFFFF';
  12. ctx.textAlign = 'center';
  13. ctx.textBaseline = 'middle';
  14. ctx.fillText(text, width/2,height/2);
  15. return canvas;
  16. },

2、加载

  1. var geometry = new THREE.PlaneGeometry(e.w, e.h, 30 );
  2. var material = new THREE.MeshBasicMaterial(
  3. {
  4. // map:new THREE.CanvasTexture(this.getTextCanvas(e.content)), // canvas 画图方式
  5. map:new THREE.TextureLoader().load(`${this.GLOBAL.service}img/043img/btn/${e.content}.png`),
  6. } );
  7. var introduce = new THREE.Mesh( geometry, material );
  8. introduce.name= "model introduce"
  9. // plane.location=i.location
  10. introduce.modeltype= 3 //
  11. introduce.position.set(x,y,z);
  12. introduce.lookAt(0,y,0)
  13. skyBox.add(introduce);

三、用CSS2DObject进行处理

1、增加渲染器 CSS2DRenderer

2、使用 three.js 的 CSS2DObject 模块 进行html内容转换 并绑定模型

官网案例

官网示例代码

一般需要这个功能的肯定都不是新手了,所以内容就不做介绍了,这里只需要关注几点

1、增加渲染器(原有的渲染器不动,新增一个CSS2DRenderer渲染器 ):

  1. addhtml() {
  2. // 场景渲染器
  3.  
  4. this.renderer = new THREE.WebGLRenderer();
  5. this.renderer.shadowMapEnabled = true;
  6. this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  7. // this.renderer.gammaOutput = true;
  8. this.renderer.gammaFactor = 2.2;
  9. // this.renderer.setClearColor(new THREE.Color(0xcce0ff));
  10.  
  11. this.renderer.setSize(window.innerWidth*0.95, window.innerHeight*0.95);
  12. document
  13. .getElementById("container")
  14. .appendChild(this.renderer.domElement);
  15. // window.addEventListener("resize", () => this.onWindowResize());
  16.  
  17. this.labelRenderer = new CSS2DRenderer(); // 新增的渲染器
  18. this.labelRenderer.setSize(window.innerWidth*0.95, window.innerHeight*0.95);
  19. // this.labelRenderer.domElement.style.position = 'absolute';
  20. // this.labelRenderer.domElement.style.top = 0;
  21. this.labelRenderer.domElement.style="pointer-events: auto;position: absolute;top: 0px;" // 处理新的渲染器
  22. document.getElementById("container").appendChild(this.labelRenderer.domElement);
  23. },
  1. animate() {
  2. // 渲染
  3. this.renderer.render(this.scene, this.camera);
  4. this.labelRenderer.render(this.scene, this.camera);// 加载新渲染器
  5. window.requestAnimationFrame(() => this.animate());
  6. TWEEN.update();
  7. },

注意:官网示例只适应于全屏的情况 不全屏的情况请自行调整

2、增加内容容器:

  1. <template>
  2. <div class="project">
  3. <div id="text" style=" position: relative;width: 30%;
  4. height: 100px;
  5. color: #fff;">
  6. {{modelnumber}}
  7. </div>
  8. <div id="container">
  9.  
  10. </div>
  11. </template>

3、绑定模型(创建模型什么的这里就不解释了):

  1. // 2D 文本
  2. // let laberDiv = document.createElement('div');//创建div容器
  3. let laberDiv = document.getElementById('text');//获取div容器
  4. // laberDiv.innerHTML=`
  5. // <div class="leftTip" style="">
  6. // ${this.modelnumber}
  7. // </div>
  8. // `;
  9. laberDiv.style.marginTop = '-1em';
  10. let pointLabel = new CSS2DObject(laberDiv);
  11. pointLabel.position.set(0,100,0); // 相对模型的位置
  12. console.log(pointLabel)
  13. skyBox.add(pointLabel); //绑定到模型

也看到了,你也可以选择直接新建一个容器、但是我尝试的时候内容无法动态变化、如果你不需要动态变化也可以直接新建

找资料的时候看到一个问题(没有尝试)、创建的这个容器切换场景不会消失、需要注意处理、这个创建出来的不在模型列表内、而是在dom里面、所以遇到这个情况、请尝试直接处理dom

效果:

注:

前面两种方式是直接在场景内加载一个模型、第三种方式是将元素绑定在模型上

three.js 添加html内容、文本的更多相关文章

  1. react修改app.js添加中文内容后中文部分乱码解决

    [问题]:配置完react后修改app.js内容时添加中文出现如下乱码的中文. [A解决]文档——文本编码——转换文本编码,在弹出窗口修改,确定,搞定 [B解决]首先在EditPlus内:工具——首选 ...

  2. JS添加删除一组文本框并对输入信息加以验证

    在做项目中遇到这样一个问题,就是我们需要添加几组数据到数据库,但是具体几组数据不确定,有客户来填写,比如我们需要添加打折策略,可能个策略有很多组方案,比如“满100打5折,满200打4折,满500打3 ...

  3. 用JS添加文本框案例代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 通过 js 修改 html 的文本内容或者样式

    通过 js 修改 html 的文本内容 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  5. JS控制页面内容

    JS操作页面内容 innerText:普通标签内容(自身文本与所有子标签文本)innerHTML:包含标签在内的内容(自身文本及子标签的所有)value:表单标签的内容outerHTML:包含自身标签 ...

  6. atitit.js的 字符串内容 转义  js处理html

    atitit.js的 字符串内容 转义  js处理html 1. js处理html的问题 1 2. js的 字符串内容 转义 1 2.1. 处理流程 1 3. 下面的表格列出了其余的特殊字符,这些特殊 ...

  7. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  8. JS 仿支付宝input文本输入框放大组件

    input输入的时候可以在后边显示数字放大镜 <!doctype html> <html lang="en"> <head> <meta ...

  9. 解决UEditor编辑时,只添加视频内容,不添加文字,视频信息不能保存到数据库的问题

    造成这个问题的原因是富文本保存内容时会筛除空标签,然后统计是否有内容,通过字数统计也可以看到,上传完视频后字数还是零,因为视频上传后是<video></video>标签,这个标 ...

随机推荐

  1. 从net到java:MyBatis快速入门

    第一:这不是net与java的对比,只是我学习java相关知识梳理的笔记. 第二:这也没有否认net,只是现在的工作需要自己会java. 第三:这不深入.只是我看了些官网和网上的视频,算是入门的总结. ...

  2. 阿里云视频点播获取视频点播的video信息

    背景 因为在项目中需要使用阿里云的视频点播服务,需要获取视频点播的时长信息. 工具类 生成签名串Signature SignatureUtils.java package com.meeno.wzq. ...

  3. C# prism 框架

    定义Region (RegionManager) 定义Region 的方式有两种,一个是在XMAL界面指定,另一种这是代码当中指定. RegionManager.RegionName(XMAL) Re ...

  4. vscode如何配置ts的lint,如何配置才能让eslint和prettier不冲突一键格式化代码(vue开发使用)

    最近在使用ts,发觉tslint在vscode上使用很不方便,不如eslint一键格式化高效,就想着能不能配置下vscode让其像写js一样爽 这篇文章主要解决2个问题,第一个是如何让vscode使用 ...

  5. nacos配置

    server: port: 3377 spring: application: name: nacos-config-client cloud: nacos: discovery: #nacos 服务 ...

  6. 机器学习基本概念:batch_size、epoch、 iteration

    batch_size 单次训练用的样本数,通常为2^N,如32.64.128... 相对于正常数据集,如果过小,训练数据就收敛困难:过大,虽然相对处理速度加快,但所需内存容量增加. 使用中需要根据计算 ...

  7. MySQL——字符串类型——char(n) 和 varchar(n)

    MySQL 的 char(n) 和 varchar(n) 括号中 n 代表字符的个数,而非字节个数,这里说的字符不论文字种类,假设一个字段的数据类型被规定为 char(2),则可以在这个字段上插入 ' ...

  8. zap高性能日志

    摘要 日志在整个工程实践中的重要性不言而喻,在选择日志组件的时候也有多方面的考量.详细.正确和及时的反馈是必不可少的,但是整个性能表现是否也是必要考虑的点呢?在长期的实践中发现有的日志组件对于计算资源 ...

  9. Nginx的高级使用

    1.概述 之前介绍过Nginx的简单使用,今天来聊聊Nginx的一些高级使用. 2.使用Nginx解决跨域问题 当公司存在多个域名时,两个不同的域名相互访问就会存在跨域问题. 或者在进行前端开发时,通 ...

  10. 洛谷P3130 haybalesCounting Haybale P 题解

    题目 [USACO15DEC]haybalesCounting Haybale P 题解 最近刚刚自学了线段树这个数据结构,恰巧做到了这道线段树的模板题.其实也没有什么好多说的,接触过线段树的大犇肯定 ...