ScaleTransform transforme non linéaire
-
24-10-2019 - |
Question
J'utilise l'échelle transformer pour permettre à un utilisateur de redimensionner un contrôle. Ce qui se passe est bien que lorsque vous commencez à déplacer la souris le contrôle passe à une nouvelle taille, puis échelles curieusement. Plus vous déplacez votre souris à partir de la position de départ plus l'augmentation de la taille devient.
J'attends sa la façon dont je calcule l'échelle à appliquer. Voici le code:
private void ResizeGrip_MouseDown(object sender, MouseButtonEventArgs e)
{
ResizeHandle.CaptureMouse();
//Get the initial coordinate cursor location on the window
initBtmX = e.GetPosition(this).X;
bottomResize = true;
}
private void ResizeGrip_MouseUp(object sender, MouseButtonEventArgs e)
{
bottomResize = false;
ResizeHandle.ReleaseMouseCapture();
}
private void ResizeGrip_MouseMove(object sender, MouseEventArgs e)
{
if( bottomResize == true)
{
//Get the new Y coordinate cursor location
double newBtmX = e.GetPosition(this).X;
//Get the smallest change between the initial and new cursor location
double diffX = initBtmX - newBtmX;
// Let our rectangle capture the mouse
ResizeHandle.CaptureMouse();
double newWidth = e.GetPosition(this).X - diffX;
double scaler = newWidth / ResizeContainer.ActualWidth;
Console.WriteLine("newWidth: {0}, scalar: {1}", newWidth, scaler);
if (scaler < 0.75 || scaler > 3)
return;
ScaleTransform scale = new ScaleTransform(scaler, scaler);
ResizeContainer.LayoutTransform = scale;
}
}
Mise à jour: Maintenant, avec XAML
<wtk:IToolDialog x:Name="VideoPlayer" ParentControl="{Binding ElementName=Stage}" DialogTitle="Video Player" Margin="90,5,0,0">
<Grid>
<Grid x:Name="ResizeContainer" ClipToBounds="True" Width="320" Height="240" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,1">
<!-- The video frame -->
<Image Stretch="Fill" Source="{Binding CurrentFrameImage}" x:Name="VideoImage" />
<Grid>
<pplcontrols:VideoGroundPlane Foreground="Black" GridSize="20" GroundPlane="{Binding GroundPlane}">
</pplcontrols:VideoGroundPlane>
</Grid>
<Grid x:Name="HitMask" IsHitTestVisible="False"/>
</Grid>
<ResizeGrip Cursor="SizeNWSE" x:Name="ResizeHandle" VerticalAlignment="Bottom" HorizontalAlignment="Right" Mouse.MouseDown="ResizeGrip_MouseDown" Mouse.MouseUp="ResizeGrip_MouseUp" Mouse.MouseMove="ResizeGrip_MouseMove"></ResizeGrip>
</Grid>
</wtk:IToolDialog>
La solution
Toute raison pour laquelle vous n'utilisez pas ResizeContainer.RenderTransfrom au lieu de ResizeContainer.LayoutTransform? C'est à dire. utilisation
ResizeContainer.LayoutTransform = scale;
Si vous voulez que l'échelle soit linéaire, je pense que vous devriez utiliser
double scaler = 1 - diff / ResizeContainer.ActualWidth;
EDIT:
Il y a un bogue dans le code qui provoque le contrôle mises à l'échelle « sauter » dans la taille si vous essayez de redimensionner plus d'une fois. Je vous suggère de faire ce qui suit:
Ajouter un RenderTransform à votre réseau ResizeContainer:
<Grid.RenderTransform>
<ScaleTransform x:Name="transform" ScaleX="1" ScaleY="1" />
</Grid.RenderTransform>
Modifier le code dans votre gestionnaire d'événements MouseMove à ce qui suit:
if (bottomResize)
{
double newBtmX = e.GetPosition(this).X;
double scaler = -(initBtmX - newBtmX) / grid1.ActualWidth;
initBtmX = newBtmX;
transform.ScaleX += scaler;
transform.ScaleY += scaler;
}
De cette façon, vous modifiez l'échelle quel que soit peu la souris est déplacé tout en faisant glisser. Tous les contrôles enfants dans la grille devrait évoluer aussi bien.