WPF 中Canvas图形移动、缩放代码

从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印。

只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线、画矩形等基础形状的代码,移动和缩放说的并不清晰,只能自己努力来解决一下。

素材准备:

WPF项目的屏幕上放一个Canvas控件,名称为canvas1。

代码如下:

  1 using System;
  2 using System.Windows;
  3 using System.Windows.Media;
  4 using System.Windows.Input;
  5 using System.Windows.Shapes;
  6 using System.Windows.Controls;
  7
  8 namespace WpfcanvasDrawing
  9 {
 10     /// <summary>
 11     /// MainWindow.xaml 的交互逻辑
 12     /// </summary>
 13     public partial class MainWindow : Window
 14     {
 15         //移动标志
 16         bool isMoving = false;
 17         //鼠标按下去的位置
 18         Point startMovePosition;
 19
 20         TranslateTransform totalTranslate = new TranslateTransform();
 21         TranslateTransform tempTranslate = new TranslateTransform();
 22         ScaleTransform totalScale = new ScaleTransform();
 23         Double scaleLevel = 1;
 24
 25         public MainWindow()
 26         {
 27             InitializeComponent();
 28
 29             canvas1.Focusable = true;//重要:默认条件下不接收鼠标事件
 30
 31             DrawingLine(new Point(100, 100), new Point(300, 200));
 32             DrawingLine(new Point(100, 200), new Point(300, 100));
 33         }
 34
 35         private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
 36         {
 37             //问题一:点击窗口最大化按钮时未能改变Canvas尺寸
 38             //if (this.WindowState == WindowState.Maximized) {}
 39             canvas1.Width = this.Width;
 40             canvas1.Height = this.Height;
 41
 42         }
 43
 44         protected void DrawingLine(Point startPt, Point endPt)
 45         {
 46             LineGeometry myLineGeometry = new LineGeometry();
 47             myLineGeometry.StartPoint = startPt;
 48             myLineGeometry.EndPoint = endPt;
 49
 50             Path myPath = new Path();
 51             myPath.Stroke = Brushes.Black;
 52             myPath.StrokeThickness = 1;
 53             myPath.Data = myLineGeometry;
 54
 55             canvas1.Children.Add(myPath);
 56         }
 57
 58         private void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 59         {
 60             // code A:
 61             //FrameworkElement element = sender as FrameworkElement;
 62             //startMovePosition = e.GetPosition(element);
 63             // code B:
 64             startMovePosition = e.GetPosition((Canvas)sender);
 65             isMoving = true;
 66         }
 67
 68         private void canvas1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
 69         {
 70             isMoving = false;
 71             Point endMovePosition = e.GetPosition((Canvas)sender);
 72
 73             //为了避免跳跃式的变换,单次有效变化 累加入 totalTranslate中。
 74             totalTranslate.X += (endMovePosition.X - startMovePosition.X)/scaleLevel;
 75             totalTranslate.Y += (endMovePosition.Y - startMovePosition.Y)/scaleLevel;
 76         }
 77
 78         private void canvas1_MouseMove(object sender, MouseEventArgs e)
 79         {
 80             if (isMoving)
 81             {
 82                 Point currentMousePosition = e.GetPosition((Canvas)sender);//当前鼠标位置
 83
 84                 Point deltaPt = new Point(0, 0);
 85                 deltaPt.X = (currentMousePosition.X - startMovePosition.X) /scaleLevel;
 86                 deltaPt.Y = (currentMousePosition.Y - startMovePosition.Y) /scaleLevel;
 87
 88                 tempTranslate.X = totalTranslate.X + deltaPt.X;
 89                 tempTranslate.Y = totalTranslate.Y + deltaPt.Y;
 90
 91                 adjustGraph();
 92             }
 93         }
 94
 95         private void canvas1_MouseWheel(object sender, MouseWheelEventArgs e)
 96         {
 97             Point scaleCenter = e.GetPosition((Canvas)sender);
 98
 99             if (e.Delta > 0)
100             {
101                 scaleLevel *= 1.08;
102             }
103             else
104             {
105                 scaleLevel /= 1.08;
106             }
107             //Console.WriteLine("scaleLevel: {0}", scaleLevel);
108
109             totalScale.ScaleX = scaleLevel;
110             totalScale.ScaleY = scaleLevel;
111             totalScale.CenterX = scaleCenter.X;
112             totalScale.CenterY = scaleCenter.Y;
113
114             adjustGraph();
115         }
116
117         private void adjustGraph()
118         {
119             TransformGroup tfGroup = new TransformGroup();
120             tfGroup.Children.Add(tempTranslate);
121             tfGroup.Children.Add(totalScale);
122
123             foreach (UIElement ue in canvas1.Children)
124             {
125                 ue.RenderTransform = tfGroup;
126             }
127         }
128
129     }
130 }

变量说明:

     //移动标志
        bool isMoving = false;
        //鼠标按下去的位置
        Point startMovePosition;

        TranslateTransform totalTranslate = new TranslateTransform();//多次操作中需要对总的移动量进行统计。
        TranslateTransform tempTranslate = new TranslateTransform();//单次移动过程中根据鼠标位置实时更新。
        ScaleTransform totalScale = new ScaleTransform();//缩放变量
        Double scaleLevel = 1;//缩放的级别

函数功能说明:DrawingLine 在指定的Canvas控件中画线,用于测试。Window_SizeChanged  屏幕大小变更时,调整Canvas的大小。
鼠标按下时,记录起始移动的位置点,标记拖动操作开始 isMoving = true。鼠标移动过程中,对位置进行刷新,使用临时变量 tempTranslate 记录当前移动的距离。鼠标抬起过程中,将有效的移动距离记录到总移动变量 totalTranslate 当中。鼠标滚轮变化时,根据滚轮方向调整缩放级别。不同缩放级别下,屏幕中移动相同的距离,对于Canvs内的图形来说距离不同,因此需要对鼠标移动的距离进行修正,即将移动距离除以缩放级别,这样可以得到相对精确的移动位置。

遗留问题:1、缩放后移动时,仍会有较小的抖动,细节处理上还有瑕疵。2、窗口最大化按钮点击后,无法捕获相关事件,导致canvas1不能同时放大,请各位高手帮忙指点一下,谢谢!
时间: 2024-08-07 05:05:01

WPF 中Canvas图形移动、缩放代码的相关文章

WPF中C#代码触发鼠标点击事件

1.如下代码; 1 <Button x:Name="btnTest" Click="btnTest_Click"> 2 <Button.Triggers> 3 <EventTrigger RoutedEvent="Button.Click"> 4 <BeginStoryboard> 5 <!--要执行的动画代码--> 6 </BeginStoryboard> 7 </E

在WPF中绘制多维数据集

原文 https://stuff.seans.com/2008/08/13/drawing-a-cube-in-wpf/ 是时候使用WPF绘制一个简单的3D对象了.作为WPF中3D图形的快速介绍,让我们只渲染一个最简单的对象 - 一个立方体. 在这个例子中,我将直接在XAML中定义我们需要的所有内容.与WPF中的其他内容一样,我们可以直接在代码中完成所有这些操作.但是在XAML中定义所有内容更加清晰,因为它使对象层次结构更加明显.在实际项目中,您显然会在代码中执行此操作,例如创建或加载3D网格(

WPF中的换行符

原文:WPF中的换行符 WPF中UI上和后台代码中的换行符不同. 其中: XAML中为 C#代码中为 \r\n 或者: Environment.NewLine 版权声明:本文为博主原创文章,未经博主允许不得转载.

wpf中的换行符(转)

WPF中UI上和后台代码中的换行符不同. 其中: XAML中为 C#代码中为 \r\n 或者: Environment.NewLine

WPF中的数据绑定!!!

引用自:https://msdn.microsoft.com/zh-cn/magazine/cc163299.aspx 数据点: WPF 中的数据绑定 数据点 WPF 中的数据绑定 John Papa 代码下载位置: DataPoints2007_12.exe (161 KB) Browse the Code Online   目录 数据绑定细节 创建简单的绑定 绑定模式 绑定的时间 绑定到 XML 对象绑定和 DataTemplates 对数据进行排序 欢迎试用和反馈 到目前为止,很多人都知道

二维图形的矩阵变换(三)——在WPF中的应用矩阵变换

UIElement和RenderTransform 首先,我们来看看什么样的对象可以进行变换.在WPF中,用于呈现给用户的对象的基类为Visual类,但是Visual对象并不具有变换功能,具有变换功能的是它的子类UIElement.这个类也是非常底层的类了,几乎我们所有的常用控件都是继承自它,也就是说,基本上所有的UI对象都是可以应用变换的. 然后,我们在再来看看UIElement中变换种类.UIElement支持两种变换:RenderTransform和LayoutTransform,其中La

二维图形的矩阵变换(二)——WPF中的矩阵变换基础

在前文二维图形的矩阵变换(一)——基本概念中已经介绍过二维图像矩阵变换的一些基础知识,本文中主要介绍一下如何在WPF中进行矩阵变换. Matrix结构 在WPF中,用Matrix结构(struct类型)表示二维变换矩阵,它是一个3*3的数组,结构如下, 由于第三列是常量0,0,1,因此并不作为公开属性,可见的只有剩余六个属性. 构造变换 虽然Matrix类公开了这六个属性让我们设置,但是靠直接设置这六个属性来实现平移.旋转等变换对于我们来说实在太困难了,因此又增加了如下许多函数来帮助我们实现这一

WPF中通过代码设置控件的坐标

用WPF做贪吃蛇小游戏时,发现了一个问题: 贪吃蛇的移动,我是通过不断刷新Rectangle来实现(贪吃蛇的身体由一组Rectangle组成),因此需要不断调整Rectangle的坐标,但是WPF中没有Location的相关设置 在网上查到可以用Thickness实现 Rectangle Rec = new Rectangle(); Rec.Margin = new Thickness(1, 2, 3, 4); 但总是调不准 其实可以通过Canvas实现 Canvas介绍 用代码实现Canvas

在WPF中,如何得到任何Object对象的XAML代码?

原文:在WPF中,如何得到任何Object对象的XAML代码? 在WPF中,可以使用System.Windows.Markup.XamlWriter.Save(objName)得到任何Object对象的XAML代码. 这里举个例子,然后来比较一下:XAML代码:// Window1.xaml<Window x:Class="XamlWriter.Window1"??? xmlns="http://schemas.microsoft.com/winfx/2006/xaml