mcpField
P
pointer-events

pointer-events

github.com/drawcall-ai开发122 次安装
代码仓库

关于 pointer-events

pointer-events 是将 DOM 或物体表面输入转发到 Three.js 场景的库,供场景对象响应指针事件。它支持按对象和指针类型筛选命中,并允许自定义指针及交点计算方式。

主要功能

  1. 01转发 HTML 事件到场景
  2. 02转发表面事件到门户场景
  3. 03按对象属性筛选事件目标
  4. 04按指针类型过滤事件
  5. 05自定义指针与相交计算

适用场景

  1. 01让 Three.js 对象响应页面输入
  2. 02创建可交互的门户场景
  3. 03限制透明物体捕获指针事件
  4. 04通过射线或球体实现自定义交互

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/drawcall-ai/skills --skill pointer-events

安装后在 Claude Code 中输入/pointer-events确认已加载。

详细介绍

通过 @pmndrs/pointer-events 使用指针事件

@pmndrs/pointer-events 会将真实输入转发到 Three.js 场景中,使 3D 对象触发指针监听器、筛选会命中的对象,并允许你定义指针本身的形状。

概述

该库基于三大支柱:

  1. 转发输入。 forwardHtmlEvents 将 DOM 事件引入场景;forwardObjectEvents 将来自某个表面的事件引入单独的门户场景。两者都会返回一个每帧运行的 update()。
  2. 筛选命中对象。 pointerEvents 属性(源自 CSS:none/listener/auto)和 pointerEventsType 属性(all/allow/deny/函数)会按对象决定哪些事件会命中。
  3. 定义指针。 你可以构建自己的 Pointer,并选择如何计算其交点。

这些功能可以串联使用:转发会生成各自带有 pointerType 的事件;筛选会按对象决定这些事件中哪些会命中;自定义指针则决定如何以及在哪里计算交点。下文将按此顺序介绍:将事件转发到场景、筛选命中对象,以及自定义指针。

将事件转发到场景

转发功能会在场景中安装指针事件源,并提供一个 update(),供你在每帧推进事件。

forwardHtmlEvents 会将 HTML 文档的事件转发到 3D 场景中。调用时传入 DOM 目标、相机获取函数和场景 — forwardHtmlEvents(document.body, () => camera, scene) — 它会返回 { update }。在渲染循环中,每帧调用一次 update(),并且要在 renderer.render(scene, camera) 之前调用。随后,对象便可通过 addEventListener('pointerover' | 'pointerout', (e: PointerEvent) => ...) 接收事件;PointerEvent 类型与 forwardHtmlEvents 一同从 @pmndrs/pointer-events 导入。每个事件都包含 e.point(一个向量,可调用 e.point.toArray()),并且你可以为同一种事件类型附加多个监听器。

import * as THREE from 'three'
import { forwardHtmlEvents, PointerEvent } from '@pmndrs/pointer-events'

const width = window.innerWidth,
  height = window.innerHeight

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10)
camera.position.z = 1
const { update } = forwardHtmlEvents(document.body, () => camera, scene)

const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2)
const material = new THREE.MeshBasicMaterial({ color: new THREE.Color('red') })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

mesh.addEventListener('pointerover', (e: PointerEvent) => material.color.set('blue'))
mesh.addEventListener('pointerover', (e: PointerEvent) => console.log(e.point.toArray()))
mesh.addEventListener('pointerout', (e: PointerEvent) => material.color.set('red'))

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(width, height)
renderer.setAnimationLoop(() => {
  update()
  renderer.render(scene, camera)
})

forwardObjectEvents 会将来自某个表面(例如一个平面)的事件转发到单独的场景中,并将该场景渲染到该表面上,从而生成一个可交互的门户。它的用法与 forwardHtmlEvents 相同:传入表面网格、相机获取函数和门户场景。它会返回自己的 update,此处命名为 updatePortal;每帧都必须与主 update() 一同调用。

const { update: updatePortal } = forwardObjectEvents(planeMesh, () => portalCamera, portalScene)
// in the render loop, alongside the main update():
updatePortal()

筛选命中对象

两个逐对象属性控制哪些事件会到达对象:pointerEvents 决定对象是否可作为目标,pointerEventsType 则按指针类型筛选。

pointerEvents 基于 CSS 的 pointer-events 属性,取值为 none、listener 或 auto。

object.pointerEvents = 'none'
  • none — 对象永远不会被直接指定为目标。
  • auto — 对象始终会成为事件的目标,与 CSS 属性行为一致。
  • listener — 额外提供的取值,也是默认值:只有对象附加了监听器时,它才会成为目标。

对于 3D 场景,listener 默认值比 auto(Web 默认值)更合理,因为场景中通常包含半透明内容,例如粒子;这类内容默认不应拦截指针事件。

每个对象还可以通过 pointerEventsType 按指针类型筛选,默认值为 all(接受来自所有指针类型的事件)。若要筛选,可设置 { allow: "screen-mouse" } 或 { deny: "screen-touch" }(screen-mouse 表示通过 2D 屏幕操作的普通鼠标)。allow 和 deny 都接受字符串或字符串数组;pointerEventsType 也接受函数,以实现自定义逻辑。

默认使用的指针类型包括 screen-touch、screen-pen、ray、grab 和 touch。从 DOM 转发的事件所带的 pointerType 以 screen- 为前缀;通过门户经 forwardObjectEvents 转发的事件所带的 pointerType 则以 forward- 为前缀。

自定义指针

你可以创建自己的 Pointer——例如,将指针放在相机内部或其他位置,让第一人称控制器能够与环境交互。自定义 Pointer 可以使用普通的 Ray 进行相交检测,也可以使用一组 Lines,或使用 Sphere 处理抓取和触摸事件。

注意事项

克隆对象时,不会复制 Mesh/Object3D 的 pointerEvents 属性;请在克隆对象上重新应用该属性。

评论

支持 Markdown