本文来告诉大家如何通过 Win2d 完全控制笔迹绘制逻辑,本文适合用来实现复杂的自定义逻辑,可以完全控制笔迹的行为。包括在书写过程中切换模式,如进行手势擦除切换为橡皮擦模式

本文提供的方法适合用来做复杂的自定义,本文的方法的优点也是缺点。优点是啥都可以自己控制,缺点是啥都需要自己控制。需要自己处理笔迹的多笔同步问题,处理笔迹的长笔迹分段问题,处理笔迹的绘制问题,处理动态笔迹切换

本文提供的方法依然可以实现非常高性能的笔迹,比 WPF 最快的笔迹实现还要快,但需要自己处理好各个部分的逻辑,如动态笔迹和静态笔迹,笔迹分段等逻辑。本文提供的方法的性能依然不如只使用默认的 InkCanvas 快

界面

在开始之前,请先安装 Win2d 库,可参阅 win10 uwp win2d 入门 看这一篇就够了 博客了解如何安装

在 XAML 界面上加上 xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml" 命名空间,用来导入 Win2d 控件。界面如下

  <Grid Background="#565656">
<canvas:CanvasControl x:Name="Canvas" Draw="Canvas_OnDraw"/>
<InkCanvas x:Name="InkCanvas" />
</Grid>

本文将使用一个 InkCanvas 放在 Win2d 的 CanvasControl 上层,让 InkCanvas 作为快速的事件接收层,让 Win2d 的 CanvasControl 作为实际的绘制层。其实,更好的界面框架是存放两个 Win2d 的 CanvasControl 分别用来存放动态笔迹和静态笔迹。如果自己实现的笔迹没有分动态笔迹和静态笔迹,那么可以忽略,本文为了简洁将不演示动态笔迹和静态笔迹的处理

此时的界面逻辑如下

<Page
x:Class="KeanearkallhawDaherenenallyi.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:KeanearkallhawDaherenenallyi"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid Background="#565656">
<canvas:CanvasControl x:Name="Canvas" Draw="Canvas_OnDraw"/>
<InkCanvas x:Name="InkCanvas" />
</Grid>
</Page>

初始化笔迹接收

在构造函数初始化笔迹的接收逻辑,通过 InkCanvas 进行快速的事件接收

        private readonly InkSynchronizer _inkSynchronizer;

        public MainPage()
{
this.InitializeComponent();
_inkSynchronizer = InkCanvas.InkPresenter.ActivateCustomDrying();
InkCanvas.InkPresenter.SetPredefinedConfiguration(InkPresenterPredefinedConfiguration
.SimpleMultiplePointer);
InkCanvas.InkPresenter.InputDeviceTypes =
CoreInputDeviceTypes.Touch | CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Mouse;
InkCanvas.InkPresenter.UnprocessedInput.PointerMoved += UnprocessedInput_PointerMoved;
InkCanvas.InkPresenter.InputProcessingConfiguration.Mode = InkInputProcessingMode.None;
InkCanvas.InkPresenter.InputProcessingConfiguration.RightDragAction =
InkInputRightDragAction.LeaveUnprocessed;
}

以上的代码里面,只是监听了 UnprocessedInput 的 PointerMoved 事件,事实上需要监听更多的事件用来了解笔迹的绘制开始和完成逻辑。本文为了方便演示,就不详细写所有逻辑

以上各个部分逻辑的含义,请参阅 win10 uwp 通过 win2d 画出笔迹

收集笔迹

UnprocessedInput_PointerMoved 将是本文的核心逻辑,在这里通过事件参数了解到当前是哪个手指或笔触摸,以及通过 InkStrokeBuilder 将输入的点构造笔迹

        private void UnprocessedInput_PointerMoved(InkUnprocessedInput sender, Windows.UI.Core.PointerEventArgs args)
{
var id = args.CurrentPoint.PointerId;
// 需要根据 id 分开多个手指 InkStrokeBuilder.SetDefaultDrawingAttributes(new InkDrawingAttributes()
{
Color = Colors.Blue,
Size = new Size(5, 5)
}); _currentPointerList.AddRange(args.GetIntermediatePoints());
_inkStroke = InkStrokeBuilder.CreateStrokeFromInkPoints(
_currentPointerList.Select(t => new InkPoint(t.Position, t.Properties.Pressure)), Matrix3x2.Identity); Canvas.Invalidate();
} private readonly List<PointerPoint> _currentPointerList = new List<PointerPoint>();
private InkStroke _inkStroke; private InkStrokeBuilder InkStrokeBuilder { get; } = new InkStrokeBuilder();

以上代码没有编写的部分是了解当前是由哪个 id 的设备触发的事件,如有多个手指在触摸,那么不同的手指的 id 是不相同的。需要自己创建列表数组进行处理

另外,通过 InkStrokeBuilder 的 CreateStrokeFromInkPoints 创建的 InkStroke 是需要预先在 SetDefaultDrawingAttributes 设置绘制属性的,而不是在创建之后依然可以设置。另外上面代码只使用了一个 InkStroke 字段,实际上需要根据当前是否有多指触摸的需求,使用列表存放多个笔迹

本文以上代码通过 CreateStrokeFromInkPoints 创建是不包含笔迹分段的,也就是说在用户绘制一段长线,将会需要使用较多的计算资源创建笔迹。请在自己的产品逻辑里面,手动分开为多个不同的笔迹段,用来提升性能

上面代码通过调用 CanvasControl 的 Invalidate 让 Win2d 的画布重新绘制。重新绘制会进入 Canvas_OnDraw 方法,将在此方法绘制出笔迹

绘制笔迹

绘制笔迹的方法十分简单,调用 Win2d 的 DrawInk 方法传入笔迹即可

        private void Canvas_OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (_inkStroke != null)
{
args.DrawingSession.DrawInk(new []{_inkStroke});
}
}

为什么在 Win2d 的设计里面,是传入数组?原因是笔迹是需要分段的,多段笔迹可以一起绘制。另外,如果有笔迹分段,那么逻辑上就需要额外的转换为静态笔迹的功能,大概就是将一段连续的多段笔迹合成一段笔迹的过程。建议绘制动态笔迹和静态笔迹放在两个 Win2d 的 CanvasControl 里。这样也能提升笔迹的动态绘制性能,因为笔迹在绘制的时候需要不断调用 Win2d 的刷新,如果此时刷新的是一个只包含很少笔迹的动态笔迹层的画布,那每次刷新的性能就比较好

无限漫游

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

使用时需要自己转换坐标,可以在 InkStrokeBuilder 的 CreateStrokeFromInkPoints 方法传入缩放和平移的矩阵,此时创建出来的笔迹是包含了变换的

代码

本文所有代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin d33e26640f0108ae6bb29b90e7b189a14a92d624

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 KeanearkallhawDaherenenallyi 文件夹

参考

更多笔迹和触摸,请参阅 触摸相关

win10 uwp 通过 Win2d 完全控制笔迹绘制逻辑的更多相关文章

  1. win10 uwp win2d CanvasVirtualControl 与 CanvasAnimatedControl

    本文来告诉大家 CanvasVirtualControl ,在什么时候使用这个控件. 在之前的入门教程win10 uwp win2d 入门 看这一篇就够了我直接用的是CanvasControl,实际上 ...

  2. win10 uwp 毛玻璃

    毛玻璃在UWP很简单,不会和WPF那样伤性能. 本文告诉大家,如何在 UWP 使用 win2d 做毛玻璃. 毛玻璃可以使用 win2D 方法,也可以使用 Compositor . 使用 win2d 得 ...

  3. win10 uwp 萤火虫效果

    原文:win10 uwp 萤火虫效果 本文在Nukepayload2指导下,使用他的思想用C#写出来. 本文告诉大家,如何使用 win2d 做出萤火虫效果. 安装 win2d 安装win2d的方法请使 ...

  4. Win10 UWP开发系列:实现Master/Detail布局

    在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档: ...

  5. win10 uwp MVVM 轻量框架

    如果在开发过程,遇到多个页面之间,需要传输信息,那么可能遇到设计的问题.如果因为一个页面内包含多个子页面和多个子页面之间的通信问题找不到一个好的解决方法,那么请看本文.如果因为ViewModel代码越 ...

  6. win10 uwp 入门

    UWP是什么我在这里就不说,本文主要是介绍如何入门UWP,也是合并我写的博客. 关于UWP介绍可以参见:http://lib.csdn.net/article/csharp/32451 首先需要申请一 ...

  7. win10 uwp 渲染原理 DirectComposition 渲染

    本文来告诉大家一个新的技术DirectComposition,在 win7 之后(实际上是 vista),微软正在考虑一个新的渲染机制 在 Windows Vista 就引入了一个服务,桌面窗口管理器 ...

  8. win10 uwp 商业游戏

    本文告诉大家去做一个商业游戏,游戏很简单,几乎没有什么技术 游戏的开始,需要添加框架库,于是引用我自己写的库. 首先是创建一个启动页面,这个页面是显示启动的. 在显示启动的时候,是需要加载游戏需要使用 ...

  9. Win10 UWP版《芒果TV》v2.4.0直播超女,芒果台综艺一网打尽

    Win10 UWP版<芒果TV>直播超女,芒果台综艺一网打尽 Win10版UWP<芒果TV>自2015年9月登录商店以来,一直在持续更新,积极改进,拥有芒果台视频的独家点播和直 ...

随机推荐

  1. 记一次Hvv中遇到的API接口泄露而引起的一系列漏洞

    引言 最近朋友跟我一起把之前废弃的公众号做起来了,更名为鹿鸣安全团队,后面陆续会更新个人笔记,有趣的渗透经历,内网渗透相关话题等,欢迎大家关注 前言 Hvv中的一个很有趣的漏洞挖掘过程,从一个简单的A ...

  2. Altium Designer 21.x中文版安装破解教程

    Altium Designer 21.x是一款优秀的PCB设计工具,可以原理图设计.电路仿真.PCB绘制编辑.拓扑逻辑自动布线.信号完整性分析和设计输出等功能,为设计者提供了全新的设计解决方案,提高设 ...

  3. 构建后端第2篇之---springb @ComponentScan注解使用

    张艳涛写于2021-2-8日 构建后端项目的时候遇到一个问题,在zyt-auth项目的依赖定义了@Component类,这个类在项目启动的时候提示没有找到bean Field tokenService ...

  4. Docker安装Kong API Gateway并使用

    我最新最全的文章都在南瓜慢说 www.pkslow.com,文章更新也只在官网,欢迎大家来喝茶~~ 1 简介 Kong不是一个简单的产品,本文讲的Kong主要指的是Kong API Gateway,即 ...

  5. netty系列之:netty中的Channel详解

    目录 简介 Channel详解 异步IO和ChannelFuture Channel的层级结构 释放资源 事件处理 总结 简介 Channel是连接ByteBuf和Event的桥梁,netty中的Ch ...

  6. vue传值 ---- >> 子传父,$emit()

    划重点: $emit 绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数.   子组件:   1 <template& ...

  7. 什么是RSA

    一.RSA引入: RSA是什么,嗯,这是一个好问题,有没有兴趣啊 二.RSA的解释: RSA是一种加密方式,它是现代密码学的代表(什么是现代密码学,这个吗,我感觉就是我们所使用的密码的加密的方式之一可 ...

  8. linux笔记2随笔

    124.diff命令:文件内容对比 diff命令用于比较多个文本文件之间的差异,这在系统安全防范中非常重要.比如当黑客入侵系统之后,往往会修改一些系统配置文件,从而留下一些后门. 所以作为运维人员.最 ...

  9. 为什么大部分的Android开发成为不了架构师

    小团队一般 10 人左右,其中常常是技术最牛的人做架构师(或TL).所以,架构师在广大码农中的占比大概平均不到 10%.而架构师也可以分为初级.中级.高级三档,江湖上真正高水平的软件架构师就更少了. ...

  10. 字节跳动已经10万人了?渣本双非Android程序员怎么上车?

    字节跳动已经 10 万人了? 是的,在 2020 年字节跳动的员工总数从 6 万蹿到 10 万,平均每个工作日就有 150 人在办理入职,加入字节跳动全球超过 240 个办公点. 更有统计,在总部北京 ...