improve:多指书写
优化性能
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
@@ -8,18 +9,19 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
public class VisualCanvas : FrameworkElement
|
||||
{
|
||||
private readonly List<DrawingVisual> _visuals = new List<DrawingVisual>();
|
||||
|
||||
protected override Visual GetVisualChild(int index)
|
||||
{
|
||||
return Visual;
|
||||
if (index < 0 || index >= _visuals.Count)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
return _visuals[index];
|
||||
}
|
||||
|
||||
protected override int VisualChildrenCount => 1;
|
||||
protected override int VisualChildrenCount => _visuals.Count;
|
||||
|
||||
public VisualCanvas(DrawingVisual visual)
|
||||
public VisualCanvas()
|
||||
{
|
||||
Visual = visual;
|
||||
AddVisualChild(visual);
|
||||
|
||||
CacheMode = new BitmapCache();
|
||||
|
||||
RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality);
|
||||
@@ -27,17 +29,32 @@ namespace Ink_Canvas.Helpers
|
||||
RenderOptions.SetCachingHint(this, CachingHint.Cache);
|
||||
}
|
||||
|
||||
public DrawingVisual Visual { get; }
|
||||
public void AddVisual(DrawingVisual visual)
|
||||
{
|
||||
if (visual == null) return;
|
||||
_visuals.Add(visual);
|
||||
AddVisualChild(visual);
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var visual in _visuals)
|
||||
{
|
||||
RemoveVisualChild(visual);
|
||||
}
|
||||
_visuals.Clear();
|
||||
}
|
||||
|
||||
public IReadOnlyList<DrawingVisual> Visuals => _visuals;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于显示笔迹的类
|
||||
/// </summary>
|
||||
public class StrokeVisual : DrawingVisual
|
||||
public class StrokeVisual
|
||||
{
|
||||
private bool _needsRedraw = true;
|
||||
private int _lastPointCount = 0;
|
||||
private const int REDRAW_THRESHOLD = 3;
|
||||
private int _lastDrawnPointCount = 0;
|
||||
private const int INCREMENTAL_DRAW_THRESHOLD = 2;
|
||||
private VisualCanvas _visualCanvas;
|
||||
|
||||
/// <summary>
|
||||
/// 创建显示笔迹的类
|
||||
@@ -59,10 +76,6 @@ namespace Ink_Canvas.Helpers
|
||||
public StrokeVisual(DrawingAttributes drawingAttributes)
|
||||
{
|
||||
_drawingAttributes = drawingAttributes;
|
||||
|
||||
RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality);
|
||||
RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
|
||||
RenderOptions.SetCachingHint(this, CachingHint.Cache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,6 +83,14 @@ namespace Ink_Canvas.Helpers
|
||||
/// </summary>
|
||||
public Stroke Stroke { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置关联的VisualCanvas
|
||||
/// </summary>
|
||||
public void SetVisualCanvas(VisualCanvas visualCanvas)
|
||||
{
|
||||
_visualCanvas = visualCanvas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在笔迹中添加点
|
||||
/// </summary>
|
||||
@@ -80,16 +101,61 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
var collection = new StylusPointCollection { point };
|
||||
Stroke = new Stroke(collection) { DrawingAttributes = _drawingAttributes };
|
||||
_lastPointCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stroke.StylusPoints.Add(point);
|
||||
_lastPointCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 标记需要重绘
|
||||
_needsRedraw = true;
|
||||
/// <summary>
|
||||
/// 绘制点段到新的DrawingVisual
|
||||
/// </summary>
|
||||
private void DrawSegmentToNewVisual(int startIndex, int endIndex)
|
||||
{
|
||||
if (Stroke == null || Stroke.StylusPoints.Count == 0 || _visualCanvas == null) return;
|
||||
if (startIndex >= endIndex || startIndex < 0 || endIndex > Stroke.StylusPoints.Count) return;
|
||||
|
||||
var points = Stroke.StylusPoints;
|
||||
var drawingAttributes = Stroke.DrawingAttributes;
|
||||
|
||||
// 创建新的DrawingVisual用于绘制这个点段
|
||||
var segmentVisual = new DrawingVisual();
|
||||
|
||||
RenderOptions.SetBitmapScalingMode(segmentVisual, BitmapScalingMode.LowQuality);
|
||||
RenderOptions.SetEdgeMode(segmentVisual, EdgeMode.Aliased);
|
||||
RenderOptions.SetCachingHint(segmentVisual, CachingHint.Cache);
|
||||
|
||||
using (var dc = segmentVisual.RenderOpen())
|
||||
{
|
||||
var pen = new Pen(new SolidColorBrush(drawingAttributes.Color), drawingAttributes.Width);
|
||||
pen.StartLineCap = PenLineCap.Round;
|
||||
pen.EndLineCap = PenLineCap.Round;
|
||||
pen.LineJoin = PenLineJoin.Round;
|
||||
|
||||
// 绘制指定范围内的点段
|
||||
if (endIndex - startIndex >= 2)
|
||||
{
|
||||
// 多个点,绘制线段
|
||||
for (int i = startIndex; i < endIndex - 1 && i < points.Count - 1; i++)
|
||||
{
|
||||
var startPoint = new Point(points[i].X, points[i].Y);
|
||||
var endPoint = new Point(points[i + 1].X, points[i + 1].Y);
|
||||
dc.DrawLine(pen, startPoint, endPoint);
|
||||
}
|
||||
}
|
||||
else if (endIndex - startIndex == 1 && startIndex < points.Count)
|
||||
{
|
||||
// 只有一个点,绘制圆点
|
||||
var brush = new SolidColorBrush(drawingAttributes.Color);
|
||||
var point = points[startIndex];
|
||||
dc.DrawEllipse(brush, null, new Point(point.X, point.Y),
|
||||
drawingAttributes.Width / 2, drawingAttributes.Height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// 将新的DrawingVisual添加到VisualCanvas中
|
||||
_visualCanvas.AddVisual(segmentVisual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -97,30 +163,47 @@ namespace Ink_Canvas.Helpers
|
||||
/// </summary>
|
||||
public void Redraw()
|
||||
{
|
||||
if (!_needsRedraw || Stroke == null) return;
|
||||
if (Stroke == null || _visualCanvas == null) return;
|
||||
|
||||
if (_lastPointCount % REDRAW_THRESHOLD != 0 && _lastPointCount > REDRAW_THRESHOLD)
|
||||
var currentPointCount = Stroke.StylusPoints.Count;
|
||||
if (currentPointCount == 0) return;
|
||||
|
||||
// 计算新增的点数
|
||||
int newPointCount = currentPointCount - _lastDrawnPointCount;
|
||||
|
||||
// 如果新增点数达到阈值,才进行增量绘制
|
||||
if (newPointCount >= INCREMENTAL_DRAW_THRESHOLD || _lastDrawnPointCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var dc = RenderOpen())
|
||||
if (_lastDrawnPointCount == 0)
|
||||
{
|
||||
Stroke.Draw(dc);
|
||||
// 首次绘制:绘制所有点
|
||||
DrawSegmentToNewVisual(0, currentPointCount);
|
||||
_lastDrawnPointCount = currentPointCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 从上次绘制的最后一个点开始
|
||||
int startIndex = Math.Max(0, _lastDrawnPointCount - 1);
|
||||
DrawSegmentToNewVisual(startIndex, currentPointCount);
|
||||
_lastDrawnPointCount = currentPointCount;
|
||||
}
|
||||
_needsRedraw = false;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制重绘
|
||||
/// </summary>
|
||||
public void ForceRedraw()
|
||||
{
|
||||
_needsRedraw = true;
|
||||
if (_visualCanvas != null)
|
||||
{
|
||||
_visualCanvas.Clear();
|
||||
}
|
||||
_lastDrawnPointCount = 0;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
|
||||
@@ -482,8 +482,8 @@ namespace Ink_Canvas
|
||||
|
||||
var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone());
|
||||
StrokeVisualList[id] = strokeVisual;
|
||||
StrokeVisualList[id] = strokeVisual;
|
||||
var visualCanvas = new VisualCanvas(strokeVisual);
|
||||
var visualCanvas = new VisualCanvas();
|
||||
strokeVisual.SetVisualCanvas(visualCanvas);
|
||||
VisualCanvasList[id] = visualCanvas;
|
||||
inkCanvas.Children.Add(visualCanvas);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user