Как вы можете рассчитать координату X / Y, чтобы увеличить - PullRequest
4 голосов
/ 04 марта 2010

Я пишу приложение WPF с возможностью масштабирования и панорамирования, но я также хочу реализовать возможность автоматического масштабирования и панорамирования (с помощью нажатия кнопки).

У меня есть все методы для масштабирования и панорамирования, но я не могу сообщить приложению желаемые координаты X / Y для панорамирования.

В принципе, я знаю, что хочу, чтобы элемент управления центрировался на желаемом уровне масштабирования (скажем, увеличенном в 6 раз), но точка назначения панорамирования НЕ является центральной точкой элемента управления, поскольку после масштабирования его масштабировали.

Кто-нибудь знает способ расчета желаемой позиции X / Y для панорамирования, учитывая также масштабирование? Должен ли я просто масштабировать желаемую точку назначения? Кажется, это не работает для меня ...

Большое спасибо

РЕДАКТИРОВАТЬ - ЗАВЕРШЕНО -

Вот теперь то, что у меня работает, прекрасно работает:)

<Canvas x:Name="LayoutRoot" Background="{DynamicResource WindowBackground}" Width="1024" Height="768">
    <Canvas x:Name="ProductCanvas" Width="1024" Height="768">
        <Canvas.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform/>
                <TranslateTransform />
            </TransformGroup>
        </Canvas.RenderTransform>
        <Rectangle x:Name="r1" Fill="White" Stroke="Black" Width="180" Height="103.5" Canvas.Left="131.5" Canvas.Top="121.5" MouseDown="r1_MouseDown"/>
        <Rectangle x:Name="r2" Fill="#FF942222" Stroke="Black" Width="180" Height="103.5" Canvas.Left="617.5" Canvas.Top="121.5" MouseDown="r2_MouseDown"/>
        <Rectangle x:Name="r3" Fill="#FF2B1E9F" Stroke="Black" Width="180" Height="103.5" Canvas.Left="131.5" Canvas.Top="408" MouseDown="r3_MouseDown"/>
        <Rectangle x:Name="r4" Fill="#FF1F6E1D" Stroke="Black" Width="180" Height="103.5" Canvas.Left="617.5" Canvas.Top="408" MouseDown="r4_MouseDown"/>
    </Canvas>
  </Canvas>

---- C # ----

    private void r1_MouseDown(object sender, MouseButtonEventArgs e1)
    {
        Rect bounds = r1.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r1.ActualWidth, r1.ActualHeight));
        ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2)));
    }

    private void r2_MouseDown(object sender, MouseButtonEventArgs e1)
    {
        Rect bounds = r2.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r2.ActualWidth, r2.ActualHeight));
        ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2)));
    }

    private void r3_MouseDown(object sender, MouseButtonEventArgs e1)
    {
        Rect bounds = r3.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r3.ActualWidth, r3.ActualHeight));
        ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2)));
    }

    private void r4_MouseDown(object sender, MouseButtonEventArgs e1)
    {
        Rect bounds = r4.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r4.ActualWidth, r4.ActualHeight));
        ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width/2), bounds.TopLeft.Y + (bounds.Height/2)));
    }

    public void ZoomInAndPan(double zoomTo, Point translateTarget)
    {
        var group = (ProductCanvas.RenderTransform as TransformGroup);

        var zoomTransform = group.Children[0] as ScaleTransform;
        var translateTransform = group.Children[3] as TranslateTransform;

        Point center = new Point(512, 384);

        destinationPoint.X *= newScale;
        destinationPoint.Y *= newScale;

        var deltaX = center.X - (translateTarget.X);
        var deltaY = center.Y - (translateTarget.Y);

        translateTransform.BeginAnimation(TranslateTransform.XProperty, CreateZoomAnimation(deltaX));
        translateTransform.BeginAnimation(TranslateTransform.YProperty, CreateZoomAnimation(deltaY));

        zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, CreateZoomAnimation(zoomTo));
        zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, CreateZoomAnimation(zoomTo));
    }

    private DoubleAnimation CreateZoomAnimation(double toValue)
    {
        var da = new DoubleAnimation(toValue, new Duration(TimeSpan.FromMilliseconds(700)))
        {
            AccelerationRatio = 0.1,
            DecelerationRatio = 0.9
        };

        return da;
    }

Ответы [ 2 ]

5 голосов
/ 10 марта 2010

Вы говорите о трансформации - кастрюле и шкале.

Вы можете сделать это несколькими способами, но поскольку вы используете WPF, есть ли причина, по которой вы не можете просто использовать RenderTransforms?

var pointClicked = (where user clicked)
var myWindow = (whatever your window is);

myWindow.RenderTransform = new TransformGroup();
var pan = new TranslateTransform(pointClicked.X, pointClicked.Y);
var scale = new ScaleTransform(6.0,6.0);
myWindow.RenderTransform.Children.Add(pan);
myWindow.RenderTransform.Children.Add(scale);

Если вы не хотите идти по этому пути, вам нужно выполнить двумерное преобразование «вручную»: но сначала выполните панорамирование, затем масштаб. Преобразования обычно не являются коммуникативными; вы получите неправильные результаты, если сделаете их в другом порядке.

1 голос
/ 09 марта 2010

Изначально ваш видовой экран имеет значение (0,0), и изображение, и видовой экран имеют размер X по Y. Вы хотите масштабировать размер с некоторым коэффициентом увеличения m, чтобы ваши изображения имели размер m X на m Y, но ваш видовой экран (часть, которую вы показываете) по-прежнему является прямоугольником размера X по Y, расположенным в точке (0,0) на изображении. Так что вам нужно переместить порт просмотра.

Если ваше изображение теперь m X на m Y, вы можете найти средние точки, разделив каждую на две. Затем вы можете вычесть половину размера области просмотра, чтобы получить верхний левый угол. Что-то вроде (m X / 2 - X / 2, m Y / 2 - Y / 2).

...