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
+113 -30
View File
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Windows; using System.Windows;
using System.Windows.Ink; using System.Windows.Ink;
using System.Windows.Input; using System.Windows.Input;
@@ -8,18 +9,19 @@ namespace Ink_Canvas.Helpers
{ {
public class VisualCanvas : FrameworkElement public class VisualCanvas : FrameworkElement
{ {
private readonly List<DrawingVisual> _visuals = new List<DrawingVisual>();
protected override Visual GetVisualChild(int index) 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(); CacheMode = new BitmapCache();
RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality); RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality);
@@ -27,17 +29,32 @@ namespace Ink_Canvas.Helpers
RenderOptions.SetCachingHint(this, CachingHint.Cache); 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>
/// 用于显示笔迹的类 /// 用于显示笔迹的类
/// </summary> /// </summary>
public class StrokeVisual : DrawingVisual public class StrokeVisual
{ {
private bool _needsRedraw = true; private int _lastDrawnPointCount = 0;
private int _lastPointCount = 0; private const int INCREMENTAL_DRAW_THRESHOLD = 2;
private const int REDRAW_THRESHOLD = 3; private VisualCanvas _visualCanvas;
/// <summary> /// <summary>
/// 创建显示笔迹的类 /// 创建显示笔迹的类
@@ -59,10 +76,6 @@ namespace Ink_Canvas.Helpers
public StrokeVisual(DrawingAttributes drawingAttributes) public StrokeVisual(DrawingAttributes drawingAttributes)
{ {
_drawingAttributes = drawingAttributes; _drawingAttributes = drawingAttributes;
RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.LowQuality);
RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
RenderOptions.SetCachingHint(this, CachingHint.Cache);
} }
/// <summary> /// <summary>
@@ -70,6 +83,14 @@ namespace Ink_Canvas.Helpers
/// </summary> /// </summary>
public Stroke Stroke { set; get; } public Stroke Stroke { set; get; }
/// <summary>
/// 设置关联的VisualCanvas
/// </summary>
public void SetVisualCanvas(VisualCanvas visualCanvas)
{
_visualCanvas = visualCanvas;
}
/// <summary> /// <summary>
/// 在笔迹中添加点 /// 在笔迹中添加点
/// </summary> /// </summary>
@@ -80,16 +101,61 @@ namespace Ink_Canvas.Helpers
{ {
var collection = new StylusPointCollection { point }; var collection = new StylusPointCollection { point };
Stroke = new Stroke(collection) { DrawingAttributes = _drawingAttributes }; Stroke = new Stroke(collection) { DrawingAttributes = _drawingAttributes };
_lastPointCount = 1;
} }
else else
{ {
Stroke.StylusPoints.Add(point); Stroke.StylusPoints.Add(point);
_lastPointCount++; }
}
/// <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中
_needsRedraw = true; _visualCanvas.AddVisual(segmentVisual);
} }
/// <summary> /// <summary>
@@ -97,22 +163,35 @@ namespace Ink_Canvas.Helpers
/// </summary> /// </summary>
public void Redraw() 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;
return;
}
try // 计算新增的点数
int newPointCount = currentPointCount - _lastDrawnPointCount;
// 如果新增点数达到阈值,才进行增量绘制
if (newPointCount >= INCREMENTAL_DRAW_THRESHOLD || _lastDrawnPointCount == 0)
{ {
using (var dc = RenderOpen()) try
{ {
Stroke.Draw(dc); if (_lastDrawnPointCount == 0)
{
// 首次绘制:绘制所有点
DrawSegmentToNewVisual(0, currentPointCount);
_lastDrawnPointCount = currentPointCount;
}
else
{
// 从上次绘制的最后一个点开始
int startIndex = Math.Max(0, _lastDrawnPointCount - 1);
DrawSegmentToNewVisual(startIndex, currentPointCount);
_lastDrawnPointCount = currentPointCount;
}
} }
_needsRedraw = false; catch { }
} }
catch { }
} }
/// <summary> /// <summary>
@@ -120,7 +199,11 @@ namespace Ink_Canvas.Helpers
/// </summary> /// </summary>
public void ForceRedraw() public void ForceRedraw()
{ {
_needsRedraw = true; if (_visualCanvas != null)
{
_visualCanvas.Clear();
}
_lastDrawnPointCount = 0;
Redraw(); Redraw();
} }
+2 -2
View File
@@ -482,8 +482,8 @@ namespace Ink_Canvas
var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone()); var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone());
StrokeVisualList[id] = strokeVisual; StrokeVisualList[id] = strokeVisual;
StrokeVisualList[id] = strokeVisual; var visualCanvas = new VisualCanvas();
var visualCanvas = new VisualCanvas(strokeVisual); strokeVisual.SetVisualCanvas(visualCanvas);
VisualCanvasList[id] = visualCanvas; VisualCanvasList[id] = visualCanvas;
inkCanvas.Children.Add(visualCanvas); inkCanvas.Children.Add(visualCanvas);