2017-01-05 5 views
1

Bei der Arbeit haben wir eine komplexe Anwendung mit C#/WPF und dem MVVM-Muster erstellt. In der Anwendung haben wir eine Leinwand. Auf dieser Leinwand zeigen wir ein Bild in der Mitte der Leinwand. Wir wollen das Bild skalieren und übersetzen können. Wir können einen Skalierungsfaktor angeben, um alle Elemente auf der Arbeitsfläche zu skalieren. Um Transformationen auf das Bild anzuwenden, haben wir eine TransformGroup an die RenderTransform-Eigenschaft des Bildes in XAML gebunden. Die TransformGroup wird im Ansichtsmodell erstellt, indem zuerst die ScaleTransform gefolgt von der TranslateTransform hinzugefügt wird.Probleme beim Skalieren und Übersetzen von Bild auf Leinwand

Die Transformationen sind auf diese Weise angegeben:

// 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; 
} 

Jetzt sind wir in der Lage, das Bild richtig zu skalieren, wenn Sie den Skalierungsfaktor zu verändern.

Um die Übersetzung des Bildes zu ermöglichen, setzen wir das Bild in einen Thumb. Der Daumen liefert ein DragDelta-Ereignis, das uns die Verschiebung in x- und y-Richtung gibt. Diese Verschiebung wird bei jedem Ziehen des Daumens zu totalShift hinzugefügt. Die folgende Methode ist Teil des Ansichtsmodells und wird vom DragDelta-Ereignishandler im Code hinter der Ansicht aufgerufen.

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; 
} 

Das Problem: wir scalefactor 1,5 sagen, und wir das Bild 100 Pixel in x-Richtung gezogen

public void addShift(double horizontal, double vertical) { 
    totalShift.X += horizontal; 
    totalShift.Y += vertical; 
} 

ApplyTransformations() wird wie folgt geändert. Wenn wir ApplyTransformation() ausführen, wird das Bild nicht 100 px in x-Richtung verschoben, sondern nur 100/1,5 = 66,67 px. Dies bedeutet, dass die Verschiebung skaliert wird, bevor sie angewendet wird.

Wie können wir das erreichen? Jede Hilfe wird geschätzt. Danke im Voraus.

Edit: Die Transform auf diese Weise aufgebaut ist:

private TransformGroup _transform = new TransformGroup(); 
public TransformGroup Transform { 
    get { 
     _transformGroup.Children.Clear(); 
     _transformGroup.Children.Add(scaleTransform); 
     _transformGroup.Children.Add(translateTransform); 
    } 
} 

Wenn ich es auf diese Weise das Problem, das oben beschrieben occures tun.

Edit 2

ich eine MCVE erstellt haben, so können Sie ihn ausführen und das Problem sehen. Ändern Sie den Skalierungsfaktor auf einen Wert ungleich 1.0. Ziehen Sie dann die schwarze Leinwand mit der Maus vom roten Punkt (Mittelpunkt) weg und ändern Sie den Maßstabsfaktor erneut. Jetzt scheint die schwarze Leinwand ein wenig zu springen.

+1

Ändern Sie die Reihenfolge der Kinder des Transform? – Clemens

+0

Haben Sie auch den CenterX und CenterY der ScaleTransform repariert? Sie können vielleicht RenderTansformOrigin des Bildes besser einstellen. – Clemens

+0

Ich setze das RenderTransformOrigin auf das negative totalShift, anstatt es auf CenterX und CenterY der Maßstabs-Transformation zu setzen, aber es hat auch nicht funktioniert. – ooorndtski

Antwort

0

Ich glaube, dass Sie Ihre Transformationen in der falschen Reihenfolge anwenden. Zuerst übersetzen Sie, dann skalieren Sie. Sie sollten stattdessen versuchen, Ihre Maßstabsänderung auf Ihr Bild anzuwenden, gefolgt von einer Drehung auf Ihr Bild (in diesem Beispiel verwenden Sie keine), gefolgt von allen Übersetzungen.

Schauen Sie sich diese MSDN-Artikel für weitere Informationen über Bestellung von Transformationen: https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx

+0

Ich habe meinen Beitrag aktualisiert. Wenn ich die Reihenfolge der Kinder ändere, wird das Bild nicht mehr richtig skaliert, obwohl die erste Skalierung und dann die Übersetzung korrekt zu sein scheint. – ooorndtski

+0

Stellen Sie sicher, dass Ihre Transformationen richtig eingerichtet sind, indem Sie den oben genannten @ Clemens-Ratschlag befolgen. – RichardJones

Verwandte Themen