標籤:false str font 素材 調整 很多 zed 相關 protected
從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 else104 {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不能同時放大,請各位高手幫忙指點一下,謝謝!
WPF 中Canvas圖形移動、縮放代碼