Основы пути в SkiaSharp
Изучение объекта SkPath SkiaSharp для объединения подключенных линий и кривых
Одной из наиболее важных функций графического пути является возможность определить, когда необходимо подключить несколько строк и когда они не должны быть подключены. Разница может быть значительной, так как вершины этих двух треугольников демонстрируют:
Графический путь инкапсулируется SKPath
объектом. Путь — это коллекция одного или нескольких контуров. Каждый контур представляет собой коллекцию подключенных прямых линий и кривых. Контуры не связаны друг с другом, но они могут визуально перекрываться. Иногда один контур может перекрываться.
Контур обычно начинается с вызова следующего метода SKPath
:
MoveTo
начало нового контура
Аргументом этого метода является одна точка, которую можно выразить как значение, так SKPoint
и как отдельные координаты X и Y. Вызов MoveTo
устанавливает точку в начале контура и начальную текущую точку. Можно вызвать следующие методы, чтобы продолжить контур с линией или кривой из текущей точки в точку, указанную в методе, которая затем становится новой текущей точкой:
LineTo
Добавление прямой линии в путьArcTo
добавление дуги, которая является линией по окружности круга или многоточияCubicTo
добавление кубической spline BezierQuadTo
Добавление четырехкратной spline BezierConicTo
чтобы добавить рациональную квадратику Spline Bezier, которая может точно отрисовывать конусные разделы (эллипсы, параболы и гиперболы)
Ни один из этих пяти методов не содержит всю информацию, необходимую для описания линии или кривой. Каждый из этих пяти методов работает в сочетании с текущей точкой, установленной вызовом метода сразу перед ним. Например, LineTo
метод добавляет прямую линию к контуру на основе текущей точки, поэтому параметр LineTo
является только одной точкой.
Класс SKPath
также определяет методы, которые имеют те же имена, что и эти шесть методов, но с R
начальным:
Это означает относительный R
. Эти методы имеют тот же синтаксис, что и соответствующие методы без R
текущей точки. Это удобно для рисования аналогичных частей пути в методе, который вы вызываете несколько раз.
Контур заканчивается другим вызовом MoveTo
или RMoveTo
, который начинает новый контур, или вызов, который Close
закрывает контур. Метод Close
автоматически добавляет прямую линию от текущей точки к первой точке контура и помечает путь как закрытый, что означает, что он будет отображаться без каких-либо заметок штриха.
Разница между открытыми и закрытыми контурами показана на странице "Два треугольника контуров ", которая использует SKPath
объект с двумя контурами для отрисовки двух треугольников. Первый контур открыт, а второй закрыт. Класс TwoTriangleContoursPage
выглядит так:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
// Create the path
SKPath path = new SKPath();
// Define the first contour
path.MoveTo(0.5f * info.Width, 0.1f * info.Height);
path.LineTo(0.2f * info.Width, 0.4f * info.Height);
path.LineTo(0.8f * info.Width, 0.4f * info.Height);
path.LineTo(0.5f * info.Width, 0.1f * info.Height);
// Define the second contour
path.MoveTo(0.5f * info.Width, 0.6f * info.Height);
path.LineTo(0.2f * info.Width, 0.9f * info.Height);
path.LineTo(0.8f * info.Width, 0.9f * info.Height);
path.Close();
// Create two SKPaint objects
SKPaint strokePaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Magenta,
StrokeWidth = 50
};
SKPaint fillPaint = new SKPaint
{
Style = SKPaintStyle.Fill,
Color = SKColors.Cyan
};
// Fill and stroke the path
canvas.DrawPath(path, fillPaint);
canvas.DrawPath(path, strokePaint);
}
Первый контур состоит из вызова MoveTo
использования координат X и Y, а не SKPoint
значения, а трех вызовов LineTo
рисования трех сторон треугольника. Второй контур имеет только два вызова LineTo
, но он заканчивает контур с вызовом Close
, который закрывает контур. Разница имеет значительное значение:
Как видно, первый контур, очевидно, ряд трех подключенных линий, но конец не связывается с началом. Две линии перекрываются в верхней части. Второй контур, очевидно, закрыт, и был выполнен с одним меньшим LineTo
числом вызовов, так как Close
метод автоматически добавляет окончательную линию для закрытия контура.
SKCanvas
определяет только один DrawPath
метод, который в этой демонстрации вызывается дважды для заполнения и перечерка пути. Все контуры заполнены, даже те, которые не закрыты. Для заполнения незакрытых путей предполагается, что прямая линия существует между начальными и конечными точками контуров. Если удалить последний LineTo
из первого контура или удалить Close
вызов из второго контура, каждый контур будет иметь только две стороны, но будет заполнен, как если бы он был треугольником.
SKPath
определяет множество других методов и свойств. Следующие методы добавляют целые контуры в путь, который может быть закрыт или не закрыт в зависимости от метода:
AddRect
AddRoundedRect
AddCircle
AddOval
AddArc
Добавление кривой по окружности многоточияAddPath
Добавление другого пути к текущему путиAddPathReverse
Добавление другого пути в обратном направлении
Помните, что SKPath
объект определяет только геометрию — серию точек и соединений. Только если SKPath
объект сочетается с SKPaint
объектом, это путь, отрисованный с определенным цветом, шириной штриха и т. д. Кроме того, помните, что SKPaint
объект, переданный DrawPath
методу, определяет характеристики всего пути. Если вы хотите нарисовать что-то, требующее нескольких цветов, необходимо использовать отдельный путь для каждого цвета.
Так же, как внешний вид начала и конца линии определяется крышкой штриха, внешний вид соединения между двумя линиями определяется соединением штриха. Укажите это, задав StrokeJoin
свойство SKPaint
элемента SKStrokeJoin
перечисления:
Miter
для точечных соединенийRound
для округленного соединенияBevel
для отрезанного соединения
На странице "Соединения штрихов" показаны три объединения штрихов с кодом, похожим на страницу "Крышки штрихов ". Это PaintSurface
обработчик событий в StrokeJoinsPage
классе:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
SKPaint textPaint = new SKPaint
{
Color = SKColors.Black,
TextSize = 75,
TextAlign = SKTextAlign.Right
};
SKPaint thickLinePaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Orange,
StrokeWidth = 50
};
SKPaint thinLinePaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Black,
StrokeWidth = 2
};
float xText = info.Width - 100;
float xLine1 = 100;
float xLine2 = info.Width - xLine1;
float y = 2 * textPaint.FontSpacing;
string[] strStrokeJoins = { "Miter", "Round", "Bevel" };
foreach (string strStrokeJoin in strStrokeJoins)
{
// Display text
canvas.DrawText(strStrokeJoin, xText, y, textPaint);
// Get stroke-join value
SKStrokeJoin strokeJoin;
Enum.TryParse(strStrokeJoin, out strokeJoin);
// Create path
SKPath path = new SKPath();
path.MoveTo(xLine1, y - 80);
path.LineTo(xLine1, y + 80);
path.LineTo(xLine2, y + 80);
// Display thick line
thickLinePaint.StrokeJoin = strokeJoin;
canvas.DrawPath(path, thickLinePaint);
// Display thin line
canvas.DrawPath(path, thinLinePaint);
y += 3 * textPaint.FontSpacing;
}
}
Вот работающая программа:
Соединение мизера состоит из резкой точки, где линии соединяются. Когда две линии присоединяются в небольшом углу, соединение мизера может стать довольно длинным. Чтобы предотвратить чрезмерно длинные соединения митеров, длина соединения мизера ограничена значением StrokeMiter
свойства SKPaint
. Соединение мизера, превышающее эту длину, отрезается, чтобы стать скосом соединения.