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