我是靠谱客的博主 落寞可乐,这篇文章主要介绍WPF InkCanvas 毛笔效果,现在分享给大家,希望可以做个参考。

1、先来看看InkCanvas的一般用法:

<InkCanvas>
     <InkCanvas.DefaultDrawingAttributes>
           <DrawingAttributes StylusTip="Ellipse" Height="8" Width="4" IgnorePressure="False" FitToCurve="True" >
           <!--稍微变换一下,就算设备不支持“压感”,效果也是棒棒-->

    <DrawingAttributes.StylusTipTransform>
                   <Matrix M11="1" M12="1.5" M21="2.2" M22="1"/>
              </DrawingAttributes.StylusTipTransform>
           </DrawingAttributes>
     </InkCanvas.DefaultDrawingAttributes>
</InkCanvas>

2、自定义InkCanvas,实现毛笔效果

找到2篇文章,代码基本一致,也不知道哪位是原作者抑或都不是原作者?

使用WPF的自定义InkCanvas实现毛笔效果 【个人觉得该作者为原创?】

wpf inkcanvas customink 毛笔效果 【这位童鞋的话,后面都叛变去搞Unity3D了!】

以上代码缺点:

2-1、卡顿【虽然提到了解决办法,但都没有给出具体代码】

2-2、颜色【毛笔配黑墨才是正途,但世界是多姿多彩的不是?】

2-3、粗细【这个嘛~】

废话不多说,奉上改进后的代码:

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
1 public class ChinesebrushRenderer : DynamicRenderer 2 { 3 private ImageSource imageSource; 4 private readonly double width = 16; 5 6 protected override void OnDrawingAttributesReplaced() 7 { 8 if (DesignerProperties.GetIsInDesignMode(this.Element)) 9 return; 10 11 base.OnDrawingAttributesReplaced(); 12 13 var dv = new DrawingVisual(); 14 var size = 90; 15 using (var conext = dv.RenderOpen()) 16 { 17 //[关键]OpacityMask了解下?也许有童鞋想到的办法是,各种颜色的图片来一张? 18 conext.PushOpacityMask(new ImageBrush(new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Images\pen.png", UriKind.Absolute)))); 19 //用颜色生成画笔画一个矩形 20 conext.DrawRectangle(new SolidColorBrush(this.DrawingAttributes.Color), null, new Rect(0, 0, size, size)); 21 conext.Close(); 22 } 23 var rtb = new RenderTargetBitmap(size, size, 96d, 96d, PixelFormats.Pbgra32); 24 rtb.Render(dv); 25 imageSource = BitmapFrame.Create(rtb); 26 //[重要]此乃解决卡顿问题的关键! 27 imageSource.Freeze(); 28 } 29 30 protected override void OnDraw(DrawingContext drawingContext, StylusPointCollection stylusPoints, Geometry geometry, Brush fillBrush) 31 { 32 var p1 = new Point(double.NegativeInfinity, double.NegativeInfinity); 33 var p2 = new Point(0, 0); 34 var w1 = this.width + 20; 35 36 for (int i = 0; i < stylusPoints.Count; i++) 37 { 38 p2 = (Point)stylusPoints[i]; 39 40 //两点相减得到一个向量[高中数学知识了解下?] 41 var vector = p1 - p2; 42 43 //得到 x、y的变化值 44 var dx = (p2.X - p1.X) / vector.Length; 45 var dy = (p2.Y - p1.Y) / vector.Length; 46 47 var w2 = this.width; 48 if (w1 - vector.Length > this.width) 49 w2 = w1 - vector.Length; 50 51 //为啥又来一个for?图像重叠,实现笔画的连续性,感兴趣的童鞋可以把for取消掉看看效果 52 for (int j = 0; j < vector.Length; j++) 53 { 54 var x = p2.X; 55 var y = p2.Y; 56 57 if (!double.IsInfinity(p1.X) && !double.IsInfinity(p1.Y)) 58 { 59 x = p1.X + dx; 60 y = p1.Y + dy; 61 } 62 63 //画图,没啥可说的 64 drawingContext.DrawImage(imageSource, new Rect(x - w2 / 2.0, y - w2 / 2.0, w2, w2)); 65 66 //再把新的坐标赋值给p1,以序后来 67 p1 = new Point(x, y); 68 69 if (double.IsInfinity(vector.Length)) 70 break; 71 72 } 73 } 74 }

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
1 public class ChinesebrushStroke : Stroke 2 { 3 4 private ImageSource imageSource; 5 private readonly double width = 16; 6 7 public ChinesebrushStroke(StylusPointCollection stylusPointCollection, Color color) : base(stylusPointCollection) 8 { 9 if (DesignerProperties.GetIsInDesignMode(App.Current.MainWindow)) 10 return; 11 var dv = new DrawingVisual(); 12 var size = 90; 13 using (var conext = dv.RenderOpen()) 14 { 15 conext.PushOpacityMask(new ImageBrush(new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Images\pen.png", UriKind.Absolute)))); 16 conext.DrawRectangle(new SolidColorBrush(color), null, new Rect(0, 0, size, size)); 17 conext.Close(); 18 } 19 var rtb = new RenderTargetBitmap(size, size, 96d, 96d, PixelFormats.Pbgra32); 20 rtb.Render(dv); 21 imageSource = BitmapFrame.Create(rtb); 22 23 //Freezable 类提供特殊功能,以便在使用修改或复制开销很大的对象时帮助提高应用程序性能 24 //WPF中的Frozen(冻结)与线程及其他相关问题 25 imageSource.Freeze(); 26 } 27 28 //卡顿就是该函数造成,每写完一笔就会调用,当笔画过长,后果可想而知~ 29 protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes) 30 { 31 if (this.StylusPoints?.Count < 1) 32 return; 33 34 var p1 = new Point(double.NegativeInfinity, double.NegativeInfinity); 35 var w1 = this.width + 20; 36 37 38 for (int i = 0; i < StylusPoints.Count; i++) 39 { 40 var p2 = (Point)this.StylusPoints[i]; 41 42 var vector = p1 - p2; 43 44 var dx = (p2.X - p1.X) / vector.Length; 45 var dy = (p2.Y - p1.Y) / vector.Length; 46 47 var w2 = this.width; 48 if (w1 - vector.Length > this.width) 49 w2 = w1 - vector.Length; 50 51 for (int j = 0; j < vector.Length; j++) 52 { 53 var x = p2.X; 54 var y = p2.Y; 55 56 if (!double.IsInfinity(p1.X) && !double.IsInfinity(p1.Y)) 57 { 58 x = p1.X + dx; 59 y = p1.Y + dy; 60 } 61 62 drawingContext.DrawImage(imageSource, new Rect(x - w2 / 2.0, y - w2 / 2.0, w2, w2)); 63 64 p1 = new Point(x, y); 65 66 if (double.IsInfinity(vector.Length)) 67 break; 68 } 69 } 70 } 71 }

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1 public class ChinesebrushCanvas : InkCanvas 2 { 3 public ChinesebrushCanvas() 4 { 5 //当然要换上我们特地搞出来的ChinesebrushRenderer 6 this.DynamicRenderer = new ChinesebrushRenderer(); 7 } 8 9 10 protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e) 11 { 12 //感兴趣的童鞋,注释这一句看看? 13 this.Strokes.Remove(e.Stroke); 14 15 this.Strokes.Add(new ChinesebrushStroke(e.Stroke.StylusPoints, this.DefaultDrawingAttributes.Color)); 16 } 17 }

 笔画原图:

以上代码只是解决了1、2点,第三点嘛~毕竟每个人都有自己的粗细,大家自行体会~

 

吐槽一下:

本以为本篇文章能有点小小贡献,于是发布到“首页”,结果也就存活十多分钟,而且园内搜索还搜不到!

其实这个需求很久以前做项目就有提了,但那时候刚出来工作没多久【12年毕业,工作以后自学WPF】,还是一个菜鸟萌新,一篇相关文章都搜索不到啊不到!【手动哭泣】

之后也陆陆续续做了好多类似项目,但一直使用文中第一种方案,效果也能被客户接受。

哎,期待有缘人吧!毕竟WPF用的人还是太少!

也是,本篇文章没得个“抄袭”的罪名算好的了,还胆大包天的贴出原文链接!

最后【手动满地打滚撒泼~】

转载于:https://www.cnblogs.com/LCHL/p/9055642.html

最后

以上就是落寞可乐最近收集整理的关于WPF InkCanvas 毛笔效果的全部内容,更多相关WPF内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(105)

评论列表共有 0 条评论

立即
投稿
返回
顶部