从A帧中的其他组件访问动态创建的子项目
我目前有2个组件。其中一个创建了一系列十二面体,另一个则隐藏了它们。它们都是在运行时生成的。从A帧中的其他组件访问动态创建的子项目
问题在于看不见的问题。在可见组件的init
方法
el.querySelector('*')
:我无法使用得到的动态生成的孩子。
我甚至试过:
- 监听“装”事件,然后注册该组件。
- 使用承诺并收听加载的事件。
- 在组件注册后使用3秒的window.setTimeout()函数。
这是我完整的代码,到目前为止:
export class InvisibleComponent {
constructor() {
/**
* Sets the current element and all of its children as invisible
* by using its materials property.
*
*/
const _this = this;
AFRAME.registerComponent('invisible', {
init: function() {
_this.setTransparent(this.el);
console.log(this.el);
let children = this.el.querySelector('*');
if (!children) return;
Array.from(children).forEach(child => {
_this.setTransparent(this.el);
})
},
remove: function() {
if (!this.el) return;
_this.setOpaque(this.el);
let children = this.el.querySelector('*');
if (!children) return;
Array.from(children).forEach(child => {
_this.setOpaque(this.el);
})
}
})
}
setTransparent(el: AFrame.Entity) {
this.getMaterial(el).then((material :any) => {
this.setAttributes(el,material.opacity);
})
.catch(resolve => {
console.log("Material couldn't be gathered. Using 100% of opacity instead", resolve);
this.setAttributes(el, 1);
});
}
setAttributes(el : AFrame.Entity, opacity){
el.setAttribute('data-previous-opacity',opacity);
el.setAttribute('material', 'opacity:0; transparent: true; visible:false;');
}
/**
* This is a solution if the element which is trying to load
* hasn't been loaded yet. All elements must have a material
* in order to be inserted in a scene.
* @param el
*/
getMaterial(el: AFrame.Entity): Promise<number> {
return new Promise<number>((resolve, reject) => {
let material = el.getAttribute('material');
if (material) resolve(material);
el.sceneEl.addEventListener('loaded', function() {
let material = el.getAttribute('material');
!material ? reject(undefined) : resolve(material);
})
});
}
// If you had previous property, this will not remove them.
setOpaque(el: AFrame.Entity) {
let dataPreviousOpacity = el.getAttribute('data-previous-opacity');
if (!dataPreviousOpacity) dataPreviousOpacity = 1;
el.setAttribute('material', 'transparent', dataPreviousOpacity === 1 ? false : true);
el.setAttribute('material', 'opacity', dataPreviousOpacity);
el.setAttribute('material', 'visible', true);
}
}
出于某种原因,我不能让它与寻找实体儿童工作。
这里是我的方法:
-
揭露创建的元素:
init:function(){ //expose the object: this.object = document.createElement('a-dode(..)') }
- 访问使用
el.components.componentName.object
它可以是对象的公共数组对象,但是你喜欢。 访问undefined
对象似乎没有问题。如果你有,你可以做一个间隔检查,如果对象是未定义的,或者循环访问一个数组,在每个'未定义'元素上执行'set invisible'。
工作小提琴here:component'create'制作一个方框,'change_color'设置颜色+位置。还有一个getObject()函数,稍后我会讨论它,因为我的方法存在严重的安全问题,并且可能需要适当的getter来获取对象。
我不知道什么是所提到的“安全问题”的正确方法,但我设法让一个“吸”,用
bind();
传递对象,吸气:
init: function(){
object = (...);
this.getObject = this.getObject.bind(this,[object]);
},
getObject(){
return arguments[0];
}
如果这太可怕了,而且本来应该被处理,请让我知道。
也许我应该使用get getterName(){//getterBody},但它会引发一些错误。
更新提琴here。
有趣。感谢您的高举。这可以工作。让我想出一个方法来自动化这个过程,我会回来;) –
@JoseA肯定,祝你好运:) –
虽然我已经偏离了自己在做什么,但el.components存在问题。 componentName.object,因为componentName在我访问它的时刻似乎没有被定义。 –
组件不应该在运行时注册,而应该在页面加载。当你检测到所有的孩子被加载并且让其他组件监听那个事件时,附属于孩子的事件应该会有帮助,发出一个事件。或者setTimeouts也应该工作。将有助于将不可分割的组件设置为十二面体生成器作为依赖关系 – ngokevin
@ngokevin:有道理。我也会检查这个方法。谢谢。一旦我完成解决我有另一个问题后会回发(完全不同的问题) –