瀏覽代碼

Implement basic ZoomBox

Equbuxu 4 年之前
父節點
當前提交
fc6a50224e

+ 12 - 8
PixiEditor/Views/UserControls/MainDrawingPanel.xaml

@@ -4,19 +4,23 @@
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:local="clr-namespace:PixiEditor.Views"
+             xmlns:userc="clr-namespace:PixiEditor.Views.UserControls"
              xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
              xmlns:helpers="clr-namespace:PixiEditor.Helpers"
              xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
              mc:Ignorable="d" PreviewMouseDown="MainDrawingPanel_PreviewMouseDown" PreviewMouseUp="MainDrawingPanel_PreviewMouseUp"
              d:DesignHeight="450" d:DesignWidth="800" x:Name="mainDrawingPanel" PreviewMouseWheel="Zoombox_MouseWheel">
-    <xctk:Zoombox PreviewMouseDown="Zoombox_PreviewMouseDown" Cursor="{Binding Cursor}" Name="Zoombox" KeepContentInBounds="False"
+    <Grid>
+        <userc:ZoomBox/>
+        <xctk:Zoombox PreviewMouseDown="Zoombox_PreviewMouseDown" Cursor="{Binding Cursor}" Name="Zoombox" KeepContentInBounds="False" Visibility="Hidden"
                   Loaded="Zoombox_Loaded" IsAnimated="False" MouseDown="Zoombox_MouseDown"
                   CurrentViewChanged="Zoombox_CurrentViewChanged" DragModifiers="Blocked" ZoomModifiers="None">
-        <i:Interaction.Triggers>
-            <i:EventTrigger EventName="MouseMove">
-                <i:InvokeCommandAction Command="{Binding MouseMoveCommand, ElementName=mainDrawingPanel, Mode=OneWay}" />
-            </i:EventTrigger>
-        </i:Interaction.Triggers>
-        <ContentPresenter Content="{Binding Item, ElementName=mainDrawingPanel}" />
-    </xctk:Zoombox>
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="MouseMove">
+                    <i:InvokeCommandAction Command="{Binding MouseMoveCommand, ElementName=mainDrawingPanel, Mode=OneWay}" />
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+            <ContentPresenter Content="{Binding Item, ElementName=mainDrawingPanel}" />
+        </xctk:Zoombox>
+    </Grid>
 </UserControl>

+ 19 - 0
PixiEditor/Views/UserControls/ZoomBox.xaml

@@ -0,0 +1,19 @@
+<ContentControl x:Class="PixiEditor.Views.UserControls.ZoomBox"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800">
+    <Canvas MouseDown="OnMouseDown" MouseUp="OnMouseUp" MouseMove="OnMouseMove" MouseWheel="OnScroll" x:Name="mainCanvas">
+        <Grid x:Name="mainGrid">
+            <Grid.LayoutTransform>
+                <ScaleTransform x:Name="scaleTransform"/>
+            </Grid.LayoutTransform>
+            <Border Background="White" BorderThickness="2" BorderBrush="Aquamarine" Width="200" Height="100">
+                <TextBlock>Test!</TextBlock>
+            </Border>
+        </Grid>
+    </Canvas>
+</ContentControl>

+ 103 - 0
PixiEditor/Views/UserControls/ZoomBox.xaml.cs

@@ -0,0 +1,103 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace PixiEditor.Views.UserControls
+{
+    /// <summary>
+    /// Interaction logic for ZoomBox.xaml
+    /// </summary>
+    public partial class ZoomBox : ContentControl
+    {
+        private bool captured = false;
+        private Point prevMousePos;
+
+        private Point backingSpaceOriginPos;
+        private Point SpaceOriginPos
+        {
+            get => backingSpaceOriginPos;
+            set
+            {
+                backingSpaceOriginPos = value;
+                Canvas.SetLeft(mainGrid, backingSpaceOriginPos.X);
+                Canvas.SetTop(mainGrid, backingSpaceOriginPos.Y);
+            }
+        }
+
+        private int backingZoomPower;
+        private int ZoomPower
+        {
+            get => backingZoomPower;
+            set
+            {
+                backingZoomPower = value;
+                var mult = Zoom;
+                scaleTransform.ScaleX = mult;
+                scaleTransform.ScaleY = mult;
+            }
+        }
+        private double Zoom => Math.Pow(1.1, backingZoomPower);
+
+        public ZoomBox()
+        {
+            InitializeComponent();
+        }
+
+        private void OnMouseDown(object sender, MouseButtonEventArgs e)
+        {
+            mainCanvas.CaptureMouse();
+            captured = true;
+            prevMousePos = e.GetPosition(mainCanvas);
+        }
+
+        private void OnMouseUp(object sender, MouseButtonEventArgs e)
+        {
+            mainCanvas.ReleaseMouseCapture();
+            captured = false;
+            prevMousePos = e.GetPosition(mainCanvas);
+        }
+
+        private void OnMouseMove(object sender, MouseEventArgs e)
+        {
+            if (!captured)
+                return;
+            var curMousePos = e.GetPosition(mainCanvas);
+            SpaceOriginPos += curMousePos - prevMousePos;
+
+            prevMousePos = e.GetPosition(mainCanvas);
+        }
+
+        private Point ToScreenSpace(Point p)
+        {
+            double zoom = Zoom;
+            p.X /= zoom;
+            p.Y /= zoom;
+            p.X += SpaceOriginPos.X;
+            p.Y += SpaceOriginPos.Y;
+            return p;
+        }
+
+        private Point ToZoomboxSpace(Point mousePos)
+        {
+            double zoom = Zoom;
+            mousePos.X -= SpaceOriginPos.X;
+            mousePos.Y -= SpaceOriginPos.Y;
+            mousePos.X *= zoom;
+            mousePos.Y *= zoom;
+            return mousePos;
+        }
+
+        private void OnScroll(object sender, MouseWheelEventArgs e)
+        {
+            var oldMousePos = e.GetPosition(mainCanvas);
+            var oldZoomboxMousePos = ToZoomboxSpace(oldMousePos);
+
+            ZoomPower += e.Delta / 100;
+
+            var shiftedMousePos = ToScreenSpace(oldZoomboxMousePos);
+            var deltaMousePos = oldMousePos - shiftedMousePos;
+            SpaceOriginPos = SpaceOriginPos - deltaMousePos;
+        }
+    }
+}