在 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