Javascript three.js-如何将非可视属性连接到对象?

Javascript three.js-如何将非可视属性连接到对象?,javascript,three.js,Javascript,Three.js,我有一个相当广泛的问题,但不知道如何解决。所以请原谅我 我正在尝试创建几个(比如200个或更多)对象,我们只需要在字段的一侧创建一个容器,在这里我绘制对象。现在我想要的是,每个对象都有一些非可视属性,当我单击该对象时,属性应该显示在该容器中 现在我可以开始了 我的意思是,我知道我可以询问所选对象的名称,然后从某个字典中进行键值查询。问题是,是否有一种更简单的方法来解决这个问题。是的,没关系。您可以将自己的自定义密钥直接放在Three.js对象上,只要您不意外地覆盖重要的内置Three.js密钥,

我有一个相当广泛的问题,但不知道如何解决。所以请原谅我

我正在尝试创建几个(比如200个或更多)对象,我们只需要在字段的一侧创建一个容器,在这里我绘制对象。现在我想要的是,每个对象都有一些非可视属性,当我单击该对象时,属性应该显示在该容器中

现在我可以开始了


我的意思是,我知道我可以询问所选对象的名称,然后从某个字典中进行键值查询。问题是,是否有一种更简单的方法来解决这个问题。

是的,没关系。您可以将自己的自定义密钥直接放在Three.js对象上,只要您不意外地覆盖重要的内置Three.js密钥,就不会麻烦它。出于这个原因,我建议您将所有自定义键都放在对象的“名称空间”中,这样它们就很好、整洁并且包含在内

例如,如果您有一个Three.js对象
foo
,您可以将所有键放在
foo.myCustomNamespace
下,这样您的自定义数据(如
foo.myCustomNamespace.name
foo.myCustomNamespace.description
)都在一起,不会干扰Three.js属性

编辑:Three.js为用户数据提供了一个内置名称空间,方便地称为
userData
。在
THREE.Object3D.userData
上访问它


对于我使用了一个名为的库的click事件,请查看GitHub页面以了解更多信息,该事件的代码是不言自明的

首先,需要在场景中初始化DomeEvents,如下所示:

var domEvents = new THREEx.DomEvents(camera, renderer.domElement);
然后我创建了一个自定义网格对象:

// random id
function genRandomId()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

// random int for position
var min = -50;
var max = 50;

function genRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
}

// custom mesh --------------------------------------------
function MyMesh(geometry, material, destinationContainer) {
    THREE.Mesh.call(this, geometry, material);

    this.userData = {
        foo1: genRandomId(),
        foo2: genRandomId(),
        foo3: genRandomId(),
    };

    this.position.x = genRandomInt(min, max);
    this.position.y = genRandomInt(min, max);
    this.position.z = genRandomInt(min, max);

    var that = this;

    // click event listener
    domEvents.addEventListener(this, 'click', function(event) {
        console.log('clicked object on position:');
        console.log(that.position);

        destinationContainer.userData = that.userData;

        console.log('Now the conainer has:');
        console.log(destinationContainer.userData);

        destinationContainer.userData = that.userData;
    }, false);
}

MyMesh.prototype = Object.create(THREE.Mesh.prototype);
MyMesh.prototype.constructor = MyMesh;
最后渲染场景:

const color = 0x156289;
const emissive = 0x072534;

var planeGeometry = new THREE.PlaneGeometry(5, 5);
var planeMaterial = new THREE.MeshPhongMaterial({
    color: color,
    emissive: emissive,
    side: THREE.DoubleSide,
    shading: THREE.FlatShading
});

var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);

scene.add(planeMesh);

var objGeometry = new THREE.BoxGeometry(1, 1, 1);
var objMaterial = new THREE.MeshPhongMaterial({
    color: color,
    emissive: emissive,
    shading: THREE.FlatShading
});

var i = 0;

while (i < 200) {
    scene.add(new MyMesh(objGeometry, objMaterial, planeMesh));
    i++;
}
var render = function() {
    requestAnimationFrame(render);

    planeMesh.rotation.x += 0.010;
    planeMesh.rotation.y += 0.010;

    renderer.render(scene, camera);
};

render();
这是一个包含完整源代码的演示:


打开浏览器控制台并单击一个立方体,您将看到
planeMesh
正在将其
userData
属性与单击的立方体网格的属性进行切换。

可能应该添加:three.js在每个Object3D实例中已经有一个名为
userData
的对象,正是出于此目的:(该对象中的数据将自动克隆和序列化)