WPF 使用InkCanvas实现画板的缩放以及移动

最近博主需要实现一个画板功能,可以写字并且支持触屏的手势缩放以及拖动。

找资料的时候发现网上相关资料特别少,于是经历了#$#@!##$#¥#$*就完成了。

上教程:

1.首先我们要实现一个最基本的画板功能,只需要简单的一行代码即可:

对InkCanvas如还有不会使用的,参考这篇文章(WPF InkCanvas 画图 基础使用教程)

  

这样我们便有了一个最基本的画板,下面我们先用鼠标滚轮来实现画板放大缩小。

   
            
        
2.鼠标滚轮实现缩放以及移动

如果对InkCanvas本身控件进行缩放移动,那么将会露出部分父容器Grid的背景色,要解决这个问题,我们只需要对墨迹进行缩放即可,对ink.Strokes进行操作,使用Transform方法对其进行变换,Matrix是一个矩阵变换的类(C# 矩阵变换Matrix),然而我们用自带的方法就OK了,以鼠标为中心点进行缩放:

   private void ink_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (e.Delta < 0)
            {
                foreach (Stroke stroke in ink.Strokes)
                {
                    Matrix matrix = new Matrix();
                    //缩小     小于1为缩小(最好不要为负数),大于1为放大,此为缩小0.8倍
                    matrix.ScaleAt(0.8, 0.8, Mouse.GetPosition(ink).X, Mouse.GetPosition(ink).Y);
                    //X轴移动  正数为右,负数为左,此为右移1.2倍   斜着移动设置两个值
                    matrix.Translate(1.2, 0);
                    stroke.Transform(matrix, false);
                }
            }
            else
            {
                foreach (Stroke stroke in ink.Strokes)
                {
                    Matrix matrix = new Matrix();
                    //放大     此为放大1.25倍
                    matrix.ScaleAt(1.25, 1.25, Mouse.GetPosition(ink).X, Mouse.GetPosition(ink).Y);
                    //Y轴移动 此为左移1.2倍
                    matrix.Translate(0, 1.2);
                    stroke.Transform(matrix, false);
                }
            }
        }
3.触屏实现

我们需要了解几个事件并通过他们完成各种手势操作:ManipulationStarting(开始)、ManipulationStarted(开始以后)、ManipulationDelta(手势)、ManipulationInertiaStarting(惯性)、ManipulationCompleted(完成),并把控件的IsManipulationEnabled设为"True",于是就出现了下面的代码:

  
        
    

经博主实验,我们面临了几个比较坑的问题:

1.WPF识别多个鼠标或者触摸设备是异步的

2.InkCanvas触摸/点击移动就会留下墨迹

3.手势如何实现

为了解决第一个问题,我们使用PreviewTouchDown事件进行设备的捕获并保存,第二个问题我们只需要让画笔的InkCanvasEditingMode属性为None:

定义全局变量

 
 //记录触摸设备ID
  private List dec = new List();
 //中心点
  Point centerPoint;

PreviewTouchDown事件:

 private void ink_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            dec.Add(e.TouchDevice.Id);
            //设备1个的时候,记录中心点
            if (dec.Count == 1)
            {
                TouchPoint touchPoint = e.GetTouchPoint(ink);
                centerPoint = touchPoint.Position;
            }
            //设备两个及两个以上,将画笔功能关闭
            if (dec.Count > 1)
            {
                if (ink.EditingMode != InkCanvasEditingMode.None)
                {
                    ink.EditingMode = InkCanvasEditingMode.None;
                }
            }
        }
PreviewTouchUp事件:
 private void ink_PreviewTouchUp_PreviewTouchUp(object sender, TouchEventArgs e)
        {
            //手势完成后切回之前的状态
            if (dec.Count > 1)
            {
                if (ink.EditingMode == InkCanvasEditingMode.None)
                {
                    ink.EditingMode = InkCanvasEditingMode.Ink;
                }
            }
            dec.Remove(e.TouchDevice.Id);
        }

接下来我们需要实现手势的操作:

   private void touchGrid_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
        {
            e.ManipulationContainer = ink;
            e.Mode = ManipulationModes.All;
        }
        private void touchGrid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            //小于两指 不触发事件
            if (dec.Count < 2) return;
            //两指缩放
            if (dec.Count == 2)
            {
                foreach (Stroke stroke in ink.Strokes)
                {
                    Matrix matrix = new Matrix();
                    matrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y, centerPoint.X, centerPoint.Y);
                    stroke.Transform(matrix, false);
                }
            }
            //三指滑动
            if (dec.Count == 3)
            {
                foreach (Stroke stroke in ink.Strokes)
                {
                    Matrix matrix = new Matrix();
                    matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
                    stroke.Transform(matrix, false);
                }
            }
        }
        private void touchGride_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            //TODO 完成之后需要做的事情
        }

到此,基本的使用InkCanvas实现画板的缩放以及移动已经完成,需要Demo的可以点这个 链接


你可能感兴趣的:(WPF 使用InkCanvas实现画板的缩放以及移动)