WPF使用Canvas绘制可变矩形

简介: 原文:WPF使用Canvas绘制可变矩形 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WANGYAN9110/article/details/38130661 1、问题以及解决办法 最近因为项目需要,需要实现一个位置校对的功能,大致的需求如下:有一个图片,有一些位置信息,但是位置信息可能和实际有些偏差,需要做简单调整,后面会对这张图片进行切割等,做些处理。
原文: WPF使用Canvas绘制可变矩形

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WANGYAN9110/article/details/38130661

1、问题以及解决办法

最近因为项目需要,需要实现一个位置校对的功能,大致的需求如下:有一个图片,有一些位置信息,但是位置信息可能和实际有些偏差,需要做简单调整,后面会对这张图片进行切割等,做些处理。(位置信息连接起来是一个个小矩形。)

解决以上问题的大致思路如下:使用canvas进行绘制,把图片作为canvas的背景,在canvas上绘制矩形,类似于qq截图一样,矩形框可以使用鼠标拖动调整大小。然后在记下修改后的位置,提供给后面切割图片使用。目前的关键问题就是实现类似qq截图那样可以拖动的矩形

2、实现的效果预览


以上是实现的demo的效果。主要由定位点和连线组成。

3、可变矩形实现

  1. 定位点
    定位点主要用于描述在矩形上的小方框,鼠标拖动的事件就是由它触发,它位置的移动会联动相关线的移动。


定位点主要是定位点的一些基本属性和基本方法,主要包括绘制方法,移动方法。
其中:AnchorPointType为定位点的类型;

    public enum AnchorPointType
    {
        /// <summary>
        /// 上下
        /// </summary>
        NS,
        /// <summary>
        /// 左右
        /// </summary>
        WE,
        /// <summary>
        /// 右上
        /// </summary>
        NE,
        /// <summary>
        /// 左下
        /// </summary>
        SW,
        /// <summary>
        /// 右下
        /// </summary>
        NW,
        /// <summary>
        /// 左上
        /// </summary>
        SE
    }

draw()方法用于绘制矩形:

        public Rectangle Draw() 
        {
            double offset = this.Width / 2;
            Rectangle retc = new Rectangle()
            {
                Margin = new Thickness(this.X - offset, this.Y - offset, 0, 0),
                Width = this.Width,
                Height = this.Height,
                Fill = Brushes.LightGoldenrodYellow,
                Stroke = Brushes.Black,
                StrokeThickness = 1,
                DataContext = this.Key
            };
            this.retc = retc;
            return retc;
        }

move()方法用户改变定位点位置

        public void Move(double x,double y)
        {
            double offset = this.Width / 2;
            this.retc.Margin = new Thickness(x-offset,y-offset,0,0);
            this.X = x;
            this.Y = y;
        }
  1. 可变矩形
    这部分主要实现绘制矩形功能,主要代码如下:
        public void Init()
         {
             //按x轴分类
             IEnumerable<IGrouping<double, Point>> pointXs = points.GroupBy(o => o.X);
             //按y周分类
             IEnumerable<IGrouping<double, Point>> pointYs = points.GroupBy(o => o.Y);
             //绘制竖线
             DrawXLine(pointXs);
             //绘制横线
             DrawYLine(pointYs);
             //设置定位点
             AddAnchorPoints();
             //绘制定位点并且添加事件
             foreach (AnchorPoint anchorPoint in anchorPoints)
             {
                 Rectangle rec=anchorPoint.Draw();
                 rec.MouseLeftButtonDown += new MouseButtonEventHandler(rec_MouseLeftButtonDown);
                 rec.MouseMove += new MouseEventHandler(rec_MouseMove);
                 canvas.Children.Add(rec);
             }
             //canvas添加事件
             canvas.MouseLeftButtonUp += new MouseButtonEventHandler(canvas_MouseLeftButtonUp);
             canvas.MouseMove += new MouseEventHandler(canvas_MouseMove);
             canvas.MouseLeave += new MouseEventHandler(canvas_MouseLeave);
         }
    
    如上代码:
    如上代码:
    1、按x轴,y轴分类
    2、绘制竖线,横线
    3、设置定位点
    4、绘制定位点并且添加事件监听
    5、给canvas添加事件
    给每个定位点添加鼠标MouseMove和MouseLeftButtonDown事件,给canvas添加MouseMove,MouseLeave,MouseLeftButtonUp事件。
    具体代码不在粘贴了,如果需要代码,可以去下载源代码
  2. 矩形线联动
    矩形线联动,主要是以点带线,通过判断线是否和动点相关联,联动相关的线。主要代码如下:
         private void MoveLines(double x, double y)
         {
             List<Line> moveLines = new List<Line>();
             moveLines = lines.Where(o => o.Y1 == curAnchorPoint.Y
                 || o.Y2 == curAnchorPoint.Y
                 || o.X1 == curAnchorPoint.X
                 || o.X2 == curAnchorPoint.X).ToList();
             foreach (Line line in moveLines)
             {
                 if (line.Y1 == curAnchorPoint.Y)
                 {
                     line.Y1 = y;
                 }
                 if (line.Y2 == curAnchorPoint.Y)
                 {
                     line.Y2 = y;
                 }
                 if (line.X1 == curAnchorPoint.X)
                 {
                     line.X1 = x;
                 }
                 if (line.X2 == curAnchorPoint.X)
                 {
                     line.X2 = x;
                 }
             }
         }
    
  3. 定位点联动

点的联动,和线的联动方法类似,但是点的联动要比线的联动复杂,主要在以下三个方面:1、点的移动需要联动中点的联动。2、在矩形的四个顶点变动时,需要联动其他两个相邻的顶点,和相邻两条线的中点的联动。3、不同的方向点的联动,不一样,会有很多if else。
由于代码较长,就不粘贴了,需要源代码可以去获取源代码。
线中点联动:线的中点联动需要考虑,移动的点是否关联到计算这个中点的两个点或者一个点,关联到中点的这两个点如果有改变,则这个中点就需要改变。主要代码如下:

        private void MoveRefAnchorPoint(double x, double y,AnchorPoint movedAnchorPoint)
        {
            foreach (AnchorPoint anchorPoint in anchorPoints)
            {
                if (anchorPoint.RefPoint.Length == 2)
                {
                    if (anchorPoint.RefPoint[0].X == x && anchorPoint.RefPoint[0].Y == y)
                    {
                        anchorPoint.RefPoint[0].X = movedAnchorPoint.X;
                        anchorPoint.RefPoint[0].Y = movedAnchorPoint.Y;
                    }
                    else if (anchorPoint.RefPoint[1].X == x && anchorPoint.RefPoint[1].Y == y)
                    {
                        anchorPoint.RefPoint[1].X = movedAnchorPoint.X;
                        anchorPoint.RefPoint[1].Y = movedAnchorPoint.Y;
                    }
                    anchorPoint.X = (anchorPoint.RefPoint[0].X + anchorPoint.RefPoint[1].X) / 2;
                    anchorPoint.Y = (anchorPoint.RefPoint[0].Y + anchorPoint.RefPoint[1].Y) / 2;
                    anchorPoint.Move();
                }
            }
        }

以上为单个关联点改变的情况的代码,两个关联点都变动的代码和这个类似。

4、获取源代码

由于文字表达能力有限,另外说清点和线的关系,特别是点和线的联动,确实有点困难,如果感兴趣的话,强烈建议下载代码进行调试阅读。
https://github.com/wangyan9110/ProjectDemos/tree/master/WPFCanvasDemo


目录
相关文章
|
3月前
|
前端开发 C# Windows
WPF基础:在Canvas上绘制图形
WPF基础:在Canvas上绘制图形
126 0
|
前端开发 C#
WPF 自定义的图表(适用大量数据绘制)下
原文:WPF 自定义的图表(适用大量数据绘制)下 上一篇文章中讲了WPF中自定义绘制大量数据的图标,思路是先将其绘制在内存,然后一次性加载到界面,在后续的调试过程中,发现当数据量到达10W时,移动鼠标显示数据有明显的延迟。
1439 0
|
C#
借助Photoshop,Illustrator等设计软件进行WPF图形图像的绘制
原文:借助Photoshop,Illustrator等设计软件进行WPF图形图像的绘制 本文所示例子是借助第三方设计软件,制作复杂的矢量图形,转成与XAML酷似的SVG,再转换成xaml而实现的。
1248 0
|
C# 前端开发 JavaScript
WPF绘制自定义窗口
原文:WPF绘制自定义窗口 WPF是制作界面的一大利器,下面就用WPF模拟一下360的软件管理界面,360软件管理界面如下:   界面不难,主要有如下几个要素: 窗体的圆角 自定义标题栏及按钮 自定义状态栏 窗体的半透明效果 窗体4周有一圈半透明阴影(抓的图上看不出来) 实现思路很简单,首先隐藏默认窗口的标题栏和边框,然后用WPF的Border或Canvas等元素模拟定义窗体的标题栏、内容区和状态栏。
1518 0
|
前端开发 Windows
C#WPF 如何绘制几何图形 图示教程 绘制sin曲线 正弦 绘制2D坐标系 有图有代码
原文:C#WPF 如何绘制几何图形 图示教程 绘制sin曲线 正弦 绘制2D坐标系 有图有代码 C#WPF 如何绘制几何图形? 怎么绘制坐标系?绘制sin曲线(正弦曲线)? 这离不开Path(System.Windows.Shapes)和StreamGeometry(System.Windows.Media)类。
2209 0
|
算法 C# 图形学
WPF绘制深度不同颜色的3D模型填充图和线框图
原文:WPF绘制深度不同颜色的3D模型填充图和线框图 在机械测量过程中,测量的数据需要进行软件处理。通常测量一个零件之后,需要重建零件的3D模型,便于观察测量结果是否与所测工件一致。
2989 0
|
C# 前端开发
WPF 自定义的图表(适用大量数据绘制)
原文:WPF 自定义的图表(适用大量数据绘制) 在WPF中绘制图表比较简单,有很多的第三方控件,但是在绘制大量数据的时候,就显得有些吃力,即便是自己用StreamGeometry画也达不到理想的效果,要达到绘制大量数据而不会顿卡现象,只有一个途径,就是首先在内存中绘制好所有的图形,再一次性加载(或者说绘制)到界面控件Canvas或Grid中。
1228 0
|
C#
WPF 绘制对齐像素的清晰显示的线条
原文:WPF 绘制对齐像素的清晰显示的线条 版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:http://blog.csdn.net/wpwalter/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
1150 0
|
API C# 图形学
WPF中如何使用图像API进行绘制
原文:WPF中如何使用图像API进行绘制 首先,由于WPF中不象GDI+中有Graphics对象,因此你无法使用Graphics进行绘图了,取而代之的是:DrawingContext;类似地,GDI+中的OnPaint已被OnRender取代。
1145 0
|
C# C++ 计算机视觉
WPF特效-绘制实时2D激光雷达图
原文:WPF特效-绘制实时2D激光雷达图 接前两篇: https://blog.csdn.net/u013224722/article/details/80738619 https://blog.csdn.net/u013224722/article/details/80738995 除了c# GDI 、Opencv(c++)、 c# Emgu绘图外,其实c#  WPF绘图功能也很强大。
1894 0