Skip to content

事件传递

three.js 中,各类交互控制器(如 OrbitControlsTrackballControls 等)依赖于标准的 PointerEvent 事件进行响应。而在小程序环境中,系统仅提供类似 Web TouchEvent 的事件对象,二者存在格式和行为上的差异,无法直接兼容使用

为解决这一问题,我们在 @minisheep/three-platform-adapter 中提供的 useCanvas 方法会返回一个 eventHandler 工具对象。你只需将画布组件上的原生 touch 系列事件(如 touchstarttouchmovetouchend传递给 eventHandler,它将自动完成事件转换,生成符合 three.js 控制器需求的 PointerEvent

正常使用

基于 创建一个场景 的例子,进行如下改动:

vue

<script setup>
  import * as THREE from 'three';
  import { ref } from 'vue';  
  import { adapter } from '@minisheep/three-platform-adapter';
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; 

  const canvasEventHandler = ref(() => {
  }); 

  adapter
      .useCanvas('#canvas')
      .then(({
               canvas,
               requestAnimationFrame,
               eventHandler, 
             }) => {
        canvasEventHandler.value = eventHandler; 

        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);

        const renderer = new THREE.WebGLRenderer({ canvas });
        renderer.setSize(canvas.clientWidth, canvas.clientHeight);
        
        const controls = new OrbitControls( camera, renderer.domElement );

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

        camera.position.z = 5;

        function animate() {
          requestAnimationFrame(animate);
          controls.update(); 
          
          cube.rotation.x += 0.01;
          cube.rotation.y += 0.01;

          renderer.render(scene, camera);
        }

        animate();
      });
</script>
vue
<template>
  <canvas 
      type="webgl2"
      id="canvas"
      @touchstart="canvasEventHandler"
      @touchmove="canvasEventHandler"
      @touchcancel="canvasEventHandler"
      @touchend="canvasEventHandler"
      @tap="canvasEventHandler"
  />
</template>
vue

<style>
  canvas {
    width: 100vw;
    height: 100vh;
  }
</style>

其他应用

调用 eventHandler 不仅仅会在画布上触发对应的 PointerEvent 事件, 还会在 adapterTHREEGlobals 对象下的 document / window 属性上触发,以支持一些不仅仅在画布元素监听事件的控制器。

当然,也可以通过传递第二个参数禁用这个事件冒泡逻辑, 例如 (ev)=>eventHandler(ev, false)