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             canvas1.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
 31             canvas1.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
 32             canvas1.Background = Brushes.Transparent;//.Cyan;
 33 
 34 
 35             DrawingLine(new Point(100, 100), new Point(300, 200));
 36             DrawingLine(new Point(100, 200), new Point(300, 100));
 37         }
 38 
 39         protected void DrawingLine(Point startPt, Point endPt)
 40         {
 41             LineGeometry myLineGeometry = new LineGeometry();
 42             myLineGeometry.StartPoint = startPt;
 43             myLineGeometry.EndPoint = endPt;
 44 
 45             Path myPath = new Path();
 46             myPath.Stroke = Brushes.Black;
 47             myPath.StrokeThickness = 1;
 48             myPath.Data = myLineGeometry;
 49 
 50             canvas1.Children.Add(myPath);
 51         }
 52 
 53         private void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 54         {           
 55             startMovePosition = e.GetPosition((Canvas)sender);
 56             isMoving = true;
 57         }
 58 
 59         private void canvas1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
 60         {
 61             isMoving = false;
 62             Point endMovePosition = e.GetPosition((Canvas)sender);
 63 
 64             //为了避免跳跃式的变换,单次有效变化 累加入 totalTranslate中。           
 65             totalTranslate.X += (endMovePosition.X - startMovePosition.X)/scaleLevel;
 66             totalTranslate.Y += (endMovePosition.Y - startMovePosition.Y)/scaleLevel;           
 67         }
 68 
 69         private void canvas1_MouseMove(object sender, MouseEventArgs e)
 70         {
 71             if (isMoving)
 72             {
 73                 Point currentMousePosition = e.GetPosition((Canvas)sender);//当前鼠标位置
 74                 
 75                 Point deltaPt = new Point(0, 0);               
 76                 deltaPt.X = (currentMousePosition.X - startMovePosition.X) /scaleLevel;                
 77                 deltaPt.Y = (currentMousePosition.Y - startMovePosition.Y) /scaleLevel;
 78                 
 79                 tempTranslate.X = totalTranslate.X + deltaPt.X;
 80                 tempTranslate.Y = totalTranslate.Y + deltaPt.Y;
 81 
 82                 adjustGraph();
 83             }
 84         }        
 85         
 86         private void canvas1_MouseWheel(object sender, MouseWheelEventArgs e)
 87         {
 88             Point scaleCenter = e.GetPosition((Canvas)sender);
 89 
 90             if (e.Delta > 0)
 91             {
 92                 scaleLevel *= 1.08;
 93             }
 94             else
 95             {
 96                 scaleLevel /= 1.08;
 97             }
 98             //Console.WriteLine("scaleLevel: {0}", scaleLevel);
 99 
100             totalScale.ScaleX = scaleLevel;
101             totalScale.ScaleY = scaleLevel;
102             totalScale.CenterX = scaleCenter.X;
103             totalScale.CenterY = scaleCenter.Y;
104 
105             adjustGraph();
106         }
107        
108         private void adjustGraph()
109         {
110             TransformGroup tfGroup = new TransformGroup();
111             tfGroup.Children.Add(tempTranslate);
112             tfGroup.Children.Add(totalScale);
113 
114             foreach (UIElement ue in canvas1.Children)
115             {
116                 ue.RenderTransform = tfGroup;
117             }
118         }
119 
120     }
121 }

 

变量说明:

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

        TranslateTransform totalTranslate = new TranslateTransform();//多次操作中需要对总的移动量进行统计。        
        ScaleTransform totalScale = new ScaleTransform();//缩放变量
        Double scaleLevel = 1;//缩放的级别

函数功能说明:
DrawingLine 在指定的Canvas控件中画线,用于测试。
鼠标按下时,记录起始移动的位置点,标记拖动操作开始 isMoving = true。
鼠标移动过程中,将有效的移动距离记录到总移动变量 totalTranslate 当中,并对位置进行刷新
鼠标滚轮变化时,根据滚轮方向调整
缩放级别。

不同缩放级别下,屏幕中移动相同的距离,对于Canvs内的图形来说距离不同,因此需要对鼠标移动的距离进行修正,即将移动距离除以缩放级别,这样可以得到相对精确的移动位置。

遗留问题:
1、连续在不同位置进行缩放时,仍会有较小的抖动,细节处理上还有瑕疵。
2、使用下面的语句,可以实现canvas1自动缩放(将canvas1的宽度与高度设为Auto)。
canvas1.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
canvas1.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;



学习太辛苦,采购点东西鼓励一下自己,微信扫描二维码,“香雪杂货店”欢迎您的到来,遇到喜欢的东西尽管带走~~


posted @ 2017-12-16 20:02  刘崇军  阅读(12021)  评论(2编辑  收藏  举报