开发者

Zoom in and out to the center of the viewport in a canvas

开发者 https://www.devze.com 2023-02-21 23:28 出处:网络
I need to zoom in and out a canvas. But the zoom should always be centered to the center of the screen (not the canvas). And this doesnt work with my current code! It always zooms to the center of the

I need to zoom in and out a canvas. But the zoom should always be centered to the center of the screen (not the canvas). And this doesnt work with my current code! It always zooms to the center of the canvas and not the current screen. The canvas should also be moveable, but should not be aloweded to move away from it's borders. This is what I have so far:

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

And yes I know there is stuff like ScaleTransform but for some reason this is more performant.. dont ask me why!

Can 开发者_JAVA百科someone help me please?


Here is my solution for Pan and Zoom, both works fine in my complex application (12000px x 12000px).

You need to have a Zoom dependency property (double) and a ScaleTransform property

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

When you update the Zoom, you call this method to calculate the center point:

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

I don't provide all the code but it's a base if you can understand what I wrote.

If you need more information (I know that this question is old, this is why I'm not detailing everything) let me know.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号