【WPF】 InkCanvas 书写毛笔效果
首先贴出本文参考学习的文章吧。
https://www.cnblogs.com/LCHL/p/9055642.html#4206298
感谢这位懒羊羊博主的代码和讲解,我在此基础上稍微加了一些东西,希望能使书写效果得到更好的提升吧。建议先从羊博主的博文看起。
前文
- 本文致力于解决羊博主的2-3问题,即代码粗细度的优化。
- 本文本着分享知识的目的写出,希望能对一些寻找类似知识的人一些帮助,能得到各位的批评指正也是荣幸万分。
- 因工作公司的原因,无法贴出全部代码,我尽量在下文中对自己的思路进行详细的讲解。(要吃饭的呀)
关键词
Freeze, DrawingContext
思路
1. 卡顿问题
羊博主提出使用WPF中的Freeze()方法将画刷“冻结”。
Freezable 类提供特殊功能,以便在使用修改或复制开销很大的对象时帮助提高应用程序性能。
笔者使用该方法后,书写性能得到了很大提升,但是书写点数目达到万为单位时,出现书写不流畅的情况,且越书写越卡顿。笔者冥思苦想三天三夜,尝试了很多方法都没有得到解决。果然皇天不负有心人,终于还是让我找到了一些改进方法。代码如下:
ImageDrawing image = new ImageDrawing()
{
ImageSource = imageSource,
Rect = new Rect(x - t1 / 2.0, y - t1 / 2.0, t1, t1)
//t1 为当前的粗细度;x为当前的X坐标,y为当前Y坐标
};
image.Freeze();
drawingContext.DrawDrawing(image);
将DrawImage更改为DrawDrawing,书写性能确实得到了虽然微弱但可见的提升。(自己给自己鼓掌)但是具体有多少提升,笔者并没有做量化。(太懒了)
效果基本满意,如果您有更好的解决方法,希望能得到您的指点。
后文,笔者在羊博主的指点下让书写效率又得到了数以十倍的提升,非常感谢羊兄的指导。然笔者愚钝,力有不逮,不能向读者说出其精髓之一二,实在抱歉。该优化方法在羊博主文章中也部分写出,对于这方面有要求的读者,可以学习羊博主的博客。
2. 颜色问题
羊博主博客已完美解决该问题,棒棒哒。✿✿ヽ(°▽°)ノ✿)
3. 粗细问题
- 粗细度问题可以分解为两个问题,一个是书写时间,一个是书写距离。简而言之就是书写速度越快,笔迹越细;书写速度越慢,笔迹越粗。(速度v = 距离s / 时间t,这个大家应该都知道)
3.1 书写距离
书写距离应该怎么获得?
--- 无非就是两个点之间的距离。
- 在InkCanvas下重写OnDraw方法(详见羊博主博文)
- 在OnDraw方法中带了参数StylusPointCollection,该参数为书写点的搜集。该参数搜集动态绘制时产生的点,一般为两个点,即绘制一条线段时的前后两个点,这两个点相减就得到了两点间的距离。
3.2 书写时间
这个参数在Ondraw中没有,如果想关联该参数的话可以研究一下RawStylusInput.Timestamp,(项目组的大神把这些都搭建好了,我用就完事了)该参数可以获取发生输入的时间,两点时间相减就获得了间距的书写时间。两点就是两条线段的终点,因为在绘制时是连续的线,所以后面的线的起点和前面线的终点为相同的点,这个应该很好理解。
3.3 书写速度
通过距离除以时间得出书写速度,自己规定一个速度阈值,在大于这个阈值时,将粗细值缩小;小于这个阈值时,将粗细度放大。该阈值就看你自己想要书写的效果定。建议将进行加减时的值设置为定值,这样线条变化更加平滑。
以下代码不包含时间参数的影响,即只考虑书写间距的影响。所以大家都能用。
部分代码如下:
Point p1 = (Point)stylusPoints[1]; //线段的终点
Vector dis= p1 - p0; //两点间距
if (dis.Length != 0)
{
double y= (p1.Y - p0.Y) / dis.Length; //Y轴上的单位变化量
double x= (p1.X - p0.X) / dis.Length;
double aX = p0.X;
double aY = p0.Y;
for (double j = 0; j <= dis.Length; j += 10) //分割线段,化线为点,对每个点进行处理,达到粗细平滑变化的效果
{
if (Convert.ToInt32(dis.Length) > LastDis) //前个线段的长度大于当前线段的情况,让线条变细
{
t1 = (t1 - _sub) <= _minT ? _minT : t1 - _sub;
}
else if (t1 < _thick) //前个线段的长度大于当前线段,且小于规定的最大宽度
{
t1 = (t1 + _add) >= _thick ? _thick : t1 + _add;
}
aX+= x;
aY+= y;
ImageDrawing i = new ImageDrawing()
{
ImageSource = imageSource,
Rect = new Rect(aX - t1/ 2.0, aY - t1/ 2.0, t1, t1)
};
i.Freeze();
drawingContext.DrawDrawing(i); //绘制
}
p0 = new Point(aX, aY); //保存最后一个优化点,即终点
LastDis = Convert.ToInt32(dis.Length);
_thick= t1;
}
静态呈现方法与之相同,只要理解了上述的方法,应该就没什么大问题了。笔者就不在此赘述。
效果图:


可以在最小的粗细度的时候判断是否还是超过现在的线段长度,是的话可以让aX 和aY 这两个值直接等于最后的点,从而实现书写过快时的流线间断感。但是线段会不平滑。(图画的比较丑,没有表现出间断的优美感。。。)
效果图:
if (_thickness == _minT)
{
aX += x * (distance.Length - j - 1);
aY += y * (distance.Length - j - 1);
break;
}
打完收工。
有疑问请留言。
【WPF】 InkCanvas 书写毛笔效果的更多相关文章
- WPF InkCanvas 书写毛笔效果
https://www.cnblogs.com/younShieh/p/10602787.html
- WPF InkCanvas 毛笔效果
原文:WPF InkCanvas 毛笔效果 1.先来看看InkCanvas的一般用法: <InkCanvas> <InkCanvas.DefaultDrawingAttrib ...
- WPF图形/文字特别效果之一:交叉效果探讨(续)
原文:WPF图形/文字特别效果之一:交叉效果探讨(续) 在"WPF图形/文字特别效果之一:交叉效果探讨"(http://blog.csdn.net/johnsuna/archive ...
- WPF绘制党徽(立体效果,Cool)
原文:WPF绘制党徽(立体效果,Cool) 前面用WPF方式绘制了党旗(WPF制作的党旗) ,去年3月份利用C# 及GDI+绘制过党徽,这次使用WPF来绘制党徽. ------------------ ...
- WPF 扩大,回弹效果
原文:WPF 扩大,回弹效果 <Window x:Class="Fish.AccountBook.View.Test.PanelWindow" xmlns="htt ...
- WPF 有趣的动画效果
WPF 有趣的动画效果 这一次我要呈上一个简单的文章,关于给你的WPF apps加入美丽的光线动画,可是我对动画这东西可能有点入迷了. 实际上.我对动画如此的入迷,以至 ...
- WPF 高速书写 StylusPlugIn 原理
原文:WPF 高速书写 StylusPlugIn 原理 本文告诉大家 WPF 的 StylusPlugIn 为什么能做高性能书写,在我的上一篇博客和大家介绍了 WPF 的触摸原理,但是没有详细告诉大家 ...
- WPF图形/文字特别效果之一:交叉效果探讨
原文:WPF图形/文字特别效果之一:交叉效果探讨 为了说明问题,先看下图:图1 完全重叠的单一颜色文字它是2008几个字的叠加,并且颜色为单一的红色.如果不仔细分辨,你或许无法一下子看出是2008. ...
- WPF中制作立体效果的文字或LOGO图形(续)
原文:WPF中制作立体效果的文字或LOGO图形(续) 上篇"WPF中制作立体效果的文字或LOGO图形"(http://blog.csdn.net/johnsuna/archive/ ...
随机推荐
- 浅入深出Vue:数据绑定
上一篇我们使用了简单的数据渲染,那么如果说我们想要动态渲染标签的 class 可以这么操作么? 为什么绑定 简单的数据渲染,包括表达式.函数在内.其实都只是在标签中渲染,如果遇到以下情况怎么办呢: 需 ...
- vscode解决同步设置插件连接不上git
vscode有一款比较好用的插件,就是设置同步.可以在一台电脑上同步另一台电脑的所有配置及插件! Settings Sync 但是在公司电脑有个奇葩问题,就是连接不上git. 解决:配置代理 &quo ...
- 5分钟快速部署DataDraw数字绘
经常有小伙伴问,有没有一款好用又免费的画图软件,画画流程图.UML.思维导图?今天就介绍一款开源的在线画图软件,满足各方面人的需求. DataDraw数字绘是一个在线线框图.流程图.网络图.组织结构图 ...
- 机器学习读书笔记(一)k-近邻算法
一.机器学习是什么 机器学习的英文名称叫Machine Learning,简称ML,该领域主要研究的是如何使计算机能够模拟人类的学习行为从而获得新的知识和技能,并且重新组织已学习到的知识和和技能,使之 ...
- BZOJ 2152:聪聪可可(树上点分治)
题目链接 题意 中文题意. 思路 和上一题类似,只不过cal()函数需要发生变化. 题目中要求是3的倍数,那么可以想到 (a + b) % 3 == 0 和 (a % 3 + b % 3) % 3 = ...
- Java线程池源码及原理
目录 1 说明 1.1类继承图 2 线程池的状态 3 源码分析 3.1完整的线程池构造方法 3.2 ctl 3.3 任务的执行 3.3.1 execute(Runnable command) 3.3. ...
- C++学习书籍推荐《More Effective C++》下载
百度云及其他网盘下载地址:点我 编辑推荐 <More Effective C++:35个改善编程与设计的有效方法(中文版)>:传世经典书丛 媒体推荐 <Effective c++&g ...
- IDM 6.27.5(Internet Download Manager)中文破解版下载神器
IDM一直是我最喜欢的下载工具,感觉用的比迅雷爽,简单使用,对付网盘有一套.IDM(Internet Download Manager)和迅雷的下载提速方式不同,从原理上来说,IDM速度较稳定,迅雷下 ...
- C#使用sqlite-net搭建简易的ORM
SQLite简易版ORM 首先打开项目,使用nuget搜索sqlite-net,如下图: 下载完成后,我们会多出两个文件,SQLite.cs和SQLiteAsync.cs. 我们新建一个文件夹SQLi ...
- 聊聊C语言的预编译指令include
"include"相信大家不会陌生,在我们写代码时,开头总会来一句"include XXX".include是干嘛用的,很多教材都提到了,因此这里不会再详细解释 ...