簡體   English   中英

在 A-Frame 中動態創建的添加事件監聽器

[英]Add event listener on dynamically created in A-Frame

我創建了一個 class,它可以幫助我使用 A-Frame 顯示 3D model。 在這個 class 中,有一些在運行時創建的球體廣告插入到場景中。 我正在嘗試添加一個事件偵聽器(單擊這些球體時我必須顯示一條消息)

這是代碼:

export class AFrameObjViewNavMarkProvider implements Provider {
  // Class Variables...

  // Constructor...

  // ----- Method ----- \\
  public setPointerService(pointersService: PointersService) {
    // method code...
  }

  public setPointerTrigger(value: boolean) {
    // method code...
  }

  // ----- Handlers ----- \\

  // click Handler
  clickHandler(event, model: Model){
    // code for saving into backend...

    // save pointer into the back-end
    this.pointersService.loadPointer(newPointer).subscribe((pointer) => {
      this.showPointer(pointer);
    });
  }

  showPointer(pointer: Pointer){
    // create a string containing the position
    let pointString = pointer.position[0].toFixed(3) + " "
      + pointer.position[1].toFixed(3) + " "
      + pointer.position[2].toFixed(3);

    // compute the box that contains the model
    let modelRef = <any>document.getElementById("model");
    const box = new THREE.Box3().setFromObject(modelRef.object3D);
    const boxSizes = box.getSize(new THREE.Vector3());

    // compute the min size of the box (x, y, z)
    // it will be used to set pointer radius
    let minBoxSize = Math.min(boxSizes.x, boxSizes.y, boxSizes.z);
    let radius = minBoxSize / 30;

    let scene = document.getElementById("scene");
    let marker = document.createElement("a-sphere");
    scene.appendChild(marker);

    marker.setAttribute("class", "pointer");
    marker.setAttribute("radius", `${radius}`);
    marker.setAttribute("color", "#CC0000");
    marker.setAttribute("position", pointString);
  }

  // ----- Visual Methods ----- \\
  renderModel(model: Model) {
    // position-setter is used to set the model position according to its size
    AFrameUtils.registerPositionSetter();

    // reference to the provider itself
    let caller: any = this;

    function clickHandler(event) {
      caller.clickHandler(event, model);
    }

    // sets the behaviour in response to a click event
    AFRAME.registerComponent('click-handler', {
      // init also calls update
      init: function () {
        let mouseDownTime: number = null;
        let mouseDownPoint: any = null;

        this.el.addEventListener('mousedown', event => {
          mouseDownTime = new Date().getTime();
          mouseDownPoint = event.detail.intersection.point;
        });

        this.el.addEventListener('mouseup', event => {
          if(!event.detail.intersection) return;

          let mouseUpTime = new Date().getTime();
          let mouseUpPoint = event.detail.intersection.point;

          // compute the differences (time and position) between press and release
          let timeDiff = mouseUpTime - mouseDownTime;

          // if press and release occur within 185 ms
          //  we consider the event as a click
          if (timeDiff <= 185 && JSON.stringify(mouseDownPoint) === JSON.stringify(mouseUpPoint)) {
            clickHandler(event);
          }
        });
      }
    });

    let renderingArea = document.getElementById('rendering-area');
    renderingArea.innerHTML = `
      <a-scene embedded id="scene" cursor="rayOrigin: mouse" raycaster="objects: .clickable">
        <!-- Assets definition -->
        <a-assets>
            <a-asset-item id="object-ref" src="${model.sources[0]}"></a-asset-item>
            <a-asset-item id="material-ref" src="${model.sources[1]}"></a-asset-item>
        </a-assets>

        <!-- Using the asset management system. -->
        <a-obj-model id="model" class="clickable" src="#object-ref" mtl="#material-ref" position-setter click-handler>
        </a-obj-model>

        <!-- Camera -->
        <a-camera id="camera" wasd-controls="fly:true"></a-camera>

        <!-- Environment elements-->
        <a-sky id="sky" color="#000000"></a-sky>
      </a-scene>
    `;

    setTimeout(() => {
      this.pointersService.getPointersByModelId(model.id).subscribe(pointers => {
        for(let pointer of pointers){
          this.showPointer(pointer);
        }

        let markers = Array.from(document.getElementsByClassName('pointer'));
        for(let marker of markers){
          marker.addEventListener('click', () => {
            console.log('click on pointer');
          })
        }
      });
    }, 125);
  }
}

和截圖:

在此處輸入圖像描述

第一次嘗試:我嘗試注冊另一個組件,如下所示:

AFRAME.registerComponent('pointer-handler', {
      init: function(){
        this.el.addEventListener('click', () => {
          console.log('click on pointer');
        });
      }
    });

並在showPointer方法中使用setAttribute("pointer-handler", "")

第二次嘗試:我嘗試使用marker.addEventListener直接將事件偵聽器添加到showPointer方法中。

第三次嘗試:在代碼上可以找到第三次嘗試,進入setTimeout的回調。

每次嘗試都行不通; 如果我嘗試單擊一個球體,那么什么也不會發生。 但是,如果我打開 A-Frame 檢查器,導航到其中一個球體並單擊它,則會記錄該消息。 我懷疑添加了處理程序,但是某些原因導致未檢測到單擊。

每一個建議都將不勝感激。

謝謝!

編輯:你可以在這里找到回購

使用setAttribute("pointer-handler", "")方法是絕對有效的,並且是做您想要實現的目標的正確方法。

我認為這可能是導致問題的click事件。 我建議你用mouseupmousedown事件替換它。

還要確保您確實可以觸發事件 - 您需要將 cursor 連接到您的相機

工作示例

全屏運行(運行片段后的右上角以查看整個場景 - 關閉也在右上角)。

您可以通過按左上角的按鈕添加新元素。 看看 click 有時是如何被觸發的,有時根本不是。

 let boxCounter = 0; function createNewElement() { let box = document.createElement("a-box"); boxCounter++; box.setAttribute("position", "" + boxCounter + " 0 -2"); box.setAttribute("scale", "0.5"); box.setAttribute("color", "red"); box.setAttribute("click-handler", ""); document.getElementById("scene").appendChild(box); }
 <:DOCTYPE html> <html> <head> <script src="https.//aframe.io/releases/1.0.0/aframe.min.js"></script> </head> <body> <script> AFRAME,registerComponent('click-handler': { init. function() { this.el,addEventListener('mousedown'. (event) => { console;log("I was mousedowned."). this,el,setAttribute('material'; 'color'; 'green'). }). this,el.addEventListener('mouseup'; (event) => { console.log("I was mouseuped."), this,el;setAttribute('material'; 'color'. 'red'). }), this.el;addEventListener('click'. (event) => { console.log("I was clicked,"). this.el.setAttribute('scale'; '0;5 0;5 0:5'); }): } }); </script> <a-scene id="scene"> <a-entity camera look-controls> <a-entity cursor="fuse: true; fuseTimeout: 500." position="0 0 -1" geometry="primitive; ring: radiusInner. 0:02; radiusOuter: 0.03" material="color. black. shader: flat"> </a-entity> </a-entity> <a-sphere color="red" position="0 0 -2" scale="0;5 0:5 0;5" click-handler></a-sphere> </a-scene> <button onclick="createNewElement()" style="width: 100px; height: 100px; position: absolute; top: 0; left: 0;" value="toggle"></button> </body> </body> </html>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM