在得到建议后,重用相同的元素(实体)来重新设置父级并不是一个好主意(请参阅更改组件的父级并保持位置 https://stackoverflow.com/questions/52318200/change-parent-of-component-and-keep-position),我探索了将要重新设置父级的实体复制到新父级下的新元素中的想法,然后删除“旧”元素(而不是直接重新设置实体的父级)。诚然,这不是世界上最干净的黑客,但我希望它对我的用例有所帮助。所以,我写了一个组件:
AFRAME.registerComponent('reparent', {
schema: {
parent: {type: 'selector', default: null},
},
update: function () {
const el = this.el;
const parent = this.data.parent;
if (el.parentElement == parent) {
// We're already a child of the intended parent, do nothing
return;
};
// Reparent, once object3D is ready
reparent = function() {
// Attach the object3D to the new parent, to get position, rotation, scale
parent.object3D.attach(el.object3D);
let position = el.object3D.position;
let rotation = el.object3D.rotation;
let scale = el.object3D.scale;
// Create new element, copy the current one on it
let newEl = document.createElement(el.tagName);
if (el.hasAttributes()) {
let attrs = el.attributes;
for(var i = attrs.length - 1; i >= 0; i--) {
let attrName = attrs[i].name;
let attrVal = el.getAttribute(attrName);
newEl.setAttribute(attrName, attrVal);
};
};
// Listener for location, rotation,... when the new el is laded
relocate = function() {
newEl.object3D.location = location;
newEl.object3D.rotation = rotation;
newEl.object3D.scale = scale;
};
newEl.addEventListener('loaded', relocate, {'once': true});
// Attach the new element, and remove this one
parent.appendChild(newEl);
el.parentElement.removeChild(el);
};
if (el.getObject3D('mesh')) {
reparent();
} else {
el.sceneEl.addEventListener('object3dset', reparent, {'once': true});
};
}
});
您可以检查它是否适用于以下 HTML 文件:
<!DOCTYPE html>
<html>
<head>
<script src="https://aframe.io/releases/1.1.0/aframe.min.js"></script>
<script src="reparent.js"></script>
</head>
<body>
<a-scene id="scene" background="color: grey">
<a-entity id="red"
position="1 2 -4" rotation="30 0 0" material="color: red"
geometry="primitive: cylinder"></a-entity>
<a-entity id="green" reparent="parent: #red"
position="-1 0 -4" rotation="0 45 0" material="color: green"
geometry="primitive: box"></a-entity>
<a-entity id="wf"
position="-1 0 -4" rotation="0 45 0" material="wireframe: true"
geometry="primitive: box"></a-entity>
</a-scene>
</body>
</html>
线框实体只是为了显示绿色框如何精确地保持在相同位置,尽管它在红色实体下“重新设置了父级”(探索 DOM 来检查)。如上所述,绿色框实际上是一个新框,是从原始框克隆的,然后被组件删除。
该组件应该在其工作时工作parent
属性发生更改,允许在需要时动态重新调整父级。