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