Svelte+Threlte中如何在父子组件间传递质心(centroid)数据?
解决方案:Svelte + Threlte 实现子组件质心传递与中心缩放
方案一:子组件主动传递质心(简洁无冗余)
不用store或context,直接利用Svelte原生事件系统让子组件把计算好的centroid传给HoverGroup:
- Shelf.svelte 改造
计算完成后通过事件派发器将质心传递给父组件:
<script> import { createEventDispatcher } from 'svelte'; import { T } from '@threlte/core'; const dispatch = createEventDispatcher(); let shelfMesh; // 计算质心逻辑(示例) $: if (shelfMesh) { const box = new THREE.Box3().setFromObject(shelfMesh); const centroid = box.getCenter(new THREE.Vector3()); // 派发质心就绪事件 dispatch('centroid-ready', centroid); } </script> <T.Mesh bind:object={shelfMesh}> <!-- 你的Shelf网格内容 --> </T.Mesh>
- HoverGroup.svelte 改造
监听子组件的centroid-ready事件,拿到质心后调整缩放原点:
<script> import { T } from '@threlte/core'; import { spring } from 'svelte/motion'; let group; let centroid = new THREE.Vector3(0, 0, 0); const scale = spring(1); // 接收子组件传递的质心 function handleCentroidReady(e) { centroid = e.detail; } // 鼠标 hover 触发缩放(以质心为原点) function handleHover() { scale.set(1.1); } function handleHoverEnd() { scale.set(1); } </script> <T.Group bind:object={group} on:hover={handleHover} on:hoverend={handleHoverEnd} on:centroid-ready={handleCentroidReady} > <!-- 通过平移+缩放组合实现中心缩放 --> <T.Object3D position={centroid.multiplyScalar(-1)} scale={$scale} > <slot /> </T.Object3D> </T.Group>
该方案无需额外状态管理工具,代码简洁,子组件只需负责计算自身质心并传递,HoverGroup专注处理缩放逻辑。
方案二:将居中逻辑完全移入HoverGroup(无需子组件修改核心逻辑)
如果希望质心计算逻辑完全封装在HoverGroup中,可通过slot props让子组件注册自身的Object3D:
- HoverGroup.svelte 改造
<script> import { T } from '@threlte/core'; import { spring } from 'svelte/motion'; let group; let childObjects = []; const scale = spring(1); let centroid = new THREE.Vector3(0, 0, 0); // 注册子组件的Object3D function registerChild(obj) { if (obj && !childObjects.includes(obj)) { childObjects.push(obj); calculateCombinedCentroid(); } } // 计算所有子元素的合并质心 function calculateCombinedCentroid() { const combinedBox = new THREE.Box3(); childObjects.forEach(obj => { const box = new THREE.Box3().setFromObject(obj); combinedBox.union(box); }); centroid = combinedBox.getCenter(new THREE.Vector3()); } // hover逻辑同方案一 function handleHover() { scale.set(1.1); } function handleHoverEnd() { scale.set(1); } </script> <T.Group bind:object={group} on:hover={handleHover} on:hoverend={handleHoverEnd} > <!-- 通过slot props传递注册函数 --> <slot registerChild={registerChild} /> </T.Group>
- Shelf.svelte 改造
只需调用slot传递的注册函数即可:
<script> import { T } from '@threlte/core'; export let registerChild; let shelfMesh; $: if (shelfMesh && registerChild) { registerChild(shelfMesh); } </script> <T.Mesh bind:object={shelfMesh}> <!-- 你的Shelf网格内容 --> </T.Mesh>
这种方式将质心计算逻辑完全封装在HoverGroup内,子组件仅需少量代码完成注册,耦合度极低。
内容的提问来源于stack exchange,提问作者Joseph Reece
相关产品推荐
相关产品推荐

