2014-02-12 5 views
0

В моем приложении у меня есть многоугольник (с 4 точками = прямоугольник) на холсте. Я хочу увеличить масштаб многоугольника с помощью колеса мыши. Для этого я использую этот код:Избегайте перевода при масштабировании полинома и центра в положение мыши

double scale = 1.0, factor = 1.01, cX, cY; 

    void polygon_MouseWheel(object sender, MouseWheelEventArgs e) 
    { 
     cX = e.GetPosition(polygon).X; 
     cY = e.GetPosition(polygon).Y; 

     if (e.Delta > 0) scale *= factor; 
     else scale /= factor; 

     polygon.RenderTransform = new ScaleTransform(scale, scale, cX, cY); 
    } 

Это прекрасно работает, когда я поместить MousePointer в точку Р (скажем, P точка вблизи верхнего левого угла многоугольника) в многоугольник и выполните прокрутку вверх или вниз. Таким образом, многоугольник увеличивает или уменьшает масштаб в соответствии с этой точкой. Но когда я перемещаю указатель мыши на другую точку Q (около нижнего правого угла) и продолжаю увеличивать или уменьшать масштаб, полигон сдвигается в верхний левый угол на величину s. Кажется, что количество s зависит от расстояния между P и Q. Поэтому, если расстояние между P и Q велико, сдвиг большой.

Желаемое поведение в этом случае, что многоугольник не сдвигается, а просто масштабируется к новой точке Q.

ли кто-нибудь имеет представление о том, Что причиной сдвига? Я благодарен за любые намеки.

Пример кода:

<window ...> 
    <Grid> 
     <Canvas Name="canvas1" Background="LightBlue"> 
     <Polygon Points="100,100 100,300 300,300 300,100" Name="polygon" Fill="Black" MouseWheel="polygon_MouseWheel"/> 
    </Canvas> 
    </Grid> 
</Window> 
public MainWindow() 
{ 
    InitializeComponent(); 
} 

double scale = 1.0, factor = 1.01, cX, cY; 

void polygon_MouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    cX = e.GetPosition(polygon).X; 
    cY = e.GetPosition(polygon).Y; 

    if (e.Delta > 0) scale *= factor; 
    else scale /= factor; 

    polygon.RenderTransform = new ScaleTransform(scale, scale, cX, cY); 
} 

ответ

0

Ok, после попытки вокруг некоторое время я узнал, что вызывает такое поведение. Свойство MSDN article of the UIElement.RenderTransform говорит:

Преобразование визуализации не регенерирует размер макета или информацию о размере изображения. Преобразования рендеринга обычно предназначены для анимации или применения временного эффекта к элементу. Например, элемент может увеличиваться, когда он сфокусирован или замаскирован, или может дрожать при загрузке, чтобы привлечь внимание к той части пользовательского интерфейса (UI).

Это означает, что сам полигон, соответственно точки многоугольника, не преобразуется. При применении ScaleTransform точки многоугольника не изменяются и остаются такими, какими они были установлены в xaml. Тем не менее преобразованный многоугольник будет реагировать на события мыши, но положение мыши отображается на исходные границы.

Пример: Давайте возьмем многоугольник, определенный выше в xaml, и масштабируем его в 1,5 раза. Многоугольник отображается масштабированным и кажется, что его точки имеют значения (150, 150, 150, 450, 450, 450, 450, 150). Но внутри он все еще имеет старые значения (100 100 100 300 300 300 300 100). Если вы поймаете позицию указателя мыши в верхнем правом верхнем углу, это будет (300 100) вместо (450 150).

Использование положения мыши как центра для масштабирования вызывает смещение масштабированного многоугольника.

Решение этого заключается в том, чтобы масштабировать точки самого полигона, вместо использования ScaleTransform:

void Scale(double factor, double centerX, double centerY) 
{ 
    PointCollection pc = new PointCollection(); 

    foreach (Point p in polygon.Points) 
    { 
     Point q = new Point(); 

     q.X = p.X; 
     q.Y = p.Y; 

     q.X -= centerX; // translate 
     q.Y -= centerY; 

     q.X *= factor;  // scale 
     q.Y *= factor; 

     q.X += centerX; // translate back 
     q.Y += centerY; 

     pc.Add(q); 
    } 

    polygon.Points = pc; // polygon is defined in xaml 
} 

я не уверен, если это правильный способ сделать это, но это работает для меня ,