Панорамирование и Изображение Масштабирования

Мне кажется, что вы не хотите использовать 2D-массив. Вместо этого вы хотите использовать один массив и обращаться к нему, как если бы он был 2D-массивом. Это правильно?

Это означает, что вам нужно применить простую математику к вашей задаче.

Исходя из вашего описания, ваша 2D-таблица имеет одинаковую высоту и ширину, поэтому height = width.

Если вы хотите получить индекс

index = column + width * row

Если вы хотите получить x и y на основе индекса:

column = index % width;
row = index / width;

Примечание: я не тестировал это как код еще. Кроме того, дайте мне знать, если это помогло.

123
задан ASh 24 October 2019 в 12:37
поделиться

8 ответов

Я решил эту проблему, поместив изображение в рамку с его свойством ClipToBounds, установленным в True. RenderTransformOrigin на изображении затем устанавливается на 0,5,0,5, поэтому изображение начнет масштабироваться по центру изображения. Для RenderTransform также устанавливается TransformGroup, содержащая ScaleTransform и TranslateTransform.

Затем я обработал событие MouseWheel на изображении для реализации масштабирования

private void image_MouseWheel(object sender, MouseWheelEventArgs e)
{
    var st = (ScaleTransform)image.RenderTransform;
    double zoom = e.Delta > 0 ? .2 : -.2;
    st.ScaleX += zoom;
    st.ScaleY += zoom;
}

Для обработки панорамирования первое, что я сделал, было обработало событие MouseLeftButtonDown на событии Чтобы сохранить изображение и записать его местоположение, я также сохраняю текущее значение TranslateTransform, которое обновляется для реализации панорамирования.

Point start;
Point origin;
private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    image.CaptureMouse();
    var tt = (TranslateTransform)((TransformGroup)image.RenderTransform)
        .Children.First(tr => tr is TranslateTransform);
    start = e.GetPosition(border);
    origin = new Point(tt.X, tt.Y);
}

Затем я обработал событие MouseMove, чтобы обновить TranslateTransform.

private void image_MouseMove(object sender, MouseEventArgs e)
{
    if (image.IsMouseCaptured)
    {
        var tt = (TranslateTransform)((TransformGroup)image.RenderTransform)
            .Children.First(tr => tr is TranslateTransform);
        Vector v = start - e.GetPosition(border);
        tt.X = origin.X - v.X;
        tt.Y = origin.Y - v.Y;
    }
}

Наконец, don ' не забудьте отпустить захват мыши.

private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    image.ReleaseMouseCapture();
}

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

110
ответ дан 24 November 2019 в 01:11
поделиться

Мой образец London Underground делает это, хотя с картой, а не со статическим изображением.

1
ответ дан 21 September 2019 в 04:25
поделиться
  • Панорамирование: поместите изображение внутрь холста. Реализуйте события Mouse Up, Down и Move для перемещения свойств Canvas.Top, Canvas.Left. Когда вниз, вы помечаете isDraggingFlag в true, когда вверх, вы устанавливаете флаг в false. На ходу вы проверяете, установлен ли флаг, если вы смещаете свойства Canvas.Top и Canvas.Left на изображении внутри холста.
  • Масштаб: Привязка ползунка к масштабному преобразованию холста
  • Показать наложения: добавьте дополнительные холсты без фона поверх холста, содержащего изображение.
  • показать исходное изображение: управление изображением внутри ViewBox
9
ответ дан 24 November 2019 в 01:11
поделиться

Попробуйте этот элемент управления масштабированием: http://wpfextensions.codeplex.com

Использование элемента управления очень просто, ссылка на сборку wpfextensions:

<wpfext:ZoomControl>
    <Image Source="..."/>
</wpfext:ZoomControl>

Полосы прокрутки не поддерживается в данный момент. (Это будет в следующем выпуске, который будет доступен через одну или две недели).

10
ответ дан 24 November 2019 в 01:11
поделиться

Ответ был опубликован выше, но не был полным. вот завершенная версия:

XAML

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MapTest.Window1"
x:Name="Window"
Title="Window1"
Width="1950" Height="1546" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Controls="clr-namespace:WPFExtensions.Controls;assembly=WPFExtensions" mc:Ignorable="d" Background="#FF000000">

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="52.92"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Border Grid.Row="1" Name="border">
        <Image Name="image" Source="map3-2.png" Opacity="1" RenderTransformOrigin="0.5,0.5"  />
    </Border>

</Grid>

Code Behind

using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace MapTest
{
    public partial class Window1 : Window
    {
        private Point origin;
        private Point start;

        public Window1()
        {
            InitializeComponent();

            TransformGroup group = new TransformGroup();

            ScaleTransform xform = new ScaleTransform();
            group.Children.Add(xform);

            TranslateTransform tt = new TranslateTransform();
            group.Children.Add(tt);

            image.RenderTransform = group;

            image.MouseWheel += image_MouseWheel;
            image.MouseLeftButtonDown += image_MouseLeftButtonDown;
            image.MouseLeftButtonUp += image_MouseLeftButtonUp;
            image.MouseMove += image_MouseMove;
        }

        private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            image.ReleaseMouseCapture();
        }

        private void image_MouseMove(object sender, MouseEventArgs e)
        {
            if (!image.IsMouseCaptured) return;

            var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
            Vector v = start - e.GetPosition(border);
            tt.X = origin.X - v.X;
            tt.Y = origin.Y - v.Y;
        }

        private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            image.CaptureMouse();
            var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
            start = e.GetPosition(border);
            origin = new Point(tt.X, tt.Y);
        }

        private void image_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            TransformGroup transformGroup = (TransformGroup) image.RenderTransform;
            ScaleTransform transform = (ScaleTransform) transformGroup.Children[0];

            double zoom = e.Delta > 0 ? .2 : -.2;
            transform.ScaleX += zoom;
            transform.ScaleY += zoom;
        }
    }
}

У меня есть пример полного проекта wpf с использованием этого кода на моем веб-сайте: Запишите приложение для заметок .

43
ответ дан 24 November 2019 в 01:11
поделиться

Чтобы получить профессиональный элемент управления масштабированием для WPF, ознакомьтесь с ZoomPanel .

Он не бесплатный, но очень прост в использовании и имеет множество функций - анимированное масштабирование и панорамирование, поддержка ScrollViewer, поддержка колеса мыши, включенный ZoomController (с перемещением, увеличением, уменьшением, масштабированием прямоугольника, кнопками сброса) . Он также поставляется с множеством примеров кода.

1
ответ дан 24 November 2019 в 01:11
поделиться

Все, что вам нужно для масштабирования относительно положения мыши, это:

var position = e.GetPosition(image1);
image1.RenderTransformOrigin = new Point(position.X / image1.ActualWidth, position.Y / image1.ActualHeight);
2
ответ дан 24 November 2019 в 01:11
поделиться

@Anothen и @ Number8 - Класс Vector недоступен в Silverlight, поэтому для его работы нам просто нужно сохранить запись последней обнаруженной позиции последний раз, когда было вызвано событие MouseMove, и сравните две точки, чтобы найти разницу; затем настройте преобразование.

XAML:

    <Border Name="viewboxBackground" Background="Black">
            <Viewbox Name="viewboxMain">
                <!--contents go here-->
            </Viewbox>
    </Border>  

Код программной части:

    public Point _mouseClickPos;
    public bool bMoving;


    public MainPage()
    {
        InitializeComponent();
        viewboxMain.RenderTransform = new CompositeTransform();
    }

    void MouseMoveHandler(object sender, MouseEventArgs e)
    {

        if (bMoving)
        {
            //get current transform
            CompositeTransform transform = viewboxMain.RenderTransform as CompositeTransform;

            Point currentPos = e.GetPosition(viewboxBackground);
            transform.TranslateX += (currentPos.X - _mouseClickPos.X) ;
            transform.TranslateY += (currentPos.Y - _mouseClickPos.Y) ;

            viewboxMain.RenderTransform = transform;

            _mouseClickPos = currentPos;
        }            
    }

    void MouseClickHandler(object sender, MouseButtonEventArgs e)
    {
        _mouseClickPos = e.GetPosition(viewboxBackground);
        bMoving = true;
    }

    void MouseReleaseHandler(object sender, MouseButtonEventArgs e)
    {
        bMoving = false;
    }

Также обратите внимание, что вам не нужны TransformGroup или коллекция для реализации панорамирования и масштабирования; вместо этого CompositeTransform сделает это с меньшими хлопотами.

Я почти уверен, что это действительно неэффективно с точки зрения использования ресурсов, но, по крайней мере, это работает :)

4
ответ дан 24 November 2019 в 01:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: