using System; using System.Collections.Generic; using System.Windows; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; namespace Ink_Canvas.Helpers { public class VisualCanvas : FrameworkElement { private readonly List _visuals = new List(); protected override Visual GetVisualChild(int index) { if (index < 0 || index >= _visuals.Count) throw new ArgumentOutOfRangeException(nameof(index)); return _visuals[index]; } protected override int VisualChildrenCount => _visuals.Count; public VisualCanvas() { CacheMode = new BitmapCache(); RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.HighQuality); RenderOptions.SetEdgeMode(this, EdgeMode.Aliased); RenderOptions.SetCachingHint(this, CachingHint.Cache); } 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 Visuals => _visuals; } /// /// 用于显示笔迹的类 /// public class StrokeVisual { private int _lastDrawnPointCount = 0; private const int INCREMENTAL_DRAW_THRESHOLD = 2; private VisualCanvas _visualCanvas; /// /// 创建显示笔迹的类 /// public StrokeVisual() : this(new DrawingAttributes { Color = Colors.Red, //FitToCurve = true, Width = 3, Height = 3 }) { } /// /// 创建显示笔迹的类 /// /// public StrokeVisual(DrawingAttributes drawingAttributes) { _drawingAttributes = drawingAttributes; } /// /// 设置或获取显示的笔迹 /// public Stroke Stroke { set; get; } /// /// 设置关联的VisualCanvas /// public void SetVisualCanvas(VisualCanvas visualCanvas) { _visualCanvas = visualCanvas; } /// /// 在笔迹中添加点 /// /// public void Add(StylusPoint point) { if (Stroke == null) { var collection = new StylusPointCollection { point }; Stroke = new Stroke(collection) { DrawingAttributes = _drawingAttributes }; } else { Stroke.StylusPoints.Add(point); } } /// /// 绘制点段到新的DrawingVisual /// 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.HighQuality); 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); } /// /// 重新画出笔迹 /// public void Redraw() { if (Stroke == null || _visualCanvas == null) return; var currentPointCount = Stroke.StylusPoints.Count; if (currentPointCount == 0) return; // 计算新增的点数 int newPointCount = currentPointCount - _lastDrawnPointCount; // 如果新增点数达到阈值,才进行增量绘制 if (newPointCount >= INCREMENTAL_DRAW_THRESHOLD || _lastDrawnPointCount == 0) { try { if (_lastDrawnPointCount == 0) { // 首次绘制:绘制所有点 DrawSegmentToNewVisual(0, currentPointCount); _lastDrawnPointCount = currentPointCount; } else { // 从上次绘制的最后一个点开始 int startIndex = Math.Max(0, _lastDrawnPointCount - 1); DrawSegmentToNewVisual(startIndex, currentPointCount); _lastDrawnPointCount = currentPointCount; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); } } } /// /// 强制重绘 /// public void ForceRedraw() { if (_visualCanvas != null) { _visualCanvas.Clear(); } _lastDrawnPointCount = 0; Redraw(); } private readonly DrawingAttributes _drawingAttributes; } }