在Wpf中使用ScrollView和ViewBox缩放到鼠标点 [英] Zooming To Mouse Point With ScrollView and ViewBox in Wpf

查看:111
本文介绍了在Wpf中使用ScrollView和ViewBox缩放到鼠标点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在wpf中有一些绘制到屏幕的路径.使用的坐标非常小,因此已使用视图框将其填充到屏幕上.我现在正在尝试实现平移和缩放功能.我希望能够缩放到鼠标相对于ui的任何位置(即缩放的屏幕中心等于鼠标坐标).当前的结果是,缩放时屏幕的中心位置无法反映鼠标在ui上的确切位置.

I have some paths drawn to the screen in wpf. The coordinates being used are quite small so they have been made to fill the screen with a view box. I am now trying to implement pan and zoom functionality. I would like to be able to zoom to wherever the mouse is in relation to the ui (i.e zoomed screen center is equal to mouse coordinates). The current outcome is that the center of the screen when zoomed is not reflective of the exact mouse position on the ui.

如果您想了解发生了什么... 此处是我当前的解决方案文件.

If you want to see what is happening... Here is my current solution file.

这里有一些代码:

查看Xaml

View Xaml

<Grid Name="MasterGrid" DataContext="{StaticResource mainWindowViewModel}">

    <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" Name="VisualisationScroller">
        <Viewbox Name="VisualisationBox" Stretch="Fill" Loaded="VisualisationBox_Loaded">

            <ItemsControl Name="CustomDrawingElement" ItemsSource="{Binding Trajectories}" Width="{Binding VisualisationWidth}" Height="{Binding VisualisationHeight}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="data:VisualisedTrajectory">
                        <Path Data = "{Binding PathData}" Stroke="Red" StrokeThickness="0.001" Fill="Transparent" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas
                            Background="DarkGray"
                            IsItemsHost="True">
                        </Canvas>

                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.RenderTransform>

                    <TransformGroup>
                        <ScaleTransform ScaleX="1" ScaleY="1" />
                        <TranslateTransform />
                    </TransformGroup>

                </ItemsControl.RenderTransform>

            </ItemsControl>

        </Viewbox>
    </ScrollViewer>
</Grid>

查看模型

View Model

public class MainWindowViewModel : BaseViewModel
{

    public MainWindowViewModel()
    {
        VisualiseRawTrajectories();

    }

    private ObservableCollection<VisualisedTrajectory> _trajectories = new ObservableCollection<VisualisedTrajectory>();
    public ObservableCollection<VisualisedTrajectory> Trajectories
    {
        get { return _trajectories; } 
    }

    #region VisualisationDimensions

    private double _visualisationWidth = 100;
    public double VisualisationWidth
    {
        get { return _visualisationWidth; }
        private set { _visualisationWidth = value; }
    }

    private double _visualisationHeight = 100;
    public double VisualisationHeight
    {
        get { return _visualisationHeight; }
        private set { _visualisationHeight = value; }
    }

    #endregion

    public void VisualiseRawTrajectories()
    {
        var rand = new Random();

        for (int i = 0; i < 5; i++)
        {
            var currentTrajectorySet = new List<Point>(); //each time through reinitialise
            for (int j = 0; j < 5; j++)
            {
                currentTrajectorySet.Add(new Point(rand.NextDouble() * 0.5, rand.NextDouble() * 0.5)); //add a new point with max 0.5
                if(j == 4)
                {
                    currentTrajectorySet.Add(new Point(0.5, 0.5)); //for good measure :)
                    _trajectories.Add(new VisualisedTrajectory(CreatePathData(currentTrajectorySet)));
                }
            }
        }

        VisualisationHeight = 0.5;
        VisualisationWidth = 0.5; //just for demonstration purposes
        OnPropertyChanged("VisualisationHeight");
        OnPropertyChanged("VisualisationWidth");

    }

    private Geometry CreatePathData(IList<Point> points)
    {
        var geometry = new StreamGeometry {FillRule = FillRule.EvenOdd};
        using (StreamGeometryContext ctx = geometry.Open())
        {
            ctx.BeginFigure(points[0], false, false); //use the first index
            ctx.PolyLineTo(points, true, true);
        }
        return (Geometry)geometry.GetAsFrozen(); 
    }

}

查看背后的代码

View Code Behind

public MainWindow()
    {
        InitializeComponent();
        VisualisationScroller.PreviewMouseWheel += OnPreviewMouseWheel;
    }

    private Point originalDimensions;
    private void VisualisationBox_Loaded(object sender, RoutedEventArgs e)
    {
        Viewbox viewBox = sender as Viewbox;
        viewBox.Width = viewBox.ActualWidth;
        viewBox.Height = viewBox.ActualHeight;
        originalDimensions = new Point(viewBox.ActualWidth, viewBox.ActualHeight);

    }


    #region Zoom

    private int _numberDrawnItems = 0;
    private void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var zoomScale = new Point(CustomDrawingElement.RenderTransform.Value.M11,
                                  CustomDrawingElement.RenderTransform.Value.M22); //gets the scale x and scale y


        if (CustomDrawingElement != null && _numberDrawnItems != CustomDrawingElement.Items.Count) //if there was something draw to screen
        {
            _numberDrawnItems = CustomDrawingElement.Items.Count;
            CustomDrawingElement.RenderTransformOrigin = new Point(0.5, 0.5); //if not set zoom from center
        }
        if (e.Delta > 0)
        {
            if (CustomDrawingElement != null)
            {

                VisualisationBox.Width = originalDimensions.X * (zoomScale.X + 1);
                VisualisationBox.Height = originalDimensions.Y * (zoomScale.Y + 1);


                var mousePosition = e.GetPosition(MasterGrid);
                CustomDrawingElement.RenderTransformOrigin = new Point(mousePosition.X / MasterGrid.ActualWidth, mousePosition.Y / MasterGrid.ActualHeight);
                CustomDrawingElement.RenderTransform = new MatrixTransform(zoomScale.X + 1, 0, 0, zoomScale.Y + 1, 0, 0);


            }
        }
        if (e.Delta < 0)
        {
            if (zoomScale.X > 1 && zoomScale.Y > 1) //stops you from zooming out too much
            {
                if (CustomDrawingElement != null)
                {

                    VisualisationBox.Width = VisualisationBox.Width - originalDimensions.X;
                    VisualisationBox.Height = VisualisationBox.Height - originalDimensions.Y;

                    CustomDrawingElement.RenderTransform = new MatrixTransform(zoomScale.X - 1, 0, 0, zoomScale.Y - 1, 0, 0);


                }
            }
        }

        e.Handled = true;
    }

    #endregion //Zooming code


}

推荐答案

解决了它更改了将视图缩放到以下位置的后代码:

Solved it changed the back code for zooming the View to:

if (e.Delta > 0)
        {
            if (CustomDrawingElement != null)
            {
                //zoom

                _zoomScale++; //increase it now that we have zoomed
                VisualisationBox.Width = _originalDimensions.X * (_zoomScale);
                VisualisationBox.Height = _originalDimensions.Y * (_zoomScale);

                ScrollerDimensions.Content = VisualisationScroller.ActualWidth + "x" + VisualisationScroller.ActualHeight;
                BoxDimensions.Content = VisualisationBox.ActualWidth + "x" + VisualisationBox.ActualHeight;

                var mousePosition = e.GetPosition(MasterGrid);
                mousePosition = MasterGrid.TransformToVisual(VisualisationBox).Transform(mousePosition);

                ScrolledPoint.Content = mousePosition.X + "," + mousePosition.Y;
                VisualisationScroller.ScrollToHorizontalOffset(mousePosition.X);
                VisualisationScroller.ScrollToVerticalOffset(mousePosition.Y);

            }
        }
        if (e.Delta < 0)
        {
            if (_zoomScale > 1) //stops you from zooming out too much
            {
                if (CustomDrawingElement != null)
                {
                    var mousePosition = e.GetPosition(MasterGrid);

                    _zoomScale -= 1; //decrease the zoom
                    VisualisationBox.Width = VisualisationBox.Width - _originalDimensions.X;
                    VisualisationBox.Height = VisualisationBox.Height - _originalDimensions.Y;
                    mousePosition = MasterGrid.TransformToVisual(VisualisationBox).Transform(mousePosition);
                    mousePosition = new Point(mousePosition.X - _originalDimensions.X, mousePosition.Y - _originalDimensions.Y);

                    VisualisationScroller.ScrollToHorizontalOffset(mousePosition.X);
                    VisualisationScroller.ScrollToVerticalOffset(mousePosition.Y);
                }
            }
        }

        e.Handled = true;

如果有人感兴趣,请这里完成解决方案文件也实现了平移.

If anyone is interested HERE is the finished solution file with panning implemented too.

这篇关于在Wpf中使用ScrollView和ViewBox缩放到鼠标点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆