跳到主要内容

<pc-entity>

<pc-entity> 定义具有名称、位置、旋转和缩放的场景实体,内部组件赋予渲染、光照和物理等能力。

用法

属性​

属性类型默认值说明
enabledBoolean(布尔)"true"实体启用状态
nameString(字符串)-实体名称,省略为 Untitled
positionVector3"0 0 0"局部位置 X Y Z
rotationVector3"0 0 0"局部角度制欧拉角 X Y Z
scaleVector3"1 1 1"局部缩放 X Y Z
tagsString(字符串)-逗号分隔标签列表

事件​

通过 addEventListener() 或 oneventname property 监听。

事件说明
click主指针按钮在实体上按下并释放,详见点击
pointercancel浏览器取消按下时,例如系统接管触摸,在起始实体上触发,不再产生 click
pointerdown指针在实体上按下
pointerenter指针从整个子树之外进入实体或后代,不冒泡
pointerleave指针离开实体及全部后代,不冒泡
pointermove指针在实体上移动
pointerout指针移出实体,relatedTarget 为进入的元素
pointerover指针进入实体,relatedTarget 为离开的元素
pointerup指针在实体上释放

所属 <pc-app> 通过拾取指针下场景分发事件,行为类似原生指针事件。九者都是 PointerEvent。多数以几何体对应的实体元素为 target,再沿树冒泡,因此祖先实体或 <pc-scene> 可接收整棵子树事件。

pointerenter 和 pointerleave 不冒泡,各进入或离开的元素单独触发。从背景进入实体时,实体和各祖先按从外到内触发 enter;从父项进入子项仅触发子项,因为并未离开父项。因此祖先对整个子树只收到一对进入/离开。四种边界事件的 relatedTarget 为来源或目标,背景或离开画布时为 pc-app。

各指针独立追踪,因此两个触摸可分别位于不同实体。离开画布结束悬停并触发 out/leave,但不结束按下;返回原实体释放仍点击,画布外释放则不点击。

也可声明 onclick 和 onpointer* 内联处理器,由浏览器按标准规则编译执行。设置属性替换旧处理器,移除属性解除。this 为挂载处理器的元素,event.target 为实际命中实体。

<pc-entity name="cube"
onpointerenter="this.setAttribute('scale', '1.2 1.2 1.2')"
onpointerleave="this.removeAttribute('scale')"
onclick="this.setAttribute('rotation', '0 45 0')">
<pc-render type="box"></pc-render>
</pc-entity>

点击​

点击选择优先使用 click,而非自行组合 down 与 up,因为:

  • 必须为主按钮,右键不会触发,而单独 pointerup 会。
  • 需要按下和释放,不会像 pointerdown 一样在摄像机拖动起点触发。
  • 两端命中不同几何体时,目标为最近共同祖先。从物体拖到同级物体会点击父项,两个顶层实体则点击 pc-scene;拖到背景不点击。与浏览器嵌套 HTML 规则相同。
  • detail 保存点击计数,同元素半秒内第二次点击为 2,因此从 detail 识别双击,而非独立事件。

浏览器收回触摸时,在起始实体触发 pointercancel,不形成点击。画布设 touch-action:none,因此触摸不会转为网页滚动。

何时分发事件​

拾取需要再次渲染场景,因此只有存在监听器时才执行。默认 picking=auto,仅在实体宿主或场景上注册了对应类型监听器时拾取,支持 addEventListener、内联属性和处理器 property。无监听时零额外开销。

以下两类监听器不会被自动发现:

  • 页面其他位置,如 document、pc-app 或 React onPointerMove 委托,只在实体路径上有可见监听器时才收到分发事件,自身不触发拾取。可设 picking=always 强制,none 关闭。React onClick 例外,会同时设置元素 onclick,因此实体或场景上的点击在 auto 下正常,无需 always 增加每次移动的拾取。
  • 标签定义之前通过 addEventListener 注册,例如库模块前执行的经典脚本,或模板追加前配置的克隆。应在导入库的模块中注册,克隆则追加后注册。内联属性或处理器 property 无此限制。

画布仍接收原生事件,因此 pc-app 或更高监听器可能同时收到原生与分发事件。isTrusted 为 true 表示原生,false 表示分发,后者 target 为实体、场景,或 always 模式某些边界事件的应用。分发事件要等 GPU 拾取读回,因此稍晚于原生。

示例​

台灯由嵌套实体构成,arm、forearm 和 head 相对父项定位旋转,转动任一关节会连带下游和灯光。所有处理器在 lamp 根,整个台灯仅触发一对 enter/leave,部件点击冒泡后切换灯泡 enabled。禁用实体连同组件和后代一起生效,因此灯光与发光外观同时关闭。可修改关节 rotation 或根 scale:

实时示例
<pc-app>
<pc-material id="paint" diffuse="#e8702a" gloss="0.7"></pc-material>
<pc-material id="steel" diffuse="#b7bec7" gloss="0.8"></pc-material>
<pc-material id="glow" emissive="#fff0d0"></pc-material>
<pc-material id="desk" diffuse="#3d4250"></pc-material>
<pc-scene>
<pc-entity name="camera" position="0.45 1.55 2.3" rotation="-27 0 0">
<pc-camera clear-color="#1d1f2b"></pc-camera>
</pc-entity>
<pc-entity name="room-light" rotation="40 50 0">
<pc-light intensity="0.8" cast-shadows normal-offset-bias="0.05" shadow-bias="0.2"></pc-light>
</pc-entity>
<pc-entity name="desk" scale="100 1 100">
<pc-render type="plane" material="desk"></pc-render>
</pc-entity>
<pc-entity name="lamp" rotation="0 -25 0"
onpointerenter="document.body.style.cursor = 'pointer'"
onpointerleave="document.body.style.cursor = ''"
onclick="const bulb = this.querySelector('[name=bulb]'); bulb.setAttribute('enabled', !bulb.enabled)">
<pc-entity name="base" position="0 0.025 0" scale="0.45 0.05 0.45">
<pc-render type="cylinder" material="paint"></pc-render>
</pc-entity>
<pc-entity name="arm" position="0 0.05 0" rotation="0 0 25">
<!-- The scale is on the rod, not the arm, so it doesn't stretch the joints beyond -->
<pc-entity name="arm-rod" position="0 0.35 0" scale="0.04 0.7 0.04">
<pc-render type="cylinder" material="steel"></pc-render>
</pc-entity>
<pc-entity name="forearm" position="0 0.7 0" rotation="0 0 -80">
<pc-entity name="forearm-rod" position="0 0.35 0" scale="0.04 0.7 0.04">
<pc-render type="cylinder" material="steel"></pc-render>
</pc-entity>
<pc-entity name="head" position="0 0.7 0" rotation="0 0 70">
<pc-entity name="shade" position="0 -0.12 0" scale="0.3 0.24 0.3">
<pc-render type="cone" material="paint"></pc-render>
</pc-entity>
<pc-entity name="bulb" position="0 -0.24 0" scale="0.1 0.1 0.1">
<pc-render type="sphere" material="glow"></pc-render>
<pc-light type="spot" color="#ffc978" intensity="4" inner-cone-angle="25" outer-cone-angle="35"></pc-light>
</pc-entity>
</pc-entity>
</pc-entity>
</pc-entity>
</pc-entity>
</pc-scene>
</pc-app>

JavaScript 接口​

可以通过 EntityElement API创建和操作元素。

entity 是底层 Entity,就绪前为 null。lookAt() 和子标签添加的组件等更多功能都可通过它访问。

需要复制实体子树时,可在原生 template 中声明并克隆,详见模板复用。

另请参阅​

示例:基本形状和下落方块。