Странная проблема масштабирования в WPF - PullRequest
2 голосов
/ 09 сентября 2010

У меня есть холст, и я положил кое-что на него, затем я масштабировал его. Но, когда вы запускаете шкалы, они не берутся из той точки, в которой они должны, например, если вы немного масштабируете ее из одного источника, а затем из другого источника, второй источник действует так, как если бы он был немного смещен в действительности. странная мода вместо того, чтобы вести себя как задумано (и как ведет себя первоисточник). Я использовал этот код для масштабирования:

        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);
        }

Что на земле может происходить?

Я понял, что мой первоначальный текст вопроса был не так ясен, как мог бы быть. Я масштабируюсь от начала координат мыши, поэтому вы перемещаете указатель мыши слева от пары примеров текстовых объектов, прокручиваете колесо, и они увеличивают или уменьшают масштаб и передвигаются по экрану совершенно хорошим способом. Но если вы затем переместите указатель мыши вправо далеко на другую сторону объектов и попытаетесь прокрутить их, они будут действовать так, как если бы мышь находилась посередине, то есть увеличивать и уменьшать масштаб, не перемещаясь по экрану. на все.

1 Ответ

6 голосов
/ 09 сентября 2010

Когда вы создаете преобразование с помощью 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);
}

Аналогичный вариант - всегда удалять масштабирование из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);
}

Обновление: На самом деле, я думаю, что я пропустил больший, связанный эффект.Поскольку вы применяете новую шкалу после старой, перевод по 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...