2016-10-18 1 views
1

ich das Scrollrad bin mit in und aus auf einem Objekt vergrößern die folgende Methode:Skalierung Zoomfaktoren

void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    lastMousePositionOnTarget = Mouse.GetPosition(grid); 

    double max = 255; 
    double min = .005; 

    var deltaScale = Math.Max(Math.Log(scaleTransform.ScaleX), double.Epsilon); 
    var delta = e.Delta > 0 ? Math.Max(e.Delta * deltaScale, .5) : Math.Min(e.Delta * deltaScale, -.5); 
    double newScale = Math.Max(Math.Min((delta/250d) + scaleTransform.ScaleX, max), min); 

    scaleTransform.ScaleX = newScale; 
    scaleTransform.ScaleY = newScale; 

    System.Diagnostics.Debug.WriteLine(newScale); 

    e.Handled = true; 
} 

Ich möchte es langsamer haben, zu vergrößern, wenn es näher an dem max gezoomt wird, und schneller, wenn die Anzahl näher am Minimum liegt. Was ich derzeit habe, funktioniert irgendwie, aber nicht sehr gut. Wie kann ich das beheben, um das zu tun, was ich will?

+0

Um die Verwendung/das Lesen zu vereinfachen, berechnen Sie die Größe/Größe vor und lassen Sie das Mausrad einen Index einstellen. @GEEF ist auf dem richtigen Weg bis zur Berechnung der Werte. – overslacked

Antwort

2

Angenommen, ich verstehe das richtig, Sie möchten, dass Ihre deltaScale groß, wenn gezoomt, aber klein, wenn herausgezoomt. Dadurch erhalten Sie schnelles Zoomen bei nahem und langsamen Zoomen bei Weitem.

Wenn scaletransform.ScaleX kleiner wird, wie Sie in gezoomt sind, versuchen Sie so etwas wie dieses:

var deltaScale = Math.Max(K * 1/(scaleTransform.ScaleX), double.Epsilon); 

wobei K nur einige konst Sie mess around mit, bis es sich richtig anfühlt.

Wenn scaletransform.ScaleX größer wird, wie Sie in gezoomt sind, versuchen Sie dann so etwas wie wie Ihr Log, mit einem größeren Koeffizienten als 1:

var deltaScale = Math.Max(5*Math.Log(scaleTransform.ScaleX), double.Epsilon); 
+0

Das ist 1/2 Weg dorthin - und eine der Ideen, die ich am Anfang versuchte. Das K * 1/Scale funktioniert, aber es ist zu langsam beim Zoomen und zu schnell beim Herauszoomen. –

+0

Zum Beispiel mit K == .5, beginnend bei einem Wert von 20 dauert es etwa 40 Maus-Scrolls um 19 zu bekommen. Aber sobald wir 1,5 erreicht haben, geht es schnell zu 1.1 -> .75 -> .08 -> .005 . –

1

Zunächst einmal würde ich nicht Wert e.Delta für Berechnungen verwenden (Zeichen ist natürlich erforderlich). Dieser Wert ist nicht sehr zuverlässig - meiner Erfahrung nach lag er nahe bei zufälligem Rauschen. Verwenden Sie stattdessen einen konstanten Wert oder einen Zähler, z. B. wie oft in einer Zeile das Zoomen ausgeführt wurde und wie oft in einer Zeile das Zoomen ausgeführt wurde.

Also mein erster Versuch (mit konstantem Wert) würde irgendwie so aussehen.

void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    lastMousePositionOnTarget = Mouse.GetPosition(grid); 

    double max = 255; 
    double min = .005; 

    var deltaScale = Math.Max(Math.Log(scaleTransform.ScaleX), double.Epsilon); 
    var delta = e.Delta > 0 ? Math.Max(1 * deltaScale, .5) : Math.Min(1 * deltaScale, -.5); 
    double newScale = Math.Max(Math.Min((delta/250d) + scaleTransform.ScaleX, max), min); 

    scaleTransform.ScaleX = newScale; 
    scaleTransform.ScaleY = newScale; 

    System.Diagnostics.Debug.WriteLine(newScale); 

    e.Handled = true; 
} 

Version mit Zählern würde in etwa so aussehen.

private double counter=0; 
private bool isZoomIn=true; 
void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    lastMousePositionOnTarget = Mouse.GetPosition(grid); 

    if((e.Delta > 0 && isZoomIn) || (e.Delta < 0 && !isZoomIn)) 
       IncreaseCounter(counter);//is another one in a row 
    else 
       counter=1; 

    isZoomIn = e.Delta > 0;//we set this flag for next time 

    double max = 255; 
    double min = .005; 

    var deltaScale = Math.Max(Math.Log(scaleTransform.ScaleX), double.Epsilon); 
    var delta = e.Delta > 0 ? Math.Max(counter * deltaScale, .5) : Math.Min(counter * deltaScale, -.5); 
    double newScale = Math.Max(Math.Min((delta/250d) + scaleTransform.ScaleX, max), min); 

    scaleTransform.ScaleX = newScale; 
    scaleTransform.ScaleY = newScale; 

    System.Diagnostics.Debug.WriteLine(newScale); 

    e.Handled = true; 
} 

Bitte beachte, dass ich Pseudofunktion IncreaceCounter statt nur incrementaion verwendet, weil Sie etwas anderes als nur lineare Erhöhung möchten.

+0

In meinen Testfällen war e.Delta immer eine Konstante 120 oder -120. Aber deine Antwort lässt mich erkennen, dass dies nicht immer auf allen Computern gleich ist. Also nehme ich das unter Beratung. Soweit Zähler gehen, möchte ich diese vermeiden - ich sollte in der Lage sein, irgendeine Art von Gleichung zu machen, die weiß, wie weit ich auf der Grundlage der aktuellen Scale.X herausgezoomt bin. –

+0

Ich dachte auch das Gleiche über das Delta, mit einem const und die Delta * Richtung * ist die beste Option. – GEEF

1

Dies ist meine endgültige Antwort, ich hätte es nicht schaffen können, wenn nicht für GEEF & Pawel so ein großes Dankeschön für sie geben ihr Bestes.

void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    double max = 255; 
    double min = .005; 
    double scaler = 4; 

    var deltaScale = Math.Min(Math.Max(scaler * scaleTransform.ScaleX/max, min),1) * Math.Sign(e.Delta); 
    double newScale = Math.Max(Math.Min(deltaScale + scaleTransform.ScaleX, max), min); 

    scaleTransform.ScaleX = newScale; 
    scaleTransform.ScaleY = newScale; 

    e.Handled = true; 
} 

Ich benutze ein Verhältnis der aktuellen Skala bis zum Maximum der Steigung zu bekommen - und lassen Sie es nicht zu schnell (max 1) oder zu langsam, min == die min Skala gehen. Funktioniert OK.