2017-10-10 17 views
1

THREE.JSシーンにposition:absolute;の要素としてラベルを配置しようとしています。問題は、マウスがラベルの1つ(以下の例では赤いボックス)の上にあるとき、OrbitControlsをトリガするイベントはラベルによって「停止」され、レンダラに伝播しないことです。THREE.JS DOM要素がシーン上に配置されているとOrbitControlsが機能しない

問題を確認するために最小限のコードを再現しました。ここで

enter image description here

<html lang="en"> 

<head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> 
    <style> 
     body { 
      margin: 0px; 
      overflow: hidden; 
     } 

     #overlay { 
      position: absolute; 
      top: 40%; 
      left: 40%; 
      width: 20%; 
      height: 20%; 
      background-color: #f00; 
      padding: 3%; 
      text-align: center; 
      color: #fff; 
      box-sizing: border-box; 
     } 
    </style> 
</head> 

<body> 
    <div id="container"></div> 

    <!-- This div below stop the OrbitControls events, why? --> 
    <div id="overlay">I am a div with position:absolute</div> 

    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script> 
    <!-- https://raw.githubusercontent.com/mrdoob/three.js/r87/examples/js/controls/OrbitControls.js --> 
    <script src="orbit-controls.js"></script> 
    <script> 
     var container; 
     var camera, scene, renderer; 
     var uniforms, material, mesh; 
     var controls; 
     init(); 
     animate(); 

     function init() { 
      container = document.getElementById('container'); 
      var aspect = window.innerWidth/window.innerHeight; 
      camera = new THREE.PerspectiveCamera(45, aspect, 0.1, 1500); 
      camera.position.set(1, 1, 1); 
      scene = new THREE.Scene(); 
      renderer = new THREE.WebGLRenderer(); 
      container.appendChild(renderer.domElement); 
      renderer.setSize(window.innerWidth, window.innerHeight); 
      controls = new THREE.OrbitControls(this.camera, this.renderer.domElement); 

      var geometry = new THREE.BoxGeometry(1, 1, 1); 
      var material = new THREE.MeshBasicMaterial({ 
       color: 0x00ff00 
      }); 
      var cube = new THREE.Mesh(geometry, material); 

      scene.add(cube); 
     } 

     function animate() { 
      requestAnimationFrame(animate); 
      render(); 
     } 

     function render() { 
      renderer.render(scene, camera); 
     } 
    </script> 
</body> 

</html> 

カメラは、マウス操作に従うことができるようにラベルがイベントの伝播を停止しません似たようなプロジェクトへのリンクです。しかし、私はこのexemple仕事と私のものではないことを発見していない。 http://armsglobe.chromeexperiments.com

OrbitControlsはまだ<div>ラベルの背後で動作するようにするにはどうすればよいですか?

あなたがオーバーレイから任意のマウス・イベントを必要としない場合は、それだけで無効化イベント処理のCSSを経由するのが最も簡単です::

<div class="overlay" style="pointer-events: none">...</div> 

のことができます。また、コメントからの回答を要約する

+1

はこれを試してみてください。 OrbitControls(this.camera); '。デフォルトで 'domElement'は' document'になります – prisoner849

+0

Thanks @ prisoner849!それは問題を解決します。あなたは答えを書いていますか、それともしなければなりませんか? – Ben

+2

overlay-elementのcssに 'pointer-events:none;'を追加して、問題を修正することもできます。 –

答えて

1

イベント処理のための共通の親要素を使用します。

<div class="parent" style="position:relative"> 
    <canvas ... /> <!-- this is the canvas from renderer.domElement --> 
    <div class="overlay"></div> 
</div> 

とコントロールのために

const controls = new THREE.OrbitControls(camera, document.querySelector('.parent')); 

このように、親に到達するすべてのマウスイベント(オーバーレイからのイベントを含む)は、コントロールによって処理されます(特殊なケースは、ルートレベルのすべてのイベントを処理します。 OrbitControlsコンストラクターの場合はdocument.documentElementと指定してください)。

インスタンスのクリックなどのオーバーレイから特定のイベントを処理する場合は、stopPropagation()を使用して軌道制御に転送取得することを防ぐことができます: `コントロール=新しいTHREE:

overlayEl.addEventListener('click', event => { 
    event.stopPropagation(); 

    // handle event 
}); 
関連する問題