You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte+Threlte中如何在父子组件间传递质心(centroid)数据?

解决方案:Svelte + Threlte 实现子组件质心传递与中心缩放

方案一:子组件主动传递质心(简洁无冗余)

不用store或context,直接利用Svelte原生事件系统让子组件把计算好的centroid传给HoverGroup:

  1. 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>
  1. 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:

  1. 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>
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 19:12:35