• 2018-11-2-win10-uwp-通过-win2d-画出笔迹


    title author date CreateTime categories
    win10 uwp 通过 win2d 画出笔迹
    lindexi
    2018-11-2 20:11:0 +0800
    2018-11-02 16:18:47 +0800
    UWP win2d

    本文告诉大家如何在 UWP 上让 win2d 画出笔迹,通过实际测试发现在 UWP 的笔迹的性能比在 WPF 高很多。但是如果只是使用默认的 InkCanvas 可以做的很少,同时性能也不是特别高,在加上 win2d 才可以做到和来画一样快的性能

    在参加微软技术暨生态大会 2018听了邵猛大佬的利用 Windows 新特性开发出更好的手绘视频应用学到了使用 win2d 可以画出笔迹。

    在之前我一直在想来画的笔迹性能为什么那么好,现在终于了解到了,于是本文就将具体实现写出来。本文的代码不可以用在实际项目上,因为假设用户都是正常书写

    在 UWP 的笔迹有设置对笔迹完全控制,在中文翻译,会将 Ink 翻译为墨迹,本文将 Ink 翻译为笔迹或墨迹。

    界面

    如果想要在 win2d 画出笔迹,还是需要使用 InkCanvas 来收集笔迹,不能直接通过 Pointer 来做。通过测试使用 Pointer 和 InkCanvas 的性能相差在我的设备是 16 ms 左右,需要知道,笔迹的书写过程,相差 16 ms 是一个很大的值。

    至于为什么通过 InkCanvas 收集笔迹需要在本文下方告诉大家 InkCanvas 的原理。

    因为使用 win2d 需要通过 Nuget 安装,这部分请看在项目安装win2d 本文就直接使用

    先引用命名空间 xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml" 这样就可以在界面通过 canvas 使用高性能的 win2d 来画笔迹

            <canvas:CanvasControl x:Name="Canvas"/>
            <InkCanvas x:Name="InkCanvas"/>

    笔迹性能原理

    为什么通过 InkCanvas 可以拿到很高的性能?

    因为在 InkCanvas 使用了不清真的方式实现了从触摸收集点的方法,而使用 Pointer 是通过消息循环给到程序,同时 Pointer 还需要经过路由事件,这样就让笔迹书写速度不够快。如果 InkCanvas 只是更快收到触摸消息,那么也无法做到像现在这么快的速度。尝试写一个空白的 UWP 程序,在里面添加笔迹控件,在移动的过程中,进入断点,这时你还可以继续在 UWP 应用上画。

    也就是 InkCanvas 的书写和 UWP 的主线程是分开的

    在 UWP 的笔迹渲染是分为三个过程,第一个过程是跟随,也就是将当前的点和上一个点直接连出一条线。第二个过程是动态笔迹层,在书写过程就是进行动态笔迹渲染,这时将使用最快的方式画出笔迹。第三个过程是静态笔迹,在 UWP 官方是 Drying 将动态笔迹成为湿笔迹,就像使用钢笔写的一样。而从湿到干就是动态转静态的笔迹。将笔迹转为静态就可以让笔迹变为一个界面元素,参与界面的变化,如选择和层级这些业务。

    在动态笔迹只是做渲染,用最快的算法从触摸收集到的点画出来,而静态笔迹就是将动态笔迹转换为普通的元素,可以用来做业务

    当然大家也不会关注为什么笔迹在 UWP 那么快,于是就继续在后台代码添加设置。我才不告诉大家,我也不知道他是怎么做的

    完全控制墨迹

    在 UWP 的笔迹可以通过调用 ActivateCustomDrying 方法完全控制笔迹的静态渲染,也就是 InkCanvas 可以让代码处理从动态转静态的方法

                    _inkSynchronizer = InkCanvas.InkPresenter.ActivateCustomDrying();

    这里需要使用字段 _inkSynchronizer 记录笔迹

    多指输入

    原来的 InkCanvas 不支持多指输入,通过下面的代码可以让 InkCanvas 支持多笔

            InkCanvas.InkPresenter.SetPredefinedConfiguration(InkPresenterPredefinedConfiguration
                        .SimpleMultiplePointer);

    转换笔迹

    转换笔迹的时候需要在 win2d 上画出静态笔迹

    Canvas.Draw += CanvasControl_Draw

    在这个函数里面可以通过 win2d 画出任意的内容

    但是需要知道在什么时候开始画,同时 win2d 需要调用 Invalidate 刷新,在笔迹的一笔画完之后可以通过 InkPresenter_StrokesCollected 事件拿到添加的笔迹

                InkCanvas.InkPresenter.StrokesCollected += InkPresenter_StrokesCollected;
           
            private void InkPresenter_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
            {
    
            }

    InkPresenter_StrokesCollected 就可以将笔迹从动态转换为静态在 Win2d 添加用户的元素

    通过 _inkSynchronizer.BeginDry() 拿到现在的所有动态的笔迹

    从函数上可以看到有 BeginDry 应该就有 EndDry 尝试两个函数一起调用,会发现调用了 EndDry 之后动态笔迹就消失了。如果这时还没有将静态笔迹画出来,界面就看不到原来的笔迹

    在 UWP 可以多次调用 BeginDry 拿到动态笔迹,假如现在有动态笔迹 1、2 调用 BeginDry 会返回动态笔迹 1、2 然后用户继续触摸,在界面有动态笔迹 3 再次调用BeginDry会返回第三条笔迹。

    但是只能调用一次 EndDry 也就是在调用多次 BeginDry 只有只能调用一次 EndDry 不能相邻两次调用 EndDry 方法

    在 win2d 画静态笔迹首先需要刷新界面

     private void InkPresenter_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
     {
                _pendingDry = inkSynchronizer.BeginDry();
    
                Canvas.Invalidate();
     }

    在 Canvas 的刷新函数画出笔迹

     using (CanvasDrawingSession ds = sender.CreateDrawingSession())
     {
         ds.DrawInk(_pendingDry);
     }

    无限漫游

    如果现有做无限漫游,可以使用 CanvasVirtualControl 做一个超级大的画布,同时只画出可见的范围

    这样可以做到无限漫游添加很多笔迹而软件不会变卡

  • 相关阅读:
    jquery 左右滚动插件
    MagicAjax使用及注意事项~!!!AJAX无刷新的DLL文件!!
    android 中播放声音要注意的细节
    JNIEnv*的常用函数详解
    http协议上传数据的 优化 方法
    jni 设计的哲学
    listview动态加载数据,并更新数据列表
    Android HOME键的屏蔽
    Django在pycharm业余版进行创建项目文件
    SQL Server 日常维护查询当前正在执行的语句、死锁、堵塞
  • 原文地址:https://www.cnblogs.com/lindexi/p/12086358.html
Copyright © 2020-2023  润新知