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
相关产品推荐
相关产品推荐

