Увеличьте и уменьшите масштаб до центра области просмотра на холсте - PullRequest
0 голосов
/ 01 апреля 2011

Мне нужно увеличивать и уменьшать масштаб холста.Но зум всегда должен быть центрирован по центру экрана (а не на холсте).И это не работает с моим текущим кодом!Он всегда приближается к центру холста, а не к текущему экрану.Холст также должен быть подвижным, но не должен допускать отход от его границ.Это то, что у меня есть:

XAML

    <Grid>
    <Canvas HorizontalAlignment="Left" Name="canvas1" VerticalAlignment="Top">
    </Canvas>
</Grid>

C #

        // x & y arent the position, it's how many pixel the object should move to the left/right etc
    public void setPosition(double x, double y)
    {
        Thickness t = new Thickness(canvas1.Margin.Left + x, canvas1.Margin.Top + y, 0, 0);
        if (t.Left > 0)
        {
            t.Left = 0;
        }
        else if(t.Left < -(canvas1.Width - System.Windows.SystemParameters.PrimaryScreenWidth))
        {
            t.Left = -(canvas1.Width - System.Windows.SystemParameters.PrimaryScreenWidth);
        }

        if (t.Top > 0)
        {
            t.Top = 0;
        }
        else if (t.Top < -(canvas1.Height - System.Windows.SystemParameters.PrimaryScreenHeight))
        {
            t.Top = -(canvas1.Height - System.Windows.SystemParameters.PrimaryScreenHeight);
        }

        canvas1.Margin = t;
    }

    public void setZoom(double zoom)
    {
        double tempW = canvas1.Width;
        double tempH = canvas1.Height;

        canvas1.Width *= (1 + zoom);
        canvas1.Height *= (1 + zoom);

        Debug.WriteLine("tempW: " + tempW + " tempH: " + tempH + " canvas1.Width: " + canvas1.Width + " canvas1.Height: " + canvas1.Height);

        setPosition((tempW - canvas1.Width) / 2, ((tempH - canvas1.Height) / 2));
    }

И да, я знаю, что есть такие вещи, как ScaleTransform, но по некоторым причинам это большеисполнитель .. не спрашивай меня почему!

Может кто-нибудь помочь мне, пожалуйста?

1 Ответ

2 голосов
/ 03 июля 2012

Вот мое решение для Pan и Zoom, оба отлично работают в моем сложном приложении (12000px x 12000px).

Вам необходимо иметь свойство зависимостей Zoom (double) и свойство ScaleTransform

private double m_dCurZoom = 1.0;
public double Zoom
{
   get { return m_dCurZoom; }
   set
   {
      double oldzoom = m_dCurZoom;
      if (m_dCurZoom != value)
      {
         m_dCurZoom = value;
         OnPropertyChanged("Zoom");
         UpdateZoom(oldzoom);
      }
   }
}

private ScaleTransform m_transZoom;
public ScaleTransform TransZoom
{
   get { return m_transZoom; }
}

private TranslateTransform m_transPan;

/// <summary>
/// Gets or sets the Panning in X axis.
/// </summary>
public double PanX
{
   get { return m_transPan.X; }
   set
   {
      if (m_transPan.X != value)
      {
         m_transPan.X = value;
         ResizeElementContents();
      }
   }
}

  /// <summary>
  /// Gets or sets the Panning in Y axis.
  /// </summary>
  public double PanY
  {
     get { return m_transPan.Y; }
     set
     {
        if (m_transPan.Y != value)
        {
           m_transPan.Y = value;
           ResizeElementContents();
        }
     }
  }

Когда вы обновляете Zoom, вы вызываете этот метод для вычисления центральной точки:

public void UpdateZoom(double oldzoom)
{
   // Are we visible?
   if (m_root == null)
      return;

   // Get parent of VirtualPanel
   FrameworkElement parent = GetRootParent();
   if (parent == null)
       return;

   // Center point of the window
   Point ptCenter = new Point(parent.RenderSize.Width / 2, parent.RenderSize.Height / 2);

   // Translate into canvas coordinates
   ptCenter = m_root.TranslatePoint(ptCenter, m_canvas);

   // Update the zoom
   m_transZoom.ScaleX = m_dCurZoom;
   m_transZoom.ScaleY = m_dCurZoom;
   m_transPan.X -= ptCenter.X * m_dCurZoom - ptCenter.X * oldzoom;
   m_transPan.Y -= ptCenter.Y * m_dCurZoom - ptCenter.Y * oldzoom;

   ResizeElementContents();

   OnPropertyChanged("Zoom");
}


/// <summary>
  /// Calculate the transform for given zoom & region-to-display for the given root's render-size
  /// </summary>
  public bool ResizeElementContents()
  {
     FrameworkElement parent = GetRootParent();
     if (parent == null || m_transPan == null)
        return false;

     // Calculate the total region of the root
     Rect? region = WtoHelper.CalcElementRect(Root);
     if (region == null || region.HasValue == false)
        return false;

     // Scale the region to get the actal size with the zoom transformation.
     double rgnWid = region.Value.Width * m_dCurZoom;
     double rgnHei = region.Value.Height * m_dCurZoom;

     // Image fits within our window width?
     if (parent.RenderSize.Width > rgnWid)
        m_transPan.X = (parent.RenderSize.Width - rgnWid) / 2;
     else
     {
        // Image needs to be resized
        if (m_transPan.X < -(rgnWid - parent.RenderSize.Width))
           m_transPan.X = -(rgnWid - parent.RenderSize.Width);
        else if (m_transPan.X > 0)
           m_transPan.X = 0;
     }

     // Image fits within our window height?
     if (parent.RenderSize.Height > rgnHei)
        m_transPan.Y = (parent.RenderSize.Height - rgnHei) / 2;
     else
     {
        // Image needs to be resized
        if (m_transPan.Y < -(rgnHei - parent.RenderSize.Height))
           m_transPan.Y = -(rgnHei - parent.RenderSize.Height);
        else if (m_transPan.Y > 0)
           m_transPan.Y = 0;
     }

     return true;
  }

Я не предоставляю весь код, но это основа, если вы понимаете, что я написал.

Если вам нужна дополнительная информация (я знаю, что этот вопрос старый, вот почему я не все подробно), дайте мне знать.

...