improve:多指书写

优化性能
This commit is contained in:
2025-12-20 19:55:37 +08:00
parent a922654c17
commit d011d2ba8a
2 changed files with 115 additions and 32 deletions
+111 -28
View File
@@ -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();
}
+2 -2
View File
@@ -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);