Au travail, nous avons construit une application complexe en utilisant C#/WPF et le canevas MVVM. Dans l'application, nous avons une toile. Sur cette toile, nous affichons une image au centre de la toile. Nous voulons pouvoir mettre à l'échelle et traduire l'image. Nous pouvons spécifier un facteur d'échelle pour mettre à l'échelle tous les éléments du canevas. Pour appliquer des transformations à l'image, nous avons lié un TransformGroup à la propriété RenderTransform de l'image dans XAML. Le TransformGroup est construit dans le modèle de vue en ajoutant d'abord le ScaleTransform suivi du TranslateTransform.Problèmes lors de la mise à l'échelle et de la traduction de l'image sur le canevas
Les transformations sont spécifiées de cette façon:
// View model
// Global fileds
private ScaleTransform scaleTransform = new ScaleTransform(1, 1);
private TranslateTransform translateTransform = new TranslateTransform(0, 0);
private Vector totalShift = new Vector(0, 0);
...
public void ApplyTransformations() {
scaleTransform.ScaleX = scaleFactor;
scaleTransform.ScaleY = scaleFactor;
translateTransform.X = canvasCenter.X - imageWidth/2;
translateTransform.Y = canvasCenter.Y - imageHeight/2;
}
Maintenant, nous sommes en mesure de redimensionner l'image correctement lors du changement du facteur d'échelle.
Pour permettre la traduction de l'image, nous mettons l'image dans un pouce. Le pouce fournit un événement DragDelta qui nous donne le décalage dans les directions x et y. Ce décalage est ajouté à totalShift chaque fois que nous faisons glisser le pouce. La méthode suivante fait partie du modèle de vue et est appelée par le gestionnaire d'événements DragDelta dans le code derrière la vue.
public void addShift(double horizontal, double vertical) {
totalShift.X += horizontal;
totalShift.Y += vertical;
}
ApplyTransformations() est modifié comme suit:
private double prevScaleFactor = 0;
public void ApplyTransformations() {
double oldCenterX = scaleTransform.CenterX;
double oldCenterY = scaleTransform.CenterY;
scaleTransform.CenterX = -totalShift.X;
scaleTransform.CenterY = -totalShift.Y;
translateTransform.X = (canvasCenter.X - imageWidth/2) + (scaleTransform.CenterX - oldCenterX) * prevScaleFactor;
translateTransform.Y = (canvasCenter.Y - imageHeight/2) + (scaleTransform.CenterY - oldCenterY) * prevScaleFactor;
scaleTransform.ScaleX = scaleFactor;
scaleTransform.ScaleY = scaleFactor;
prevScaleFactor = scaleFactor;
}
Le problème: Disons que scaleFactor est de 1,5 et nous avons traîné l'image 100 px dans la direction x. Lorsque nous exécutons ApplyTransformation(), l'image n'est pas décalée de 100 px dans la direction x, mais seulement 100/1,5 = 66,67 px. Cela signifie que le décalage est mis à l'échelle avant d'être appliqué.
Comment pouvons-nous y parvenir? Toute aide est appréciée. Merci d'avance.
Edit: Le TransformGroup est construit de cette façon:
private TransformGroup _transform = new TransformGroup();
public TransformGroup Transform {
get {
_transformGroup.Children.Clear();
_transformGroup.Children.Add(scaleTransform);
_transformGroup.Children.Add(translateTransform);
}
}
Si je le fais de cette façon le problème décrit ci-dessus occures.
Edit 2
J'ai créé un MCVE, vous pouvez l'exécuter et voir le problème. Changer le facteur d'échelle à une valeur différente de 1.0. Ensuite, faites glisser la toile noire avec votre souris loin du point rouge (point central) et modifiez le facteur d'échelle à nouveau. Maintenant, la toile noire semble sauter un peu.
Modifier l'ordre des enfants du TransformGroup? – Clemens
Avez-vous également corrigé le CenterX et le CenterY de ScaleTransform? Vous pourriez peut-être mieux définir RenderTansformOrigin de l'image. – Clemens
J'ai défini RenderTransformOrigin sur totalShift négatif au lieu de définir CenterX et CenterY de la transformation d'échelle, mais cela n'a pas fonctionné. – ooorndtski