放大和缩小画布中视口的中心

发布于 2024-10-28 13:24:59 字数 1690 浏览 2 评论 0原文

我需要放大和缩小画布。但缩放应始终以屏幕(而不是画布)的中心为中心。这不适用于我当前的代码!它始终缩放到画布的中心,而不是当前屏幕。 画布也应该是可移动的,但不应该允许移动离开它的边界。 这就是我到目前为止所拥有的:

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 这样的东西,但由于某种原因,它的性能更高..不要问我为什么!

有人可以帮我吗?

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 someone help me please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江城子 2024-11-04 13:24:59

这是我的平移和缩放解决方案,两者在我的复杂应用程序(12000px x 12000px)中运行良好。

您需要有一个 Zoom 依赖属性(双精度)和一个 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;
  }

我不提供所有代码,但如果您能理解我写的内容,它是一个基础。

如果您需要更多信息(我知道这个问题很旧,这就是为什么我没有详细说明所有内容),请告诉我。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文