事件
基于物体的识别事件:
V4.X以后的升级,已经修复了之前的bug,并且和primitive统一起来了
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2023-12-15 09:28:45
* @LastEditors: 地虎降天龙
* @LastEditTime: 2025-10-16 08:22:05
-->
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
function onClick(ev) {
if (ev) {
ev.object.material.color.set('#008080')
}
}
function onPointerEnter(ev) {
if (ev) {
ev.object.material.color.set('#CCFF03')
}
}
function onPointerLeave(ev) {
if (ev) {
ev.eventObject.material.color.set('#efefef')
}
}
function onPointerMove(ev) {
if (ev) {
console.log(ev)
}
}
</script>
<template>
<TresCanvas clearColor="#202020">
<TresPerspectiveCamera :position="[11, 11, 11]" :look-at="[0, 0, 0]" />
<OrbitControls />
<template v-for=" x in [-2.5, 0, 2.5] ">
<template v-for=" y in [-2.5, 0, 2.5] ">
<TresMesh v-for=" z in [-2.5, 0, 2.5] " :key="`${[x, y, z]}`" :position="[x, y, z]" @click="onClick"
@pointerenter="onPointerEnter" @pointerleave="onPointerLeave" @pointermove="onPointerMove">
<TresBoxGeometry :args="[1, 1, 1]" />
<TresMeshToonMaterial color="#efefef" />
</TresMesh>
</template>
</template>
<TresDirectionalLight :intensity="1" />
<TresAmbientLight :intensity="1" />
</TresCanvas>
</template>
- Intersection : 返回基于
ThreeJS的光线投射Raycaster的 Intersection 类,具体参数详见链接。您可以通过 intersection.object 访问触发事件的 Object3D - PointerEvent :返回 web 通用
PointerEvent类,包含鼠标的坐标等,体参数详见链接
直接上代码:
<TresMesh
@click="(event) => console.log('click')"
@contextmenu="(event) => console.log('context-menu (right click)')"
@doubleclick="(event) => console.log('double-click')"
@pointermove="(event) => console.log('pointer-move')"
@pointerenter="(event) => console.log('pointer-enter')"
@pointerleave="(event) => console.log('pointer-leave')"
@pointerdown="(event) => console.log('pointer-down')"
@pointerup="(event) => console.log('pointer-up')"
@pointercancel="(event) => console.log('Fired when pointer interaction is cancelled')"
/>
| 事件 | 描述 | 返回参数说明 |
|---|---|---|
| click | 基于同一物体的点击 | Intersection, PointerEvent |
| pointermove | 鼠标在物体上移动 | Intersection, PointerEvent |
| pointerenter | 鼠标划入物体 | Intersection, PointerEvent |
| pointerleave | 鼠标划出物体 | Intersection,PointerEvent |
- 更多
contextmenu、doubleclick 、pointerdown、pointerup、pointercancel等详见:TresJS事件
TIP
<script setup lang="ts">
function onChildClick(event) {
event.stopPropagation() // Prevents parent from receiving the event
console.log('Child clicked!')
}
function onParentClick() {
console.log('Parent clicked!') // Won't fire if child stops propagation
}
</script>
<template>
<TresGroup @click="onParentClick">
<TresMesh @click="onChildClick">
<TresBoxGeometry />
<TresMeshNormalMaterial />
</TresMesh>
</TresGroup>
</template>
因为
TresJS封装的事件方法使用的是ThreeJS光线投射(raycaster),所以在物体mesh顶点相对多的时候,会出现卡顿的现象。需要通过开启three-mesh-bvh的方法,增加效率。开启方法详情请见:three-mesh-bvh代码应用详见 TvT.js 开源例子:heatmap2加载模型后,使用
primitive挂载后,模型绑定事件同TresMesh, 这里不再赘述。
针对整体循环刷新的 Loop 函数
我们在写 three.js 的时候,经常会写如下函数:
// 整体场景刷新
window.requestAnimationFrame(() => {
render.render(scene, camera)
})
// 或者每个基于Object3D的render循环函数
const cube = new THREE.Mesh(geometry, material)
cube.onBeforeRender = function (
renderer,
scene,
camera,
geometry,
material,
group
) {
// 在渲染之前执行的自定义操作
this.rotation.x += 0.01
}
tres有 useLoop 的全替代解决方案:
// 此函数 可在任意vue文件下 调用
import { useLoop } from '@tresjs/core'
const { onBeforeRender, onRender } = useLoop()
onRender(({ delta, elapsed }) => {
// I will run at every frame ~60FPS (depending of your monitor)
})
回调onLoop根据时钟接收具有以下属性的对象:
delta:当前帧与上一帧之间的时间差。这是自上一帧以来的时间(以秒为单位)。elapsed:自渲染循环开始以来经过的时间。
当然,还包括渲染前onBeforeLoop
// 同样 可在任意vue文件下 调用
import { useLoop } from '@tresjs/core'
const { onBeforeRender, onRender } = useLoop()
onBeforeRender(() => {
console.log('earlier before render')
}, -10)
onBeforeRender(() => {
console.log('just before render')
})
onBeforeRender(() => {
console.log('even closer before render')
}, 10)
- 这里是
TvT.js,在项目中实践的地方,供参考:
const { onBeforeRender } = useLoop()
onBeforeRender(({ elapsed }) => {
if (!sphereRef.value) return
sphereRef.value.position.y += Math.sin(elapsed) * 0.01
sphereRef2.value.position.y += Math.sin(elapsed) * 0.01
})
所有回调都会接收具有以下属性的对象:
- delta:当前帧与上一帧之间的时间差。这是自上一帧以来的秒数。
- elapsed:自渲染循环开始以来经过的时间。
- renderer:您的场景的WebGLRenderer 。
- scene:你的场景的场景。
- camera:当前活动的相机。
- controls:场景的控制。
- invalidate:使渲染循环无效的方法。仅当您将render-modeprop 设置为 时才需要该方法on-demand。
- advance:一种推进渲染循环的方法。仅当您将render-modeprop 设置为 时才需要该方法manual。
- 等等 跳转tres.js章节
