在做白板书写的时候,会有各种笔的绘制,比如 书写笔、马克笔、演示笔等等。粉笔的功能需求也是很有必要的。
上网搜了一圈,几乎没有绘制粉笔的。
有的是毛笔、楷体等绘制的如下博客:
wpf inkcanvas customink 毛笔效果_wpf inkcanvas 笔锋-CSDN博客
【WPF】 InkCanvas 书写毛笔效果-CSDN博客
绘制粉笔的思路,一开始是源于 github的一个仓库:mychalkboard/MyChalkBoard: MyChalkBoard is an application for you to quickly sketch with a chalk.
对应的网页的链接:MyChalkBoard
思路:就是用一个通用的笔头(ImageSource),利用Stroke 捕获到的StylusPoints的点,生成对应的点的坐标,调用drawingContext.DrawImage,绘制图案
1、生成笔头
找UI绘制一个粉笔形状的图片,以Png为例:
2、支持修改颜色
参考了该博文: 2018-8-10-WPF-修改图片颜色-CSDN博客
只要是修改 WriteableBitmap 的RGBA的值,达到替换颜色的效果
public static unsafe ImageSource ConvertImageColor(Color newColor, WriteableBitmap writableBitmap){var bitmap = writableBitmap;if (bitmap == null){return null;}bitmap.Lock();var length = bitmap.PixelWidth * bitmap.PixelHeight *bitmap.Format.BitsPerPixel / 8;var backBuffer = (byte*)bitmap.BackBuffer;var byteList = new byte[length];for (int i = 0; i + 4 < length; i = i + 4){byteList[i] = newColor.B;byteList[i + 1] = newColor.G;byteList[i + 2] = newColor.R;byteList[i + 3] = backBuffer[i + 3];}bitmap.Unlock();bitmap = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight, 96, 96,bitmap.Format, bitmap.Palette);bitmap.Lock();bitmap.WritePixels(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight),byteList, bitmap.BackBufferStride, 0);bitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));bitmap.Unlock();return bitmap;}
3、收集点迹
主要是调用了我们组内自己封装的一套基于鼠标、触摸汇总的笔迹点迹收集的算法,通过 Down、Move、Up以及分段汇总的方式,收集并呈现笔迹
4、自定义补点
由于通过设备采集到的点,会有疏密的区分,所以对于比较稀疏的点,需要通过补点的方式,达到减少锯齿的效果,具体的补点的距离,因业务需要不同,可以通过调节参数的方式做适配
//标识上一个点var previousPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);for (int i = 0; i < stylusPoints.Count; i++){var pressureFactor = stylusPoints[i].PressureFactor * 2;var currentPoint = stylusPoints[i].ToPoint();var vector = previousPoint - currentPoint;var newWidth = width * pressureFactor;//作为基准值var baseWidth = newWidth / 1.5;if (!double.IsInfinity(vector.Length) && vector.Length > baseWidth){var w2 = newWidth;if (newWidth - vector.Length > newWidth)w2 = newWidth - vector.Length;var newPointCount = (int)(vector.Length / (baseWidth)) * 2;var dx = (currentPoint.X - previousPoint.X) / newPointCount;var dy = (currentPoint.Y - previousPoint.Y) / newPointCount;for (int pointCount = 0; pointCount < newPointCount; pointCount++){var newX = previousPoint.X + dx * (pointCount + 1);var newY = previousPoint.Y + dy * (pointCount + 1);drawingContext.DrawImage(imageSource, new Rect(newX - w2, newY - w2, w2 * 2, w2 * 2));}}else{Rect rectangle = new Rect(currentPoint.X - newWidth, currentPoint.Y - newWidth, newWidth * 2, newWidth * 2);drawingContext.DrawImage(imageSource, rectangle);}previousPoint = currentPoint;
5、绘制点迹
通过以上4个前提步骤,就可以计算出来笔迹的大小,通过调用 drawingContext.DrawImage 的方式把带粉笔头的Image绘制出来
drawingContext.DrawImage(imageSource, new Rect(newX - w2, newY - w2, w2 * 2, w2 * 2));
6、效果如下:
普通书写
重力书写: