我试图在我在此处找到的控件上设置缩放和平移限制: https://wpfextensions.codeplex.com
我设法设置了缩放限制,但现在我设置了平移限制,因此您无法在视图外部平移画布内的对象。< / p>
我成功设置了限制,但只有当缩放级别为1(Zoom == 1
,因此没有缩放),但增加缩放的那一刻(通过旋转鼠标滚轮) )事情开始出错:设置限制,但设置不正确。
为了正确设置它们,我必须考虑deltaZoom
(与前一个缩放值相比变焦量的变化)。
我创建了一个简单的独立项目,我可以重现这个问题: https://github.com/igorpopovio/CanvasZoomPan
项目显示一个桌面窗口,其中包含ZoomControl
(带有ScaleTransform
的画布,TranslateTransform
和一系列依赖项属性,以便更轻松地处理变换)。 ZoomControl
包含一个红色方块,窗口包含ZoomControl
和一个属性的调试列表,因此我可以看到它们如何根据左击拖动和鼠标滚轮缩放进行更改。
预期行为:对象/红色方块边缘无法离开当前视图。
实际行为:对象/红色方边缘离开当前视图(仍有限制,但未正确设置)。
所有动作都发生在this file中,重要的部分是:
MinTranslateX, MaxTranslateX; MinTranslateY, MaxTranslateY
TranslateX, TranslateY
Zoom
deltaZoom
(本地变量)Zoom_PropertyChanged
方法LimitZoomingAndPanning
方法在LimitZoomingAndPanning
方法中,我设置了适用于Zoom == 1
(deltaZoom == 1
)的翻译/平移限制,但是对任何其他Zoom
值都给出了不正确的限制:
MinTranslateX = box.BottomLeft.X * deltaZoom;
MinTranslateY = box.BottomLeft.Y * deltaZoom;
MaxTranslateX = ActualWidth - box.Size.Width * deltaZoom;
MaxTranslateY = ActualHeight - box.Size.Height * deltaZoom;
box
变量实际上是画布内对象的边界框。 ActualWidth
和ActualHeight
是渲染对象的画布的大小。
逻辑上,所有翻译/平移限制都应取决于deltaZoom
。
也许我错过了什么?
答案 0 :(得分:0)
我最初尝试使用ZoomAndPanControl
做同样的事情,但无法实现我想要的功能,所以我最终编写了自己的控件来提供受约束的缩放和平移控件。
我已经将此控件打包在nuget上,但是可以在我的gist和我的github上找到,该演示项目将图像加载到视口控件中。
PM > Install-Package Han.Wpf.ViewportControl
用法:
<controls:Viewport MinZoom="1" MaxZoom="50" ZoomSpeed="1.1">
<Grid width="1200" height="1200">
<Button />
</Grid>
</controls:Viewport
并将主题添加到app.xaml
:
<Application.Resources>
<ResourceDictionary Source="pack://application:,,,/Han.Wpf.ViewportControl;component/Themes/Generic.xaml" />
</Application.Resources>
我知道您不使用MatrixTransform,而是将控件约束到父对象的边界,其计算方式如下:
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
if (IsEnabled)
{
var scale = e.Delta > 0 ? ZoomSpeed : 1 / ZoomSpeed;
var position = e.GetPosition(_content);
var x = Constrain(scale, MinZoom / _matrix.M11, MaxZoom / _matrix.M11);
var y = Constrain(scale, MinZoom / _matrix.M22, MaxZoom / _matrix.M22);
_matrix.ScaleAtPrepend(x, y, position.X, position.Y);
ZoomX = _matrix.M11;
ZoomY = _matrix.M22;
Invalidate();
}
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (IsEnabled && _capture)
{
var position = e.GetPosition(this);
var point = new Point
{
X = position.X - _origin.X,
Y = position.Y - _origin.Y
};
var delta = point;
_origin = position;
_matrix.Translate(delta.X, delta.Y);
Invalidate();
}
}
在无效呼叫Constrain()
private double Constrain(double value, double min, double max)
{
if (min > max)
{
min = max;
}
if (value <= min)
{
return min;
}
if (value >= max)
{
return max;
}
return value;
}
private void Constrain()
{
var x = Constrain(_matrix.OffsetX, _content.ActualWidth - _content.ActualWidth * _matrix.M11, 0);
var y = Constrain(_matrix.OffsetY, _content.ActualHeight - _content.ActualHeight * _matrix.M22, 0);
_matrix = new Matrix(_matrix.M11, 0d, 0d, _matrix.M22, x, y);
}