如何在three.js 上覆盖HTML 文本/按钮?

Posted

技术标签:

【中文标题】如何在three.js 上覆盖HTML 文本/按钮?【英文标题】:How to overlay HTML text/buttons on three.js? 【发布时间】:2018-04-28 02:39:17 【问题描述】:

好的,这里对 three.js 很陌生,但我正在努力实现 Google 所拥有的 https://beinternetawesome.withgoogle.com/interland

看 - 他们有他们的全屏 Three.js 场景和他们的文本、按钮(很明显是 html div,不是通过 JS 生成的)完美地覆盖在上面。

我看过 https://discourse.threejs.org/t/trying-to-overlay-a-button-and-text-on-top-of-a-three-js-scene/390/2

和类似的问题,但无法理解执行此操作的正确方法。我不想在 Three.js 中生成我的 UI 元素 - 我只想使用 HTML。

到目前为止,我生成了我的 Three.js 画布并将其添加到我的文档中,以便它获取并保持我的窗口的整个宽度/高度:

var controls, camera, renderer, scene, container, w, h;
renderer    = new THREE.WebGLRenderer()
// container = document.getElementById('canvas');
container = window;
w = container.innerWidth;
h = container.innerHeight;
renderer.setSize(w, h)
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild(renderer.domElement);

然后使用我现有的 HTML:

<body>
    <div id="ui">
    <p id="message">Test to change</p>
</div>

无论我如何使用 CSS 或 UI div 的 z 索引,我都会将 UI div 卡在顶部:

如何在 three.js 场景上覆盖 HTML 以实现 Google 效果?我做错了什么?

我需要我的画布来填充整个窗口,就像 Google 所做的那样,并且无法实现它似乎事先制作了 canvas HTML 元素并尝试在 JS 中附加所有内容。

【问题讨论】:

【参考方案1】:

创意取决于你,因为有很多方法可以达到预期的效果。

可以从 Three.js 官网查看examples 的源代码开始。在那里您可以看到示例的info 部分如何在网页上设置。

var buttons = document.getElementsByTagName("button");
for (let i = 0; i < buttons.length; i++) 
  buttons[i].addEventListener("click", onButtonClick, false);
;

function onButtonClick(event) 
  alert(event.target.id);


var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial(
  color: 0x00ff00,
  wireframe: true
);
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

var animate = function() 
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
;

animate();
body 
  overflow: hidden;
  margin: 0;


.ui 
  position: absolute;


button
  margin: 20px;
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<div style="width:100%;height:50px;text-align: center; color:white;" class="ui">Info header</div>
<button style="top:0" id="fire" class="ui">Fire</button>
<button style="bottom:0" id="spell" class="ui">Spell</button>
<button style="right:0" id="health" class="ui">Health</button>
<button style="right:0; bottom:0;" id="shield" class="ui">Shield</button>

【讨论】:

谢谢 - 有没有办法确保three.js 场景即使在拖动窗口时也保持场景的宽度/高度?我这样做时会看到窗口背景 对于任何想知道的人 - 使按钮位于场景顶部的主要代码行是每个按钮的 top/bottom/right 值。【参考方案2】:

z-index 仅适用于位置属性,position: staticposition: initial 的情况除外。

这个按钮类在我的threejs 场景中运行良好。您可以相应地编辑left, top

button 
    position: absolute;
    display: block;
    z-index: 99;
    left: 50%;
    top: 50%;
    

【讨论】:

这是对我想做的事情的一种安慰奖,但它会起作用。我很惊讶 three.js 还没有引入 9-patch 图像系统,或者至少是一种在 webgl 渲染器中使用 css 功能的方法

以上是关于如何在three.js 上覆盖HTML 文本/按钮?的主要内容,如果未能解决你的问题,请参考以下文章

Three.js如何在AR应用程序上触摸按钮时更改一个对象的两种材质

如何从 GLTF 模型动态覆盖纹理 - Three.js

如何在 Autodesk Forge 中动态更新 THREE.js PointCloud 覆盖

在three.js中动态创建二维文本

如何使用 three.js 向 Forge Viewer 添加文本?

在 three.js 中的球体上使用纹理