事件
基于物体的识别事件:
V4.X以后的升级,已经修复了之前的bug,并且和primitive
统一起来了
<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"
@pointer-enter="onPointerEnter" @pointer-leave="onPointerLeave" @pointer-move="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')"
@context-menu="(event) => console.log('context-menu (right click)')"
@double-click="(event) => console.log('double-click')"
@pointer-move="(event) => console.log('pointer-move')"
@pointer-enter="(event) => console.log('pointer-enter')"
@pointer-leave="(event) => console.log('pointer-leave')"
@pointer-down="(event) => console.log('pointer-down')"
@pointer-up="(event) => console.log('pointer-up')"
@wheel="(event) => console.log('wheel')"
@pointer-missed="(event) => console.log('pointer-missed')"
/>
事件 | 描述 | 返回参数说明 |
---|---|---|
click | 基于同一物体的点击 | Intersection, PointerEvent |
pointer-move | 鼠标在物体上移动 | Intersection, PointerEvent |
pointer-enter | 鼠标划入物体 | Intersection, PointerEvent |
pointer-leave | 鼠标划出物体 | Intersection,PointerEvent |
- 更多
contextMenu、double-click 、wheel、pointer-down、pointer-up、pointer-missed
详见:TresJS事件
TIP
- 通常在几个物体互相遮挡时,可以通过使用
EventPropagation
来控制冒泡事件。 具体例子详见链接:穿透事件
<TresMesh
@pointer-down="(event) => {
console.log('pointer-down')
event.stopPropagation() //结束冒泡
}"
/>
因为
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
}
useRenderLoop 的全替代解决方案:
我们现在有// 此函数 可在任意vue文件下 调用
const { onLoop, resume } = useRenderLoop()
onLoop(({ delta, elapsed, clock }) => {
// I will run at every frame ~60FPS (depending of your monitor)
})
回调onLoop
根据时钟
接收具有以下属性的对象:
delta
:当前帧与上一帧之间的时间差。这是自上一帧以来的时间(以秒为单位)。elapsed
:自渲染循环开始以来经过的时间。
当然,还包括渲染前onBeforeLoop
,渲染后onAfterLoop
// 同样 可在任意vue文件下 调用
const { onBeforeLoop, onAfterLoop } = useRenderLoop()
onBeforeLoop(({ delta, elapsed }) => {
// I will run before the renderer updates the scene
fps.begin()
})
onAfterLoop(({ delta, elapsed }) => {
// I will run after the renderer updates the scene
fps.end()
})
- 这里查看更多详情:userenderloop
- 这里是
TvT.js
,在项目中实践的地方,供参考:
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (!sphereRef.value) return
sphereRef.value.position.y += Math.sin(elapsed) * 0.01
sphereRef2.value.position.y += Math.sin(elapsed) * 0.01
})
事件绑定的bug
注意 Tres.js3.9 以及之前的版本,存在TresGroup
以及primitive
中有 group 的情况下,事件绑定后,不响应的问题。
新版本已解决方案:
- 使用我们较新版本的TvT.js,已经升级了最新的依赖们。
- 使用 three.js 的原生射线的方式,完成功能,让代码性能更优,参考代码:
地图瓦片鼠标提取经纬度
- 使用 three.js 的原生射线的方式,完成功能,让代码性能更优,参考代码: