WPF中的奇怪缩放问题

Pup*_*ppy 2 c# wpf .net-4.0

我有一个Canvas,我把一些东西放在上面,然后我缩放它.但是,当你运行刻度时,它们不是来自它们应该的点,比如,如果你从一个原点缩放它,然后从另一个原点缩放,第二个原点就好像它在某种程度上偏移了奇怪的时尚,而不是按照预期的行为(和第一个原点的行为).我一直在使用这些代码来执行缩放:

        foreach (UIElement element in canvas1.Children)
        {
            Point p = e.MouseDevice.GetPosition(element);
            Matrix m = element.RenderTransform.Value;
            if (e.Delta > 0)
                m.ScaleAt(1.1, 1.1, p.X, p.Y);
            else
                m.ScaleAt(1 / 1.1, 1 / 1.1, p.X, p.Y);
            element.RenderTransform = new MatrixTransform(m);
        }
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?

我意识到我原来的问题文本并不是那么清晰.我从鼠标原点缩放,因此您将鼠标移动到我的示例文本对象的左侧,滚动滚轮,它们放大或缩小,并以完美的方式在屏幕上移动.但是,如果你然后将鼠标移动到对象另一侧的右侧,并尝试滚动,那么它们就好像鼠标位于它们中间 - 也就是说,它们可以放大和缩小而不会在屏幕上移动一点都不

Qua*_*ter 6

使用ScaleAt创建转换时,您也可以创建转换.例如,如果鼠标指针位于元素左侧100像素处,那么您将其缩放1.1并将其向右移动10个像素.下次运行代码时,您也会缩放该转换,因此除了新的转换之外,还要向右移动1个像素.

一种解决方案是在应用比例之前将翻译与之前的矩阵分开,然后在最后添加回来:

foreach (UIElement element in canvas1.Children)
{
    Point p = e.MouseDevice.GetPosition(element);
    Matrix m = element.RenderTransform.Value;
    Matrix m2 = m;
    m2.Translate(-m.OffsetX, -m.OffsetY);
    if (e.Delta > 0)
        m2.ScaleAt(1.1, 1.1, p.X, p.Y);
    else
        m2.ScaleAt(1 / 1.1, 1 / 1.1, p.X, p.Y);
    m2.Translate(m.OffsetX, m.OffsetY);
    element.RenderTransform = new MatrixTransform(m2);
}
Run Code Online (Sandbox Code Playgroud)

类似的选项是始终从RenderTransform中删除缩放并在Canvas.Left和Canvas.Top中对其进行编码:

foreach (UIElement element in canvas1.Children)
{
    Point p = e.MouseDevice.GetPosition(element);
    Matrix m = element.RenderTransform.Value;
    if (e.Delta > 0)
        m.ScaleAt(1.1, 1.1, p.X, p.Y);
    else
        m.ScaleAt(1 / 1.1, 1 / 1.1, p.X, p.Y);
    Canvas.SetLeft(element, Canvas.GetLeft(element) + m.OffsetX);
    Canvas.SetTop(element, Canvas.GetTop(element) + m.OffsetY);
    m.Translate(-m.OffsetX, -m.OffsetY);
    element.RenderTransform = new MatrixTransform(m);
}
Run Code Online (Sandbox Code Playgroud)

更新:实际上,我认为我错过了更大的相关效果.因为您在旧版本之后应用新版本,所以pX和pY的翻译在不应该缩放时进行缩放.当比例很大时,这将成为一个很大的错误(而我上面提到的错误总是10%的错误).

尝试使用ScaleAtPrepend首先应用新转换:

foreach (UIElement element in canvas1.Children)
{
    Point p = e.MouseDevice.GetPosition(element);
    Matrix m = element.RenderTransform.Value;
    if (e.Delta > 0)
        m.ScaleAtPrepend(1.1, 1.1, p.X, p.Y);
    else
        m.ScaleAtPrepend(1 / 1.1, 1 / 1.1, p.X, p.Y);
    Canvas.SetLeft(element, Canvas.GetLeft(element) + m.OffsetX);
    Canvas.SetTop(element, Canvas.GetTop(element) + m.OffsetY);
    m.Translate(-m.OffsetX, -m.OffsetY);
    element.RenderTransform = new MatrixTransform(m);
}
Run Code Online (Sandbox Code Playgroud)