我使用threejs编辑器作为一些三个工作的基础。 当用户将鼠标悬停在某些元素上时,我试图显示一些工具提示。 为了实现这一点,我使用了一个画布,它在精灵上呈现为纹理。
// create a canvas element
var canvas1 = document.createElement('canvas');
var context1 = canvas1.getContext('2d');
context1.font = "Bold 20px Arial";
context1.fillStyle = "rgba(0,0,0,0.95)";
context1.fillText('Hello, world!', 0, 20);
// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;
// use the texture as material
var spriteMaterial = new THREE.SpriteMaterial({
map: texture1,
useScreenCoordinates: false
});
// create the sprite and add it tho the scene
var sprite1 = new THREE.Sprite(spriteMaterial);
sprite1.scale.set(1000, 500, 1.0);
sprite1.position.set(50, 50, 0);
scene.add(sprite1);
var i = 0;
// change the canvas' content
setInterval(function () {
context1.clearRect(0, 0, canvas1.width, canvas1.height);
var message = 'test' + i++;
context1.fillText(message, 4, 20);
texture1.needsUpdate = true;
}, 1000)
" TEST0"显示,但精灵不更新。如何更新精灵上的文字?我在这里错过了一些缓存失效吗?
答案 0 :(得分:1)
为什么渲染3D画布上的文本框?通过在页面的2D上下文中投影3D对象位置来定位2D html对象会更好。
优点是不会有任何渲染性能下降,您可以使用常规的CSS / HTML样式进行信息框。
检查a great example on how you can do that here。
而another one属于此 stackoverflow answer。工作就像这样简单:
var proj = toScreenPosition(divObj, camera);
divElem.style.left = proj.x + 'px';
divElem.style.top = proj.y + 'px';
但如果你进行一些谷歌搜索,你可以很容易地找到更多的例子......
Here is a fiddle 愚弄。
答案 1 :(得分:0)
我认为它没有用,因为你没有设置画布的高度和宽度。
canvas1.width = 256;
canvas1.height = 256;
这一行也是一个问题:context1.fillStyle = "rgba(0.0,0,0,0.95)";
我将其更改为:context1.fillStyle = '#ff0000';
以便我的工作
Here is a fiddle实现了您的代码,只是将高度和宽度添加到画布并更改了fillStyle
如果满足您的需求,威尔特的答案可能是更好的选择。
答案 2 :(得分:-1)
编辑:我是个白痴。这个问题已经2岁了。
这似乎对我有用...确定不忽略控制台中的某些错误吗?您是否在setInterval中设置了断点以确保它被调用?
我确实必须将更新移至renderloop,因为似乎没有为SO片段定义setInterval,但请在此处查看:
var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
45, // Field of view
w / h, // Aspect ratio
0.1, // Near
10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var sphereGeom = new THREE.SphereGeometry(5, 16, 16);
for (var i = 0; i < sphereGeom.vertices.length; i++) {
var v = sphereGeom.vertices[i];
if (v.y < 0) v.y = 0;
}
sphereGeom.verticesNeedUpdate = true;
sphereGeom.computeFaceNormals();
sphereGeom.computeVertexNormals();
var material = new THREE.MeshLambertMaterial({
color: 0x808080
});
var mesh = new THREE.Mesh(sphereGeom, material);
scene.add(mesh);
renderer.setClearColor(0xdddddd, 1);
// create a canvas element
var canvas1 = document.createElement('canvas');
var context1 = canvas1.getContext('2d');
context1.font = "Bold 20px Arial";
context1.fillStyle = "rgba(0,0,0,0.95)";
context1.fillText('Hello, world!', 0, 20);
// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;
// use the texture as material
var spriteMaterial = new THREE.SpriteMaterial({
map: texture1,
useScreenCoordinates: false
});
// create the sprite and add it tho the scene
var sprite1 = new THREE.Sprite(spriteMaterial);
sprite1.scale.set(40, 20, 1.0);
sprite1.position.set(-5, 0, -5);
scene.add(sprite1);
var i = 0;
(function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
context1.clearRect(0, 0, canvas1.width, canvas1.height);
var message = 'test' + i++;
context1.fillText(message, 4, 20);
texture1.needsUpdate = true;
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>