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

react-konva如何设置Shape宽高填满父Group并同步补间动画

问题描述

我希望Text和Rect组件实现完全一致的运动动画效果,因此将二者放入同一个Group中,并对Group应用Tween补间动画。但实际使用中发现x、y属性可被子元素继承,width和height属性却不会被继承,导致Rect的宽高无法实现平滑补间效果。请问是否有方法可以设置Rect的宽高始终等于其所属Group容器宽高的100%,并能跟随Group的宽高变化实时同步?

初始实现代码

const { scaleFactor, DynamicData, isPause } = props;
const groupRef = useRef<Konva.Group>(null);
const start = DynamicData.startData;
const end = DynamicData.endData;

useEffect(() => {
  if (start && end && groupRef.current) {
    const animation = new Tween({
      node: groupRef.current,
      duration: DynamicData.endTime - DynamicData.startTime,
      x: scaleFactor * end.x,
      y: scaleFactor * end.y,
      width: scaleFactor * end.width,
      height: scaleFactor * end.height,
      easing: Easings.Linear,
    });

    if (isPause) {
      animation.pause();
    } else {
      animation.play();
    }
  }
});

return (
  <>
    {!_.isUndefined(end) && (
      <Group
        ref={groupRef}
        x={scaleFactor * start.x}
        y={scaleFactor * start.y}
        width={scaleFactor * start.width}
        height={scaleFactor * start.height}
      >
        <Text
          text={start.concept}
        />
        <Rect
          stroke={start.stroke}
        />
      </Group>
    )}
  </>
);

问题更新

目前我通过给Rect单独新增一个Tween实例,来追踪宽高变化:

const sizeAnimation = new Tween({
  node: rectRef.current,
  duration: DynamicData.endTime - DynamicData.startTime,
  width: scaleFactor * end!.width,
  height: scaleFactor * end!.height,
  easing: Easings.Linear,
});

if (isPause) {
  sizeAnimation.pause();
} else {
  sizeAnimation.play();
}
解决方案

Konva的Group本质只是逻辑容器,只负责坐标变换,不会向子元素继承width、height属性,所以直接给Group做宽高补间,本身就不会带动内部Rect的尺寸变化。

你现在给Rect单独加Tween的方案是可行的,只要保证两个Tween的时长、缓动函数、播放/暂停时机完全一致,就不会出现位置和尺寸变化错位的问题。
如果不想维护两个Tween实例,有两个更简单的实现思路:

  • 不给Group设置width、height属性,Group只负责承载x、y位移动画,把宽高补间直接绑定到Rect上即可,如果内部Text也需要跟随尺寸调整,同步给Text绑定对应属性动画就行,代码更简洁,也不会有属性不继承的问题
  • 如果确实需要Rect自动同步Group的宽高,Konva没有原生的百分比宽高配置,可以给Group绑定属性变更监听,当检测到width、height更新时,直接把对应值赋值给内部Rect的width、height属性,就能实现实时同步,不需要额外给Rect维护单独的动画实例。

注意:不要通过给Group加scale缩放的方式实现尺寸变化,scale会同时缩放内部元素的描边粗细、文字字号,和直接修改宽高的视觉效果有明显差异。

内容的提问来源于stack exchange,提问作者Bowen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 01:30:45