事件传递
在 three.js
中,各类交互控制器(如 OrbitControls
、TrackballControls
等)依赖于标准的 PointerEvent
事件进行响应。而在小程序环境中,系统仅提供类似 Web TouchEvent
的事件对象,二者存在格式和行为上的差异,无法直接兼容使用。
为解决这一问题,我们在 @minisheep/three-platform-adapter
中提供的 useCanvas
方法会返回一个 eventHandler
工具对象。你只需将画布组件上的原生 touch
系列事件(如 touchstart
、touchmove
、touchend
)传递给 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
事件, 还会在 adapter
和 THREEGlobals 对象下的 document
/ window
属性上触发,以支持一些不仅仅在画布元素监听事件的控制器。
当然,也可以通过传递第二个参数禁用这个事件冒泡逻辑, 例如 (ev)=>eventHandler(ev, false)