使用WPF的自定义InkCanvas实现毛笔效果

来源:互联网 发布:mac 退出全屏 编辑:程序博客网 时间:2024/04/29 15:07


PS:如果你想用InkCanvas来实现的话,我觉得还是放弃了,卡到爆,根本找不到从哪里下手优化

首先找到了一图类似于毛笔笔触的图片,有了这张图,问题就简单多了。

要做的就只有粗细的处理。先围观下最后的效果。


自定义InkCanvas的示例已经很多,我就不再写了。

主要看下需要重写的两个方法

类一 public class MaoBiDynamicRenderer : DynamicRenderer


重写OnDraw方法


        protected override void OnDraw(System.Windows.Media.DrawingContext drawingContext, System.Windows.Input.StylusPointCollection stylusPoints, System.Windows.Media.Geometry geometry, System.Windows.Media.Brush fillBrush)        {            ImageSource img = new BitmapImage(new Uri("pack://application:,,,/Resources/maobi.png"));            //前一个点的绘制。            Point prevPoint = new Point(double.NegativeInfinity,                                        double.NegativeInfinity);            var w = Global.StrokeWidth + 15;    //输出时笔刷的实际大小            Point pt = new Point(0, 0);            Vector v = new Vector();            //前一个点与当前点的距离            var subtractY = 0d;                 //当前点处前一点的Y偏移            var subtractX = 0d;                 //当前点处前一点的X偏移            var pointWidth = Global.StrokeWidth;             double x = 0, y = 0;            for (int i = 0; i < stylusPoints.Count; i++)            {                pt = (Point)stylusPoints[i];                v = Point.Subtract(prevPoint, pt);                Debug.WriteLine("X " + pt.X + "\t" + pt.Y);                subtractY = (pt.Y - prevPoint.Y) / v.Length;    //设置stylusPoints两个点之间需要填充的XY偏移                subtractX = (pt.X - prevPoint.X) / v.Length;                if (w - v.Length < Global.StrokeWidth)          //控制笔刷大小                {                    pointWidth = Global.StrokeWidth;                }                else                {                    pointWidth = w - v.Length;                  //在两个点距离越大的时候,笔刷所展示的大小越小                }                for (double j = 0; j < v.Length; j = j + 1d)    //填充stylusPoints两个点之间                {                    x = 0; y = 0;                    if (prevPoint.X == double.NegativeInfinity || prevPoint.Y == double.NegativeInfinity || double.PositiveInfinity == prevPoint.X || double.PositiveInfinity == prevPoint.Y)                    {                        y = pt.Y;                        x = pt.X;                    }                    else                    {                        y = prevPoint.Y + subtractY;                        x = prevPoint.X + subtractX;                    }                    drawingContext.DrawImage(img, new Rect(x - pointWidth / 2, y - pointWidth / 2, pointWidth, pointWidth));    //在当前点画笔刷图片                    prevPoint = new Point(x, y);                    if (double.IsNegativeInfinity(v.Length) || double.IsPositiveInfinity(v.Length))                    { break; }                }            }            stylusPoints = null;        }


类二MaoBiStroke : Stroke

重写DrawCore方法代码内容与上面的一致



效果基本上是出来了,但是问题来了。在InkCanvas如果有大量的笔触信息,画得又比较快时,CPU一直占用在14左右,而且不会降。获取到的点也会乱跳画出来就很不爽。

于是我就在每画一笔之后,把这个保存到了一张图里面当成InkCanvas的背景看起来就像是写的一样了。


0 0
原创粉丝点击