热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印。只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线、画矩形等基础形状的代码,移动和缩放说的并不清

从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     /// 
 11     /// MainWindow.xaml 的交互逻辑
 12     /// 
 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;



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

推荐阅读
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文讨论了如何在dotnet桌面(Windows)应用程序中添加图标。作者提到可以使用dotnet命令行工具与resource.rc文件一起使用来为标准.NET核心应用程序添加图标。作者还介绍了在创建控制台应用程序时如何编辑projeto1.csproj文件来添加图标。 ... [详细]
author-avatar
爱-雨轩_627
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有