如何在 SkiaSharp 中任意直接从屏幕上的 SVG 字符串绘制 SKPath?
How can I directly draw an SKPath from SVG string on screen arbitrarily in SkiaSharp?
我正在构建一个可以发送和接收 skia sharp 绘图的应用程序。 SKPath 序列化为 SVG 格式并发送。然后接收端必须反序列化并从 SVG 字符串中绘制 SKPath。但是,似乎不可能在 OnCanvasViewPaintSurface 事件之外执行此操作。
我目前正尝试在 Xamarin 示例解决方案的手指绘画示例中执行此操作。 DrawTestLine 方法应该绘制一条我绘制并序列化为 SVG 的徒手画线。实际上它无一例外地运行,但在屏幕上什么也不画。
非常感谢您提供任何帮助使其正常工作。
在下面查看我的修改:
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using TouchTracking;
using SkiaSharp;
using SkiaSharp.Views.Forms;
namespace SkiaSharpFormsDemos.Paths
{
public partial class FingerPaintPage : ContentPage
{
Dictionary<long, SKPath> inProgressPaths = new Dictionary<long, SKPath>();
List<SKPath> completedPaths = new List<SKPath>();
SKBitmap bitmap;
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Blue,
StrokeWidth = 10,
StrokeCap = SKStrokeCap.Round,
StrokeJoin = SKStrokeJoin.Round
};
public FingerPaintPage()
{
InitializeComponent();
DrawTestLine();
}
private void DrawTestLine()
{
var svgPath = "M851.953 371.006L865.957 438.527L874.922 462.995L880.957 453.997L884.941 441.011L893.965 427.874L895.957 418.233L900.938 415.006L902.93 405.02L898.945 403.998";
var testPath = SKPath.ParseSvgPathData(svgPath);
bitmap = new SKBitmap(1920, 1080);// (int)canvasView.CanvasSize.Width, (int)canvasView.CanvasSize.Height);
var canvas = new SKCanvas(bitmap);
canvas.Clear();
canvas.DrawPath(testPath, paint);
canvasView.InvalidateSurface();
}
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
switch (args.Type)
{
case TouchActionType.Pressed:
if (!inProgressPaths.ContainsKey(args.Id))
{
SKPath path = new SKPath();
path.MoveTo(ConvertToPixel(args.Location));
inProgressPaths.Add(args.Id, path);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Moved:
if (inProgressPaths.ContainsKey(args.Id))
{
SKPath path = inProgressPaths[args.Id];
path.LineTo(ConvertToPixel(args.Location));
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Released:
if (inProgressPaths.ContainsKey(args.Id))
{
completedPaths.Add(inProgressPaths[args.Id]);
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Cancelled:
if (inProgressPaths.ContainsKey(args.Id))
{
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
args.Surface.Canvas.DrawBitmap(bitmap, 0, 0);
SKCanvas canvas = args.Surface.Canvas;
canvas.Clear();
foreach (SKPath path in completedPaths)
{
canvas.DrawPath(path, paint);
}
foreach (SKPath path in inProgressPaths.Values)
{
canvas.DrawPath(path, paint);
}
}
SKPoint ConvertToPixel(Point pt)
{
return new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
(float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
}
}
}
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using TouchTracking;
using SkiaSharp;
using SkiaSharp.Views.Forms;
namespace SkiaSharpFormsDemos.Paths
{
public partial class FingerPaintPage : ContentPage
{
Dictionary<long, SKPath> inProgressPaths = new Dictionary<long, SKPath>();
List<SKPath> completedPaths = new List<SKPath>();
SKBitmap bitmap;
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Blue,
StrokeWidth = 10,
StrokeCap = SKStrokeCap.Round,
StrokeJoin = SKStrokeJoin.Round
};
SKPath testPath = SKPath.ParseSvgPathData("M851.953 371.006L865.957 438.527L874.922 462.995L880.957 453.997L884.941 441.011L893.965 427.874L895.957 418.233L900.938 415.006L902.93 405.02L898.945 403.998");
public FingerPaintPage()
{
InitializeComponent();
DrawTestLine();
}
private void DrawTestLine()
{
canvasView.InvalidateSurface();
}
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
switch (args.Type)
{
case TouchActionType.Pressed:
if (!inProgressPaths.ContainsKey(args.Id))
{
SKPath path = new SKPath();
path.MoveTo(ConvertToPixel(args.Location));
inProgressPaths.Add(args.Id, path);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Moved:
if (inProgressPaths.ContainsKey(args.Id))
{
SKPath path = inProgressPaths[args.Id];
path.LineTo(ConvertToPixel(args.Location));
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Released:
if (inProgressPaths.ContainsKey(args.Id))
{
completedPaths.Add(inProgressPaths[args.Id]);
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Cancelled:
if (inProgressPaths.ContainsKey(args.Id))
{
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
bitmap = new SKBitmap((int)canvasView.CanvasSize.Width, (int)canvasView.CanvasSize.Height);
var canvas = new SKCanvas(bitmap);
canvas.Clear();
canvas.DrawPath(testPath, paint);
args.Surface.Canvas.DrawBitmap(bitmap, 0, 0);
canvas.Clear();
foreach (SKPath path in completedPaths)
{
canvas.DrawPath(path, paint);
}
foreach (SKPath path in inProgressPaths.Values)
{
canvas.DrawPath(path, paint);
}
}
SKPoint ConvertToPixel(Point pt)
{
return new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
(float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
}
}
}
我正在构建一个可以发送和接收 skia sharp 绘图的应用程序。 SKPath 序列化为 SVG 格式并发送。然后接收端必须反序列化并从 SVG 字符串中绘制 SKPath。但是,似乎不可能在 OnCanvasViewPaintSurface 事件之外执行此操作。
我目前正尝试在 Xamarin 示例解决方案的手指绘画示例中执行此操作。 DrawTestLine 方法应该绘制一条我绘制并序列化为 SVG 的徒手画线。实际上它无一例外地运行,但在屏幕上什么也不画。
非常感谢您提供任何帮助使其正常工作。
在下面查看我的修改:
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using TouchTracking;
using SkiaSharp;
using SkiaSharp.Views.Forms;
namespace SkiaSharpFormsDemos.Paths
{
public partial class FingerPaintPage : ContentPage
{
Dictionary<long, SKPath> inProgressPaths = new Dictionary<long, SKPath>();
List<SKPath> completedPaths = new List<SKPath>();
SKBitmap bitmap;
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Blue,
StrokeWidth = 10,
StrokeCap = SKStrokeCap.Round,
StrokeJoin = SKStrokeJoin.Round
};
public FingerPaintPage()
{
InitializeComponent();
DrawTestLine();
}
private void DrawTestLine()
{
var svgPath = "M851.953 371.006L865.957 438.527L874.922 462.995L880.957 453.997L884.941 441.011L893.965 427.874L895.957 418.233L900.938 415.006L902.93 405.02L898.945 403.998";
var testPath = SKPath.ParseSvgPathData(svgPath);
bitmap = new SKBitmap(1920, 1080);// (int)canvasView.CanvasSize.Width, (int)canvasView.CanvasSize.Height);
var canvas = new SKCanvas(bitmap);
canvas.Clear();
canvas.DrawPath(testPath, paint);
canvasView.InvalidateSurface();
}
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
switch (args.Type)
{
case TouchActionType.Pressed:
if (!inProgressPaths.ContainsKey(args.Id))
{
SKPath path = new SKPath();
path.MoveTo(ConvertToPixel(args.Location));
inProgressPaths.Add(args.Id, path);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Moved:
if (inProgressPaths.ContainsKey(args.Id))
{
SKPath path = inProgressPaths[args.Id];
path.LineTo(ConvertToPixel(args.Location));
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Released:
if (inProgressPaths.ContainsKey(args.Id))
{
completedPaths.Add(inProgressPaths[args.Id]);
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Cancelled:
if (inProgressPaths.ContainsKey(args.Id))
{
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
args.Surface.Canvas.DrawBitmap(bitmap, 0, 0);
SKCanvas canvas = args.Surface.Canvas;
canvas.Clear();
foreach (SKPath path in completedPaths)
{
canvas.DrawPath(path, paint);
}
foreach (SKPath path in inProgressPaths.Values)
{
canvas.DrawPath(path, paint);
}
}
SKPoint ConvertToPixel(Point pt)
{
return new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
(float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
}
}
}
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using TouchTracking;
using SkiaSharp;
using SkiaSharp.Views.Forms;
namespace SkiaSharpFormsDemos.Paths
{
public partial class FingerPaintPage : ContentPage
{
Dictionary<long, SKPath> inProgressPaths = new Dictionary<long, SKPath>();
List<SKPath> completedPaths = new List<SKPath>();
SKBitmap bitmap;
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Blue,
StrokeWidth = 10,
StrokeCap = SKStrokeCap.Round,
StrokeJoin = SKStrokeJoin.Round
};
SKPath testPath = SKPath.ParseSvgPathData("M851.953 371.006L865.957 438.527L874.922 462.995L880.957 453.997L884.941 441.011L893.965 427.874L895.957 418.233L900.938 415.006L902.93 405.02L898.945 403.998");
public FingerPaintPage()
{
InitializeComponent();
DrawTestLine();
}
private void DrawTestLine()
{
canvasView.InvalidateSurface();
}
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
switch (args.Type)
{
case TouchActionType.Pressed:
if (!inProgressPaths.ContainsKey(args.Id))
{
SKPath path = new SKPath();
path.MoveTo(ConvertToPixel(args.Location));
inProgressPaths.Add(args.Id, path);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Moved:
if (inProgressPaths.ContainsKey(args.Id))
{
SKPath path = inProgressPaths[args.Id];
path.LineTo(ConvertToPixel(args.Location));
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Released:
if (inProgressPaths.ContainsKey(args.Id))
{
completedPaths.Add(inProgressPaths[args.Id]);
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Cancelled:
if (inProgressPaths.ContainsKey(args.Id))
{
inProgressPaths.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
bitmap = new SKBitmap((int)canvasView.CanvasSize.Width, (int)canvasView.CanvasSize.Height);
var canvas = new SKCanvas(bitmap);
canvas.Clear();
canvas.DrawPath(testPath, paint);
args.Surface.Canvas.DrawBitmap(bitmap, 0, 0);
canvas.Clear();
foreach (SKPath path in completedPaths)
{
canvas.DrawPath(path, paint);
}
foreach (SKPath path in inProgressPaths.Values)
{
canvas.DrawPath(path, paint);
}
}
SKPoint ConvertToPixel(Point pt)
{
return new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
(float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
}
}
}