Estou implementando um recurso para girar formas usando alças de canto. A rotação funciona bem para formas quadradas, mas estou enfrentando um problema com formas não quadradas (retângulos com proporções diferentes de 1:1). Ao girar essas formas arrastando uma alça de canto, elas "encaixam" ou giram inesperadamente, sem levar em conta a proporção da forma. Isso resulta em um desalinhamento entre o ponto de clique inicial do cursor e o comportamento de rotação da forma.
Suspeito que o problema esteja no meu cálculo de rotação, que não considera a proporção, levando a deslocamentos de ângulo incorretos durante a rotação.
Como posso calcular corretamente a rotação, levando em consideração a proporção da forma, para garantir um comportamento suave e esperado quando os usuários giram formas não quadradas?
Talvez eu também esteja tentando resolver um problema de um problema, então o problema principal que quero resolver é basicamente como girar um retângulo em torno do centro por meio de alças de canto. Você pode ver o comportamento neste vídeo .
Código:
pub fn handle_rotating(
composition: &CompositionRes,
selected_nodes_query: &mut Query<
(
&mut RelativeTransformMixin,
&AbsoluteTransformMixin,
&mut 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);
// Determine rotation offset based on corner
let rotation_offset_in_radians: f32 = match corner {
_ if corner == (HandleSide::Top as u8 | HandleSide::Left as u8) => {
(-135.0 as f32).to_radians()
}
_ if corner == (HandleSide::Top as u8 | HandleSide::Right as u8) => {
(-45.0 as f32).to_radians()
}
_ if corner == (HandleSide::Bottom as u8 | HandleSide::Right as u8) => {
(45.0 as f32).to_radians()
}
_ if corner == (HandleSide::Bottom as u8 | HandleSide::Left as u8) => {
(135.0 as f32).to_radians()
}
_ => 0.0,
};
// Calculate rotation based on the corner
let rotation_angle =
calculate_rotation(initial_rotation, &cursor_position, &absolute_pivot_point);
let final_rotation_angle =
rotation_angle + rotation_offset_in_radians - initial_rotation;
relative_transform_mixin.0 = set_rotation(
relative_transform_mixin.0,
final_rotation_angle,
relative_pivot_point,
);
},
);
}
fn calculate_rotation(
initial_angle_in_radians: f32,
cursor_point: &Vec2,
pivot_point: &Vec2,
) -> f32 {
// Calculate the angle from the pivot point to the current cursor position
let current_angle = (cursor_point.y - pivot_point.y).atan2(cursor_point.x - pivot_point.x);
// Calculate the raw angle difference
let angle_diff = current_angle - initial_angle_in_radians;
return -angle_diff;
}
Os
rotation_offset_in_radians
valores estão configurados errados. Os ângulos correspondentes aos vários cantos assumem que a forma é quadrada e, portanto, vistos do centro, os cantos estão espaçados de 90 graus. Isso não é verdade em um retângulo:O que você precisa fazer é usar a proporção do retângulo (ou suas dimensões reais, não faz diferença), em combinação com, por exemplo,
atan2
para descobrir o ângulo correspondente a cada canto.Isso fornece os mesmos ângulos do código original quando a largura e a altura são iguais: