Основы пути в SkiaSharp

Download Sample Скачайте пример

Изучение объекта SkPath SkiaSharp для объединения подключенных линий и кривых

Одной из наиболее важных функций графического пути является возможность определить, когда необходимо подключить несколько строк и когда они не должны быть подключены. Разница может быть значительной, так как вершины этих двух треугольников демонстрируют:

Two triangles showing the difference between connected and disconnected lines

Графический путь инкапсулируется SKPath объектом. Путь — это коллекция одного или нескольких контуров. Каждый контур представляет собой коллекцию подключенных прямых линий и кривых. Контуры не связаны друг с другом, но они могут визуально перекрываться. Иногда один контур может перекрываться.

Контур обычно начинается с вызова следующего метода SKPath:

  • MoveTo начало нового контура

Аргументом этого метода является одна точка, которую можно выразить как значение, так SKPoint и как отдельные координаты X и Y. Вызов MoveTo устанавливает точку в начале контура и начальную текущую точку. Можно вызвать следующие методы, чтобы продолжить контур с линией или кривой из текущей точки в точку, указанную в методе, которая затем становится новой текущей точкой:

  • LineTo Добавление прямой линии в путь
  • ArcTo добавление дуги, которая является линией по окружности круга или многоточия
  • CubicTo добавление кубической spline Bezier
  • QuadTo Добавление четырехкратной spline Bezier
  • ConicTo чтобы добавить рациональную квадратику 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, который закрывает контур. Разница имеет значительное значение:

Triple screenshot of the Two Triangle Contours page

Как видно, первый контур, очевидно, ряд трех подключенных линий, но конец не связывается с началом. Две линии перекрываются в верхней части. Второй контур, очевидно, закрыт, и был выполнен с одним меньшим LineTo числом вызовов, так как Close метод автоматически добавляет окончательную линию для закрытия контура.

SKCanvas определяет только один DrawPath метод, который в этой демонстрации вызывается дважды для заполнения и перечерка пути. Все контуры заполнены, даже те, которые не закрыты. Для заполнения незакрытых путей предполагается, что прямая линия существует между начальными и конечными точками контуров. Если удалить последний LineTo из первого контура или удалить Close вызов из второго контура, каждый контур будет иметь только две стороны, но будет заполнен, как если бы он был треугольником.

SKPath определяет множество других методов и свойств. Следующие методы добавляют целые контуры в путь, который может быть закрыт или не закрыт в зависимости от метода:

Помните, что 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;
    }
}

Вот работающая программа:

Triple screenshot of the Stroke Joins page

Соединение мизера состоит из резкой точки, где линии соединяются. Когда две линии присоединяются в небольшом углу, соединение мизера может стать довольно длинным. Чтобы предотвратить чрезмерно длинные соединения митеров, длина соединения мизера ограничена значением StrokeMiter свойства SKPaint. Соединение мизера, превышающее эту длину, отрезается, чтобы стать скосом соединения.