联系QQ:715705486 18662431387
用wpf来做毛笔书写效果,需要自定义inkcanvas,基本效果可以,就是连续画很长的笔触时会有卡顿现象。解决方法,做一个判断,当笔触超过一定长度则停止。
核心代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input;
using System.Windows.Ink;
using System.Windows.Media.Imaging;
namespace WpfApplication1
{
class CustomRenderingInkCanvas:InkCanvas
{
CustomDynamicRenderer customRenderer = new CustomDynamicRenderer();
public CustomRenderingInkCanvas()
: base()
{
// Use the custom dynamic renderer on the
// custom InkCanvas.
this.DynamicRenderer = customRenderer;
}
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
{
// Remove the original stroke and add a custom stroke.
this.Strokes.Remove(e.Stroke);
CustomStroke customStroke = new CustomStroke(e.Stroke.StylusPoints);
this.Strokes.Add(customStroke);
// Pass the custom stroke to base class' OnStrokeCollected method.
InkCanvasStrokeCollectedEventArgs args =
new InkCanvasStrokeCollectedEventArgs(customStroke);
base.OnStrokeCollected(args);
}
}
// A class for rendering custom strokes
class CustomStroke : Stroke
{
Brush brush;
Pen pen;
public CustomStroke(StylusPointCollection stylusPoints)
: base(stylusPoints)
{
// Create the Brush and Pen used for drawing.
brush = new LinearGradientBrush(Colors.Red, Colors.Blue, 10d);
pen = new Pen(brush, 2d);
}
protected override void DrawCore(DrawingContext drawingContext,
DrawingAttributes drawingAttributes)
{
ImageSource img = new BitmapImage(new Uri(@"1.png", UriKind.RelativeOrAbsolute));
//前一个点的绘制。
Point prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);
int w = 10 + 15; //输出时笔刷的实际大小
Point pt = new Point(0, 0);
Vector v = new Vector(); //前一个点与当前点的距离
var subtractY = 0d; //当前点处前一点的Y偏移
var subtractX = 0d; //当前点处前一点的X偏移
var pointWidth = 10;
double x = 0, y = 0;
for (int i = 0; i < this.StylusPoints.Count; i++)
{
pt = (Point)this.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 < 10) //控制笔刷大小
{
pointWidth = 10;
}
else
{
pointWidth = w - Convert.ToInt32(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; }
}
}
// this.StylusPoints = null;
//// Allocate memory to store the previous point to draw from.
//Point prevPoint = new Point(double.NegativeInfinity,
// double.NegativeInfinity);
//// Draw linear gradient ellipses between
//// all the StylusPoints in the Stroke.
//for (int i = 0; i < this.StylusPoints.Count; i++)
//{
// Point pt = (Point)this.StylusPoints[i];
// Vector v = Point.Subtract(prevPoint, pt);
// // Only draw if we are at least 4 units away
// // from the end of the last ellipse. Otherwise,
// // we're just redrawing and wasting cycles.
// if (v.Length > 4)
// {
// // Set the thickness of the stroke
// // based on how hard the user pressed.
// double radius = this.StylusPoints[i].PressureFactor * 10d;
// drawingContext.DrawEllipse(brush, pen, pt, radius, radius);
// prevPoint = pt;
// }
//}
}
}
class CustomDynamicRenderer : DynamicRenderer
{
[ThreadStatic]
static private Brush brush = null;
[ThreadStatic]
static private Pen pen = null;
private Point prevPoint;
protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
// Allocate memory to store the previous point to draw from.
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
base.OnStylusDown(rawStylusInput);
}
protected override void OnDraw(DrawingContext drawingContext,
StylusPointCollection stylusPoints,
Geometry geometry, Brush fillBrush)
{
ImageSource img = new BitmapImage(new Uri(@"1.png",UriKind.RelativeOrAbsolute));
//前一个点的绘制。
Point prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);
int w = 10 + 15; //输出时笔刷的实际大小
Point pt = new Point(0, 0);
Vector v = new Vector(); //前一个点与当前点的距离
var subtractY = 0d; //当前点处前一点的Y偏移
var subtractX = 0d; //当前点处前一点的X偏移
var pointWidth = 10;
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 < 10) //控制笔刷大小
{
pointWidth = 10;
}
else
{
pointWidth = w - Convert.ToInt32(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;
//// Create a new Brush, if necessary.
//if (brush == null)
//{
// brush = new LinearGradientBrush(Colors.Red, Colors.Blue, 20d);
//}
//// Create a new Pen, if necessary.
//if (pen == null)
//{
// pen = new Pen(brush, 2d);
//}
//// Draw linear gradient ellipses between
//// all the StylusPoints that have come in.
//for (int i = 0; i < stylusPoints.Count; i++)
//{
// Point pt = (Point)stylusPoints[i];
// Vector v = Point.Subtract(prevPoint, pt);
// // Only draw if we are at least 4 units away
// // from the end of the last ellipse. Otherwise,
// // we're just redrawing and wasting cycles.
// if (v.Length > 4)
// {
// // Set the thickness of the stroke based
// // on how hard the user pressed.
// double radius = stylusPoints[i].PressureFactor * 10d;
// drawingContext.DrawEllipse(brush, pen, pt, radius, radius);
// prevPoint = pt;
// }
//}
}
}
}
作者:yz qq:715705486
效果图如下:
|
|