从A-Frame中的另一个组件访问动态创建的子项

时间:2017-07-31 13:07:08

标签: initialization components aframe

我目前有2个组件。其中之一,创造了一系列十二面体,另一个则使它们看不见。它们都是在运行时生成的。

问题在于看不见的问题。我无法通过使用以下方式获取动态生成的子项:

el.querySelector('*')

在隐形组件的init方法中。

我甚至尝试过:

  • 聆听"已加载"事件然后注册组件。
  • 使用promises并收听已加载的事件。
  • 在注册组件后使用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);

  }
}

1 个答案:

答案 0 :(得分:2)

出于某种原因,我不能让它与寻找实体儿童一起工作。
这是我的方法:

  1. 公开创建的元素:

    init:function(){
      //expose the object:
      this.object = document.createElement('a-dode(..)')
    }
    
  2. 使用el.components.componentName.object
  3. 访问对象

    它可以是公共的对象数组,但是你喜欢。 它似乎没有访问undefined对象的问题。但是,如果你有,你可以间隔检查对象是否未定义,或循环遍历数组,执行“设置不可见”&#39;在每个&#39;非未定义的&#39;元件。

    工作小提琴here:组件&#39;创建&#39;制作一个盒子,&#39; change_color&#39;设置颜色+位置。还有一个getObject()函数,稍后我会搞乱它,因为我的方法存在严重的安全问题,并且可能需要对该对象进行适当的getter。

    <小时/> 我不确定提到的安全问题的正确方法是什么,但是我设法制作了一个“getter”,并将对象传递给了getter使用bind();

    init: function(){
      object = (...);
      this.getObject = this.getObject.bind(this,[object]);
    },
    getObject(){
      return arguments[0];
    }
    

    如果这很糟糕,应该以其他方式处理,请告诉我。
    也许我应该使用get getterName(){//getterBody},但它会给我一些错误。
    更新了小提琴here