我需要放大和缩小画布。但是缩放应始终以屏幕中心(而不是画布)为中心。这不适用于我目前的代码!它总是缩放到画布的中心而不是当前屏幕。 画布也应该是可移动的,但不应该被允许移离它的边界。 这就是我到目前为止所做的:
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这样的东西,但由于某种原因,这是更高效的..不要问我为什么!
有人能帮助我吗?
答案 0 :(得分:2)
这是我的Pan和Zoom解决方案,在我的复杂应用程序(12000px x 12000px)中都可以正常工作。
您需要具有缩放依赖属性(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();
}
}
}
更新缩放时,可以调用此方法计算中心点:
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;
}
我不提供所有代码,但如果你能理解我写的内容,它就是一个基础。
如果您需要更多信息(我知道这个问题已经过时了,这就是为什么我没有详细说明一切)请告诉我。