DrawTool画笔之纹理笔
先上图:
今天我们要实现的是DrawTool画笔集合中的一种纹理笔,很多人可能对纹理笔概念还比较生疏,其实如果你接触过类似一些教育行业交互式白板的话,对纹理笔并不会感到陌生,纹理笔我们可以简单的理解为是一种通过图片来呈现笔迹的方式.在继续下面的阅读前,你有必要先了解下以下知识:
- 1.WPF中笔迹线程处理模型
- 2.自定义呈现笔迹
- 3.截获触笔输入
通过上面的文章,我们知道DynamicRenderer为我们提供是呈现,而Stroke是最后我们生成笔迹,如果要实现纹理笔,我们需要重载DynamicRenderer的OnDraw和Stroke的DrawCore方法.
1. 自定义Stroke
public class TextureStroke : Stroke { private System.Windows.Media.ImageSource imageSource_; //纹理图片 private string textureFile_; public TextureStroke(StylusPointCollection stylusPoints, DrawingAttributes da , string file ) : base(stylusPoints, da) { this.textureFile_ = file; this.imageSource_ = new System.Windows.Media.Imaging.BitmapImage(new Uri(this.textureFile_)); } /// <summary> /// 实现绘制 /// </summary> /// <param name="drawingContext"></param> /// <param name="drawingAttributes"></param> protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes) { double width = drawingAttributes.Width * 2.0; System.Windows.Media.StreamGeometry streamGeometry = new System.Windows.Media.StreamGeometry(); using (System.Windows.Media.StreamGeometryContext streamGeometryContext = streamGeometry.Open()) { streamGeometryContext.BeginFigure((Point)base.StylusPoints[0], false, false); foreach (System.Windows.Input.StylusPoint current in base.StylusPoints) { streamGeometryContext.LineTo((Point)current, true, true); } streamGeometryContext.Close(); } DrawTexture(streamGeometry, this.imageSource_, drawingContext, width, this.textureFile_); } public static void DrawTexture(Geometry geometry, ImageSource imageSource, DrawingContext drawingContext, double width, string imagePath) { Rect rc = geometry.Bounds; DrawingBrush drawingBrush = new DrawingBrush(new ImageDrawing { Rect = rc, ImageSource = imageSource }); drawingBrush.TileMode = TileMode.Tile; Uri uriSource = new Uri(imagePath); BitmapImage bitmapImage = new BitmapImage(uriSource); drawingBrush.Viewport = new Rect(0.0, 0.0, (double)bitmapImage.PixelWidth, (double)bitmapImage.PixelHeight); drawingBrush.ViewportUnits = BrushMappingMode.Absolute; PathGeometry widenedPathGeometry = geometry.GetWidenedPathGeometry(new Pen(null, width) { StartLineCap = PenLineCap.Round, EndLineCap = PenLineCap.Round }); Pen pen = new Pen(drawingBrush, 80.0); drawingContext.PushClip(widenedPathGeometry); drawingContext.DrawRectangle(drawingBrush, pen, rc); drawingContext.Pop(); } }
2.实例应用
这里我们使用到上篇文章中介绍的多点触摸画板 ,修改其中_startStroke方法中stroke对象的生成,相应代码如下:
bool isTexturePen = true ; // 外部定义的私有变量 private void _startStroke(object device, Point inputPosition){ // ... { some code } //==这里根据变量isTexturePen来判断使用默认的stroke还是自定义的stroke Stroke stroke = isTexturePen==true ? new TextureStroke( stylusPointCollection , this._inkCanvas.DefaultDrawingAttributes,"c:\\1.png") : new Stroke(stylusPointCollection); //end // .... { some code } }
3. 结束
DrawTool系列文章中涉及的代码都是通过修改后的,仅仅适用于demo场景,如果需要商业请自行修改,包括性能上的调整.