文档章节

【WPF】 InkCanvas 书写毛笔效果

o
 osc_a22drz29
发布于 2019/03/26 19:19
字数 1425
阅读 12
收藏 0
wpf

精选30+云产品,助力企业轻松上云!>>>

首先贴出本文参考学习的文章吧。

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 书写距离

书写距离应该怎么获得?

--- 无非就是两个点之间的距离。

  1. 在InkCanvas下重写OnDraw方法(详见羊博主博文
  2. 在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;
}

打完收工。

有疑问请留言。

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
WPF InkCanvas 毛笔效果

1、先来看看InkCanvas的一般用法: <InkCanvas> <InkCanvas.DefaultDrawingAttributes> <DrawingAttributes StylusTip="Ellipse" Height="8" Width="4" IgnorePressure="False" FitToCurve="......

osc_cw97bsoa
2018/05/18
2
0
Android-毛笔的探索与开发

前言 这篇文章主要是关于移动端毛笔的开发,在平板上有着书写毛笔字贴的效果。 介绍关于毛笔的算法思路。 项目github地址 算法思路分析 曲线拟合算法 利用曲线拟合算法增加虚拟的点,使得笔迹...

osc_urm28qtx
04/16
6
0
Android-毛笔的探索与开发

前言 这篇文章主要是关于移动端毛笔的开发,在平板上有着书写毛笔字贴的效果。 介绍关于毛笔的算法思路。 项目github地址 算法思路分析 曲线拟合算法 利用曲线拟合算法增加虚拟的点,使得笔迹...

.double
2019/05/21
0
0
WPF 的摄像头控件VideoCaptureElement 浅谈

最近有个小项目要求用wpf实现显示摄像头画面,并且能拍照,标注,切换画面等等。 看了一下wpf有个自带的库WPFMediaKit.dll,里面有个摄像头控件VideoCaptureElement ,好吧,就用它了 1、能拍...

osc_km8z9zfx
2019/11/21
25
0
继续聊WPF——数字墨迹B

前面的内容,我们用简单的方法就创建了一个手写板示例,下面,我们再来做一个更为复杂一点的手写板程序。示例程序有两个选项:选择“书写”可以进行手写输入,选择“擦除”,可以去掉不必要的...

junwong
2012/04/18
192
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux安装redis服务器和部署

Linux安装redis和部署 第一步:下载安装包 wget http://download.redis.io/releases/redis-5.0.5.tar.gz 访问https://redis.io/download 到官网进行下载。这里下载最新的5.0.5版本. 第二步:...

osc_3ytpwpyb
刚刚
0
0
IF函数,根据条件设定输入内容

if函数通常用于条件判断,根据判断结果执行相应命令。 1.函数解释: IF(logical_test, [value_if_true], [value_if_false]) logical_test 必需。 计算结果为 TRUE 或 FALSE 的任何值或表达式...

osc_sumf8h95
2分钟前
0
0
Pytorch自定义dataloader以及在迭代过程中返回image的name

pytorch官方给的加载数据的方式是已经定义好的dataset以及loader,如何加载自己本地的图片以及label? 形如数据格式为 image1 label1 image2 label2 ... imagen labeln 实验中我采用的数据的...

osc_l8u38961
3分钟前
0
0
灯塔

\[love\ and \ share \] 我怎么感觉变成了好东西推荐呢?算了,本来也差不多 还没写完,想到再更 有好看玩的能不能评论一下,qwq 动漫 大多是些国漫,多在\(b\)站、腾讯视频、盗版小网站能够...

osc_dc6pbw3x
4分钟前
0
0
网易首页 」 网易手机 」 正文 苹果超薄触摸显示技术专利曝光:重新定义轻薄

最近,苹果公司的新屏幕专利技术已经曝光。特别是苹果公司的新型超薄触摸技术,它可以降低显示器的结构水平,消除多余的电路,并使屏幕更薄。该专利表明,这项新技术适用于iPhone,iPad,App...

osc_opzpp18v
6分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部