交互
场景完成后,可根据需求选择不同交互方式。
指针事件
给 Entity 添加指针处理器,即可响应用户输入。
提示
事件会沿 React 树冒泡,因此可在父实体统一处理。
例如,创建点击变色球体:
- 演示
- 代码
interactivity.jsx
import { useState } from 'react'
import { Entity } from '@playcanvas/react'
import { Render } from '@playcanvas/react/components'
import { useMaterial } from '@playcanvas/react/hooks'
export const Interactivity = () => {
const colors = [
'lavender', 'lightsteelblue', 'powderblue', 'rebeccapurple'
]
// Create the initial diffuse color and create the material
const [diffuse, setDiffuse] = useState('lightsteelblue')
const material = useMaterial({ diffuse })
const onRequestRandomColor = () => {
setDiffuse(colors[Math.floor(Math.random() * colors.length)])
}
// Attach hover and leave handlers to the sphere
const onHover = () => document.body.style.cursor = 'pointer'
const onLeave = () => document.body.style.cursor = 'default'
return (
// Attach an onClick handler to the sphere to request a color change
<Entity
name="sphere"
onClick={onRequestRandomColor}
onPointerOver={onHover}
onPointerOut={onLeave} >
<Render type="sphere" material={material} />
</Entity>
)
}
实体支持以下与 DOM 指针 API 接近的事件:
onPointerUponPointerDownonPointerOveronPointerOutonClick
Script 组件
Script 可将任意 ESM PlayCanvas 脚本挂到实体,适合交互、动画和 React 渲染循环之外的行为。
将脚本类传给 Script 的 script prop:
- 演示
- 代码
scripting.jsx
import { Entity } from '@playcanvas/react'
import { Render } from '@playcanvas/react/components'
import { Script } from '@playcanvas/react/components'
import { Script as PcScript } from 'playcanvas'
/**
* A simple script that rotates the entity it's attached to.
*/
class SpinningCube extends PcScript {
static scriptName = 'spinningCube'
speed = 10
update(dt) {
this.entity.rotate(0, dt * this.speed, dt * this.speed * 2)
}
}
export const Scripting = () => (
<Entity>
<Render type="box" />
<Script script={SpinningCube} speed={10} />
</Entity>
)
脚本是继承 Script 的 ES 模块,可复用已有类、自行编写或使用引擎脚本库。
提示
逐帧动画通常用 Script 比重渲染 React 树更高效,但可能覆盖 Entity props。
详情见脚本文档。
应用事件
useAppEvent 以更贴近 React 的方式订阅内置或自定义事件,提供相应回调签名和 TypeScript 支持。
下例监听 update 旋转胶囊体:
- 演示
- 代码
app-events.jsx
import { useAppEvent } from '@playcanvas/react/hooks'
import { Entity } from '@playcanvas/react'
import { Render } from '@playcanvas/react/components'
import { useRef } from 'react'
export const AppEvents = () => {
const speed = 10;
const boxRef = useRef(null);
useAppEvent('update', (dt) => {
boxRef.current?.rotate(0, dt * speed, dt * speed * 2);
});
const onEntityClick = () => {
console.log('Entity clicked');
}
return (
<Entity ref={boxRef}>
<Render type='capsule' />
</Entity>
)
}
全部事件及回调详见 Application API。
也可使用 app.fire 触发自己的事件。
import { useAppEvent } from '@playcanvas/react/hooks'
const MyComponent = () => {
useAppEvent('myEvent', (message) => {
console.log('My event fired.', message);
});
}
app.fire('myEvent', 'Hello, world!');