拖拽边角绕中心旋转非正方形矩形的异常问题咨询
修复非正方形矩形旋转时的跳转问题
问题根源
你的代码中使用固定的rotation_offset_in_radians(如-45°、135°)补偿边角位置,但这些角度仅适用于正方形——非正方形矩形的边角到中心的角度并非固定值(例如宽200、高100的矩形,右上角到中心的角度约为26.57°,而非-45°)。固定偏移角导致初始旋转时,计算角度与实际点击位置的角度不匹配,从而出现跳转。
解决方案
核心思路是基于初始点击的边角位置计算旋转增量,而非依赖固定角度偏移:
- 旋转开始时,根据矩形实际宽高计算边角相对于旋转中心的原始向量
- 拖拽过程中,计算当前光标相对于中心的向量,通过两个向量的夹角差得到旋转增量
- 用初始旋转角度加上增量,得到最终旋转角度
修改后的代码
pub fn handle_rotating( composition: &CompositionRes, selected_nodes_query: &mut Query< ( &mut RelativeTransformMixin, &AbsoluteTransformMixin, &DimensionMixin, ), With<Selected>, >, event: &CursorMovedOnComposition, corner: u8, initial_rotation: f32, ) { let CursorMovedOnComposition { position: cursor_position, .. } = event; let cursor_position = transform_point_to_view_box(composition, cursor_position, true); selected_nodes_query.for_each_mut( |(mut relative_transform_mixin, absolute_transform_mixin, dimension_mixin)| { let relative_pivot_point = Vec2::new( dimension_mixin.width as f32 / 2.0, dimension_mixin.height as f32 / 2.0, ); let absolute_pivot_point = apply_transform_to_point(absolute_transform_mixin.0, relative_pivot_point); // 1. 根据边角类型计算相对于自身中心的位置 let relative_corner = match corner { c if c == (HandleSide::Top as u8 | HandleSide::Left as u8) => { Vec2::new(-dimension_mixin.width as f32 / 2.0, -dimension_mixin.height as f32 / 2.0) } c if c == (HandleSide::Top as u8 | HandleSide::Right as u8) => { Vec2::new(dimension_mixin.width as f32 / 2.0, -dimension_mixin.height as f32 / 2.0) } c if c == (HandleSide::Bottom as u8 | HandleSide::Right as u8) => { Vec2::new(dimension_mixin.width as f32 / 2.0, dimension_mixin.height as f32 / 2.0) } c if c == (HandleSide::Bottom as u8 | HandleSide::Left as u8) => { Vec2::new(-dimension_mixin.width as f32 / 2.0, dimension_mixin.height as f32 / 2.0) } _ => Vec2::ZERO, }; // 2. 转换为旋转前的绝对边角位置 let initial_corner_position = apply_transform_to_point(absolute_transform_mixin.0, relative_corner); // 3. 计算初始边角向量与当前光标向量 let initial_corner_vector = initial_corner_position - absolute_pivot_point; let current_cursor_vector = cursor_position - absolute_pivot_point; // 4. 计算向量夹角差作为旋转增量 let initial_angle = initial_corner_vector.y.atan2(initial_corner_vector.x); let current_angle = current_cursor_vector.y.atan2(current_cursor_vector.x); let rotation_delta = current_angle - initial_angle; // 5. 应用最终旋转角度 let final_rotation_angle = initial_rotation + rotation_delta; relative_transform_mixin.0 = set_rotation( relative_transform_mixin.0, final_rotation_angle, relative_pivot_point, ); }, ); }
关键改进说明
- 移除固定角度偏移,改用矩形实际宽高计算边角初始位置,适配任意宽高比
- 旋转增量基于初始边角向量与当前光标向量的夹角差,确保旋转行为完全跟随光标拖拽轨迹
- 初始点击点与旋转行为完全对齐,彻底解决非正方形矩形的旋转跳转问题
内容的提问来源于stack exchange,提问作者BennoDev
相关产品推荐
相关产品推荐

