在 canvas 上缩放和平移图像时出现问题
Problems when scaling and translating image on canvas
在工作中,我们使用 C#/WPF 和 MVVM 模式构建了一个复杂的应用程序。在应用程序中我们有一个 canvas。在 canvas 上,我们在 canvas 的中心显示图像。我们希望能够缩放和平移图像。我们可以指定一个缩放因子来缩放 canvas 上的所有元素。为了对图像应用变换,我们将 TransformGroup 绑定到 XAML 中图像的 RenderTransform 属性。通过首先添加 ScaleTransform,然后添加 TranslateTransform,在视图模型中构建 TransformGroup。
转换是这样指定的:
// View model
// Global fileds
private ScaleTransform scaleTransform = new ScaleTransform(1, 1);
private TranslateTransform translateTransform = new TranslateTransform(0, 0);
private Vector totalShift = new Vector(0, 0);
...
public void ApplyTransformations() {
scaleTransform.ScaleX = scaleFactor;
scaleTransform.ScaleY = scaleFactor;
translateTransform.X = canvasCenter.X - imageWidth / 2;
translateTransform.Y = canvasCenter.Y - imageHeight / 2;
}
现在我们可以在更改比例因子时正确缩放图像。
为了能够翻译图像,我们将图像放入 Thumb。 Thumb 提供了一个 DragDelta 事件,它让我们在 x 和 y 方向上移动。每次我们拖动拇指时,都会将此移位添加到 totalShift。以下方法是视图模型的一部分,由视图后面的代码中的 DragDelta 事件处理程序调用。
public void addShift(double horizontal, double vertical) {
totalShift.X += horizontal;
totalShift.Y += vertical;
}
ApplyTransformations() 修改如下:
private double prevScaleFactor = 0;
public void ApplyTransformations() {
double oldCenterX = scaleTransform.CenterX;
double oldCenterY = scaleTransform.CenterY;
scaleTransform.CenterX = -totalShift.X;
scaleTransform.CenterY = -totalShift.Y;
translateTransform.X = (canvasCenter.X - imageWidth / 2) + (scaleTransform.CenterX - oldCenterX) * prevScaleFactor;
translateTransform.Y = (canvasCenter.Y - imageHeight / 2) + (scaleTransform.CenterY - oldCenterY) * prevScaleFactor;
scaleTransform.ScaleX = scaleFactor;
scaleTransform.ScaleY = scaleFactor;
prevScaleFactor = scaleFactor;
}
问题:
假设 scaleFactor 为 1.5,我们将图像沿 x 方向拖动 100 px。当我们执行 ApplyTransformation() 时,图像不会在 x 方向移动 100 像素,而只会移动 100 / 1.5 = 66.67 像素。这意味着在应用移位之前会对其进行缩放。
我们怎样才能做到这一点?任何帮助表示赞赏。提前致谢。
编辑:
TransformGroup 是这样构建的:
private TransformGroup _transform = new TransformGroup();
public TransformGroup Transform {
get {
_transformGroup.Children.Clear();
_transformGroup.Children.Add(scaleTransform);
_transformGroup.Children.Add(translateTransform);
}
}
如果我这样做,就会出现上述问题。
编辑 2
我创建了一个 MCVE,因此您可以 运行 它并查看问题。将比例因子更改为不等于 1.0 的值。然后用鼠标将黑色canvas拖离红点(中心点),再次改变比例因子。现在黑色canvas好像有点跳了
我认为您应用转换的顺序有误。首先是翻译,然后是缩放。相反,您应该尝试对图像应用比例更改,然后对图像进行任何旋转(在此示例中,您没有使用任何图像),然后进行任何平移。
查看此 MSDN 文章以获取有关转换顺序的更多信息:https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx
在工作中,我们使用 C#/WPF 和 MVVM 模式构建了一个复杂的应用程序。在应用程序中我们有一个 canvas。在 canvas 上,我们在 canvas 的中心显示图像。我们希望能够缩放和平移图像。我们可以指定一个缩放因子来缩放 canvas 上的所有元素。为了对图像应用变换,我们将 TransformGroup 绑定到 XAML 中图像的 RenderTransform 属性。通过首先添加 ScaleTransform,然后添加 TranslateTransform,在视图模型中构建 TransformGroup。
转换是这样指定的:
// View model
// Global fileds
private ScaleTransform scaleTransform = new ScaleTransform(1, 1);
private TranslateTransform translateTransform = new TranslateTransform(0, 0);
private Vector totalShift = new Vector(0, 0);
...
public void ApplyTransformations() {
scaleTransform.ScaleX = scaleFactor;
scaleTransform.ScaleY = scaleFactor;
translateTransform.X = canvasCenter.X - imageWidth / 2;
translateTransform.Y = canvasCenter.Y - imageHeight / 2;
}
现在我们可以在更改比例因子时正确缩放图像。
为了能够翻译图像,我们将图像放入 Thumb。 Thumb 提供了一个 DragDelta 事件,它让我们在 x 和 y 方向上移动。每次我们拖动拇指时,都会将此移位添加到 totalShift。以下方法是视图模型的一部分,由视图后面的代码中的 DragDelta 事件处理程序调用。
public void addShift(double horizontal, double vertical) {
totalShift.X += horizontal;
totalShift.Y += vertical;
}
ApplyTransformations() 修改如下:
private double prevScaleFactor = 0;
public void ApplyTransformations() {
double oldCenterX = scaleTransform.CenterX;
double oldCenterY = scaleTransform.CenterY;
scaleTransform.CenterX = -totalShift.X;
scaleTransform.CenterY = -totalShift.Y;
translateTransform.X = (canvasCenter.X - imageWidth / 2) + (scaleTransform.CenterX - oldCenterX) * prevScaleFactor;
translateTransform.Y = (canvasCenter.Y - imageHeight / 2) + (scaleTransform.CenterY - oldCenterY) * prevScaleFactor;
scaleTransform.ScaleX = scaleFactor;
scaleTransform.ScaleY = scaleFactor;
prevScaleFactor = scaleFactor;
}
问题: 假设 scaleFactor 为 1.5,我们将图像沿 x 方向拖动 100 px。当我们执行 ApplyTransformation() 时,图像不会在 x 方向移动 100 像素,而只会移动 100 / 1.5 = 66.67 像素。这意味着在应用移位之前会对其进行缩放。
我们怎样才能做到这一点?任何帮助表示赞赏。提前致谢。
编辑: TransformGroup 是这样构建的:
private TransformGroup _transform = new TransformGroup();
public TransformGroup Transform {
get {
_transformGroup.Children.Clear();
_transformGroup.Children.Add(scaleTransform);
_transformGroup.Children.Add(translateTransform);
}
}
如果我这样做,就会出现上述问题。
编辑 2
我创建了一个 MCVE,因此您可以 运行 它并查看问题。将比例因子更改为不等于 1.0 的值。然后用鼠标将黑色canvas拖离红点(中心点),再次改变比例因子。现在黑色canvas好像有点跳了
我认为您应用转换的顺序有误。首先是翻译,然后是缩放。相反,您应该尝试对图像应用比例更改,然后对图像进行任何旋转(在此示例中,您没有使用任何图像),然后进行任何平移。
查看此 MSDN 文章以获取有关转换顺序的更多信息:https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx