首页 文章

使用Wpf中的ScrollView和ViewBox缩放到鼠标点

提问于
浏览
3

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

如果你想看看发生了什么...... Here is my current solution file .

要么

下面是一些代码:

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


}

1 回答

  • 4

    解决了它改变后面的代码,将视图缩放为:

    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;
    

    如果有人有兴趣HERE也是完成的解决方案文件,也实现了平移 .

相关问题