Три способа нарисовать дугу
Дуга — это кривая по окружности эллипса, например округленные части этого знака бесконечности:

Несмотря на простоту этого определения, невозможно определить функцию рисования дуги, удовлетворяющую всем требованиям, и, следовательно, нет консенсуса среди графических систем о том, как лучше всего нарисовать дугу. По этой причине SKPath класс не ограничивается одним подходом.
SKPath определяет AddArc метод, пять различных ArcTo методов и два относительных RArcTo метода. Эти методы делятся на три категории, представляющие три очень разных подхода к указанию дуги. Какой из них вы используете, зависит от сведений, доступных для определения дуги, и от того, как эта дуга вписывается в другую графику, которую вы рисуете.
Угловая дуга
Подход с угловой дугой к рисованию дуг требует указания прямоугольника, ограничивающего эллипс. Дуга на окружности этого эллипса обозначается углами от центра эллипса, которые указывают начало дуги и ее длину. Два разных метода рисуют угловые дуги. AddArc Это метод и метод : ArcTo
public void AddArc (SKRect oval, Single startAngle, Single sweepAngle) public void ArcTo (SKRect oval, Single startAngle, Single sweepAngle, Boolean forceMoveTo)
Эти методы идентичны методам Android AddArc и [ ArcTo ]xref:Android.Graphics.Path.ArcTo*). Метод iOS AddArc аналогичен, но ограничен дугами по окружности, а не обобщенным эллипсом.
Оба метода начинаются со SKRect значения, определяющего расположение и размер эллипса:

Дуга является частью окружности этого эллипса.
Аргумент startAngle представляет собой угол по часовой стрелке в градусах относительно горизонтальной линии, нарисованной от центра эллипса справа. Аргумент sweepAngle имеет значение относительно startAngle . Ниже приведены startAngle значения и sweepAngle 60 градусов и 100 градусов соответственно:

Дуга начинается с начального угла. Его длина определяется углом развертки. Дуга показана здесь красным цветом:

Кривая, добавленная к пути с AddArc помощью метода или ArcTo , является просто частью окружности эллипса:

Аргументы startAngle или sweepAngle могут быть отрицательными: дуга по часовой стрелке для положительных значений и sweepAngle против часовой стрелки для отрицательных значений.
AddArc Однако не определяет замкнутый контур. При вызове LineTo после AddArc , отрисовывается линия от конца дуги до точки в методе LineTo , и то же самое верно и для ArcTo .
AddArc автоматически запускает новый контур и функционально эквивалентен вызову ArcTo с окончательным аргументом true :
path.ArcTo (oval, startAngle, sweepAngle, true);
Этот последний аргумент называется forceMoveTo и фактически вызывает MoveTo вызов в начале дуги. Это начинает новый контур. Это не относится к последнему аргументу : false
path.ArcTo (oval, startAngle, sweepAngle, false);
Эта версия ArcTo рисует линию от текущего положения до начала дуги. Это означает, что дуга может находиться где-то в середине большего контура.
На странице Угловая дуга можно использовать два ползунка, чтобы указать углы начала и развертки. Xaml-файл создает два Slider элемента и SKCanvasView . Обработчик PaintCanvas в файле AngleArcPage.xaml.cs рисует овал и дугу с помощью двух SKPaint объектов, определенных как поля:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) < SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); SKRect rect = new SKRect(100, 100, info.Width - 100, info.Height - 100); float startAngle = (float)startAngleSlider.Value; float sweepAngle = (float)sweepAngleSlider.Value; canvas.DrawOval(rect, outlinePaint); using (SKPath path = new SKPath()) < path.AddArc(rect, startAngle, sweepAngle); canvas.DrawPath(path, arcPaint); >>
Как видите, начальный угол и угол развертки могут принимать отрицательные значения:

Этот подход к созданию дуги алгоритмически прост, и легко получить параметрические уравнения, описывающие дугу. Зная размер и расположение эллипса, а также углы начала и развертки, начальную и конечную точки дуги можно вычислить с помощью простой тригонометрии:
x = oval.MidX + (oval.Width / 2) * cos(angle)
y = oval.MidY + (oval.Height / 2) * sin(angle)
Значение angle равно или startAngle startAngle + sweepAngle .
Использовать два угла для определения дуги лучше всего в тех случаях, когда вы знаете угловую длину дуги, которую вы хотите нарисовать, например, для создания круговой диаграммы. Это демонстрируется на странице «Разрезаная круговая диаграмма «. Класс ExplodedPieChartPage использует внутренний класс для определения некоторых фабрикованных данных и цветов:
class ChartData < public ChartData(int value, SKColor color) < Value = value; Color = color; >public int Value < private set; get; >public SKColor Color < private set; get; >> ChartData[] chartData = < new ChartData(45, SKColors.Red), new ChartData(13, SKColors.Green), new ChartData(27, SKColors.Blue), new ChartData(19, SKColors.Magenta), new ChartData(40, SKColors.Cyan), new ChartData(22, SKColors.Brown), new ChartData(29, SKColors.Gray) >;
Сначала PaintSurface обработчик выполняет цикл по элементам, чтобы вычислить totalValues число. Таким образом, он может определить размер каждого элемента как долю от общего числа и преобразовать его в угол:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) < SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); int totalValues = 0; foreach (ChartData item in chartData) < totalValues += item.Value; >SKPoint center = new SKPoint(info.Width / 2, info.Height / 2); float explodeOffset = 50; float radius = Math.Min(info.Width / 2, info.Height / 2) - 2 * explodeOffset; SKRect rect = new SKRect(center.X - radius, center.Y - radius, center.X + radius, center.Y + radius); float startAngle = 0; foreach (ChartData item in chartData) < float sweepAngle = 360f * item.Value / totalValues; using (SKPath path = new SKPath()) using (SKPaint fillPaint = new SKPaint()) using (SKPaint outlinePaint = new SKPaint()) < path.MoveTo(center); path.ArcTo(rect, startAngle, sweepAngle, false); path.Close(); fillPaint.Style = SKPaintStyle.Fill; fillPaint.Color = item.Color; outlinePaint.Style = SKPaintStyle.Stroke; outlinePaint.StrokeWidth = 5; outlinePaint.Color = SKColors.Black; // Calculate "explode" transform float angle = startAngle + 0.5f * sweepAngle; float x = explodeOffset * (float)Math.Cos(Math.PI * angle / 180); float y = explodeOffset * (float)Math.Sin(Math.PI * angle / 180); canvas.Save(); canvas.Translate(x, y); // Fill and stroke the path canvas.DrawPath(path, fillPaint); canvas.DrawPath(path, outlinePaint); canvas.Restore(); >startAngle += sweepAngle; > >
Для каждого среза круговой диаграммы создается новый SKPath объект . Путь состоит из линии от центра, затем для ArcTo рисования дуги и другой линии обратно к центру результатов Close вызова. Эта программа отображает «разрезанные» срезы кругов, перемещая их от центра на 50 пикселей. Для этой задачи требуется вектор в направлении средней точки угла развертки для каждого среза:

Чтобы увидеть, как это выглядит без «взрыва», просто закомментируйте Translate звонок:

Тангенсная дуга
Второй тип дуги, поддерживаемый SKPath , — это тангенсная дуга, так называемая потому, что дуга — это окружность круга, который является касанием к двум соединенным линиям.
Тангенсная дуга добавляется в путь с помощью вызова ArcTo метода с двумя SKPoint параметрами или перегрузки ArcTo с отдельными Single параметрами для точек:
public void ArcTo (SKPoint point1, SKPoint point2, Single radius) public void ArcTo (Single x1, Single y1, Single x2, Single y2, Single radius)
Этот ArcTo метод аналогичен функции PostScript arct (страница 532) и методу iOS AddArcToPoint .
Метод ArcTo состоит из трех моментов:
- Текущая точка контура или точка (0, 0), если MoveTo не была вызвана
- Аргумент первой точки метода ArcTo , который называется угловой точкой
- Второй аргумент точки для ArcTo , называемый конечной точкой:

Эти три точки определяют две соединенные линии:

Если три точки являются однолинейными, то есть если они лежат на одной прямой линии, то дуга не будет нарисована.
Метод ArcTo также включает radius параметр . Определяет радиус окружности:

Тангенсная дуга не обобщается для эллипса.
Если две линии встречаются под любым углом, этот круг можно вставить между этими линиями, чтобы он был касающимся к обеим линиям:

Кривая, добавляемая к контуру, не затрагивает ни один из точек, указанных в методе ArcTo . Он состоит из прямой линии от текущей точки до первой точки касания и дуги, которая заканчивается на второй точке касания, показанной здесь красным цветом:

Вот последняя прямая линия и дуга, которые добавляются к контуру:

Контур можно продолжить со второй точки касательных.
Страница Тангенсная дуга позволяет поэкспериментировать с тангенсной дугой. Это первая из нескольких страниц, производных от InteractivePage , которая определяет несколько удобных SKPaint объектов и выполняет обработку TouchPoint :
public class InteractivePage : ContentPage < protected SKCanvasView baseCanvasView; protected TouchPoint[] touchPoints; protected SKPaint strokePaint = new SKPaint < Style = SKPaintStyle.Stroke, Color = SKColors.Black, StrokeWidth = 3 >; protected SKPaint redStrokePaint = new SKPaint < Style = SKPaintStyle.Stroke, Color = SKColors.Red, StrokeWidth = 15 >; protected SKPaint dottedStrokePaint = new SKPaint < Style = SKPaintStyle.Stroke, Color = SKColors.Black, StrokeWidth = 3, PathEffect = SKPathEffect.CreateDash(new float[] < 7, 7 >, 0) >; protected void OnTouchEffectAction(object sender, TouchActionEventArgs args) < bool touchPointMoved = false; foreach (TouchPoint touchPoint in touchPoints) < float scale = baseCanvasView.CanvasSize.Width / (float)baseCanvasView.Width; SKPoint point = new SKPoint(scale * (float)args.Location.X, scale * (float)args.Location.Y); touchPointMoved |= touchPoint.ProcessTouchEvent(args.Id, args.Type, point); >if (touchPointMoved) < baseCanvasView.InvalidateSurface(); >> >
Класс TangentArcPage является производным от InteractivePage . Конструктор в файле TangentArcPage.xaml.cs отвечает за создание и инициализацию массива touchPoints и установку baseCanvasView SKCanvasView (в InteractivePage ) для объекта, созданного в файле TangentArcPage.xaml:
public partial class TangentArcPage : InteractivePage < public TangentArcPage() < touchPoints = new TouchPoint[3]; for (int i = 0; i < 3; i++) < TouchPoint touchPoint = new TouchPoint < Center = new SKPoint(i == 0 ? 100 : 500, i != 2 ? 100 : 500) >; touchPoints[i] = touchPoint; > InitializeComponent(); baseCanvasView = canvasView; radiusSlider.Value = 100; > void sliderValueChanged(object sender, ValueChangedEventArgs args) < if (canvasView != null) < canvasView.InvalidateSurface(); >> . >
Обработчик PaintSurface использует метод для рисования ArcTo дуги на основе точек касания и Slider , но также алгоритмически вычисляет круг, на котором основан угол:
public partial class TangentArcPage : InteractivePage < . void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) < SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); // Draw the two lines that meet at an angle using (SKPath path = new SKPath()) < path.MoveTo(touchPoints[0].Center); path.LineTo(touchPoints[1].Center); path.LineTo(touchPoints[2].Center); canvas.DrawPath(path, dottedStrokePaint); >// Draw the circle that the arc wraps around float radius = (float)radiusSlider.Value; SKPoint v1 = Normalize(touchPoints[0].Center - touchPoints[1].Center); SKPoint v2 = Normalize(touchPoints[2].Center - touchPoints[1].Center); double dotProduct = v1.X * v2.X + v1.Y * v2.Y; double angleBetween = Math.Acos(dotProduct); float hypotenuse = radius / (float)Math.Sin(angleBetween / 2); SKPoint vMid = Normalize(new SKPoint((v1.X + v2.X) / 2, (v1.Y + v2.Y) / 2)); SKPoint center = new SKPoint(touchPoints[1].Center.X + vMid.X * hypotenuse, touchPoints[1].Center.Y + vMid.Y * hypotenuse); canvas.DrawCircle(center.X, center.Y, radius, this.strokePaint); // Draw the tangent arc using (SKPath path = new SKPath()) < path.MoveTo(touchPoints[0].Center); path.ArcTo(touchPoints[1].Center, touchPoints[2].Center, radius); canvas.DrawPath(path, redStrokePaint); >foreach (TouchPoint touchPoint in touchPoints) < touchPoint.Paint(canvas); >> // Vector methods SKPoint Normalize(SKPoint v) < float magnitude = Magnitude(v); return new SKPoint(v.X / magnitude, v.Y / magnitude); >float Magnitude(SKPoint v) < return (float)Math.Sqrt(v.X * v.X + v.Y * v.Y); >>
Ниже приведена страница Tangent Arc , на которую выполняется:

Тангенсная дуга идеально подходит для создания скругленные углы, например скругленные прямоугольники. Так как SKPath уже включает AddRoundedRect метод, на странице Скругленные шестиугольник показано, как использовать для скругления ArcTo углов семистороннего многоугольника. (Код обобщен для любого регулярного многоугольника.)
Обработчик PaintSurface RoundedHeptagonPage класса содержит один for цикл для вычисления координат семи вершин шестиугольника, а второй — для вычисления средних точек семи сторон от этих вершин. Затем эти средние точки используются для построения пути:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) < SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float cornerRadius = 100; int numVertices = 7; float radius = 0.45f * Math.Min(info.Width, info.Height); SKPoint[] vertices = new SKPoint[numVertices]; SKPoint[] midPoints = new SKPoint[numVertices]; double vertexAngle = -0.5f * Math.PI; // straight up // Coordinates of the vertices of the polygon for (int vertex = 0; vertex < numVertices; vertex++) < vertices[vertex] = new SKPoint(radius * (float)Math.Cos(vertexAngle), radius * (float)Math.Sin(vertexAngle)); vertexAngle += 2 * Math.PI / numVertices; >// Coordinates of the midpoints of the sides connecting the vertices for (int vertex = 0; vertex < numVertices; vertex++) < int prevVertex = (vertex + numVertices - 1) % numVertices; midPoints[vertex] = new SKPoint((vertices[prevVertex].X + vertices[vertex].X) / 2, (vertices[prevVertex].Y + vertices[vertex].Y) / 2); >// Create the path using (SKPath path = new SKPath()) < // Begin at the first midpoint path.MoveTo(midPoints[0]); for (int vertex = 0; vertex < numVertices; vertex++) < SKPoint nextMidPoint = midPoints[(vertex + 1) % numVertices]; // Draws a line from the current point, and then the arc path.ArcTo(vertices[vertex], nextMidPoint, cornerRadius); // Connect the arc with the next midpoint path.LineTo(nextMidPoint); >path.Close(); // Render the path in the center of the screen using (SKPaint paint = new SKPaint()) < paint.Style = SKPaintStyle.Stroke; paint.Color = SKColors.Blue; paint.StrokeWidth = 10; canvas.Translate(info.Width / 2, info.Height / 2); canvas.DrawPath(path, paint); >> >
Вот работающая программа:

Эллиптическая дуга
Эллиптическая дуга добавляется к пути с помощью вызова ArcTo метода, который имеет два SKPoint параметра, или перегрузки ArcTo с отдельными координатами X и Y:
public void ArcTo (SKPoint r, Single xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, SKPoint xy) public void ArcTo (Single rx, Single ry, Single xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, Single x, Single y)
Эллиптическая дуга согласуется с эллиптической дугой, включенной в масштабируемую векторную графику (SVG) и класс универсальная платформа Windows ArcSegment .
Эти ArcTo методы рисуют дугу между двумя точками, которые являются текущей точкой контура, и последним параметром ArcTo метода ( xy параметром или отдельными x параметрами и y ):

Первый параметр точки метода ArcTo ( r или rx и ry ) не является точкой, а задает горизонтальные и вертикальные радиусы эллипса;

Параметр xAxisRotate — это количество градусов по часовой стрелке для поворота этого эллипса:

Если этот наклонный эллипс расположен так, чтобы он касался двух точек, точки соединяются двумя разными дугами:

Эти две дуги можно различить двумя способами: верхняя дуга больше нижней дуги, и так как дуга рисуется слева направо, верхняя дуга рисуется по часовой стрелке, а нижняя дуга рисуется в направлении против часовой стрелки.
Можно также разместить эллипс между двумя точками другим способом:

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

Эти четыре дуги отличаются четырьмя сочетаниями аргументов SKPathArcSize ArcTo типа перечисления и SKPathDirection для метода :
- красный: SKPathArcSize.Large и SKPathDirection.Clockwise
- зеленый: SKPathArcSize.Small и SKPathDirection.Clockwise
- синий: SKPathArcSize.Small и SKPathDirection.CounterClockwise
- magenta: SKPathArcSize.Large и SKPathDirection.CounterClockwise
Если эллипс с наклоном недостаточно велик, чтобы поместиться между двумя точками, то он равномерно масштабируется до тех пор, пока он не будет достаточно большим. В этом случае две уникальные дуги соединяют две точки. Их можно отличить с SKPathDirection помощью параметра .
Хотя этот подход к определению дуги звучит сложно при первой встрече, он является единственным подходом, который позволяет определить дугу с повернутым эллипсом, и это часто самый простой подход, когда необходимо интегрировать дуги с другими частями контура.
На странице Эллиптическая дуга можно в интерактивном режиме задать две точки, а также размер и поворот эллипса. Класс EllipticalArcPage является производным от InteractivePage , а PaintSurface обработчик в файле кода программной части EllipticalArcPage.xaml.cs рисует четыре дуги:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) < SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); using (SKPath path = new SKPath()) < int colorIndex = 0; SKPoint ellipseSize = new SKPoint((float)xRadiusSlider.Value, (float)yRadiusSlider.Value); float rotation = (float)rotationSlider.Value; foreach (SKPathArcSize arcSize in Enum.GetValues(typeof(SKPathArcSize))) foreach (SKPathDirection direction in Enum.GetValues(typeof(SKPathDirection))) < path.MoveTo(touchPoints[0].Center); path.ArcTo(ellipseSize, rotation, arcSize, direction, touchPoints[1].Center); strokePaint.Color = colors[colorIndex++]; canvas.DrawPath(path, strokePaint); path.Reset(); >> foreach (TouchPoint touchPoint in touchPoints) < touchPoint.Paint(canvas); >>

На странице Arc Infinity используется эллиптическая дуга для рисования знака бесконечности. Знак бесконечности основан на двух кругах с радиусами 100 единиц, разделенных на 100 единиц:

Две линии, пересекаемые друг с другом, касательные к обоим кругам:

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

Радиус окружности составляет 100 единиц, а гипотенузы треугольника — 150 единиц, поэтому угол α является арксинусом (обратным синусом) 100, разделенным на 150, или 41,8 градуса. Длина другой стороны треугольника составляет 150 раз косиуса 41,8 градуса, или 112, что также может быть вычислено с помощью теоремы Пифагора.
Затем координаты точки касания можно вычислить с помощью следующих сведений:
x = 112·cos(41.8) = 83
y = 112·sin(41.8) = 75
Четыре точки тангенсов — это все, что необходимо для рисования знака бесконечности по центру точки (0, 0) с радиусами круга 100:

Обработчик PaintSurface в ArcInfinityPage классе размещает знак бесконечности таким образом, чтобы точка (0, 0) располагалась в центре страницы, и масштабирует путь до размера экрана:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) < SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); using (SKPath path = new SKPath()) < path.LineTo(83, 75); path.ArcTo(100, 100, 0, SKPathArcSize.Large, SKPathDirection.CounterClockwise, 83, -75); path.LineTo(-83, 75); path.ArcTo(100, 100, 0, SKPathArcSize.Large, SKPathDirection.Clockwise, -83, -75); path.Close(); // Use path.TightBounds for coordinates without control points SKRect pathBounds = path.Bounds; canvas.Translate(info.Width / 2, info.Height / 2); canvas.Scale(Math.Min(info.Width / pathBounds.Width, info.Height / pathBounds.Height)); using (SKPaint paint = new SKPaint()) < paint.Style = SKPaintStyle.Stroke; paint.Color = SKColors.Blue; paint.StrokeWidth = 5; canvas.DrawPath(path, paint); >> >
Код использует Bounds свойство для SKPath определения размеров синуса бесконечности, чтобы масштабировать его до размера холста:

Результат кажется немного небольшим, что говорит о том, что Bounds свойство SKPath сообщает размер больше, чем путь.
На внутреннем уровне Скиа аппроксимирует дугу с помощью нескольких квадратитических кривых Безье. Эти кривые (как вы увидите в следующем разделе) содержат контрольные точки, которые управляют способом рисования кривой, но не являются частью отрисованной кривой. Свойство Bounds включает эти контрольные точки.
Чтобы получить более тесное соответствие, используйте TightBounds свойство , которое исключает контрольные точки. Ниже приведена программа, работающая в альбомном режиме TightBounds и использующей свойство для получения границ пути:

Хотя соединения между дугами и прямыми линиями математически гладкие, переход от дуги к прямой может показаться немного резким. Знак бесконечности лучше представлен в следующей статье о трех типах кривых Безье.
Связанные ссылки
- API SkiaSharp
- SkiaSharpFormsDemos (пример)
Как нарисовать дугу в Canva?
Обратите внимание, что в данном редакторе нет привычных инструментов рисования тех или иных фигур. Вам вместо этого предлагается выбрать одну из готовых форм, а затем подогнать ее свойства под свой проект. То же самое делается и в случае рисования дуги. Найдите форму дуги через поиск в панели инструментов, а затем настройте ее. Обратите внимание, что изменению поддаются не все параметры дуги, а только цвет, размер и угол наклона.
Другие вопросы посетителей из раздела «Фото и Видео Canva»:
Программное обеспечение
Оборудование
Служба поддержки
Размещение рекламы
info@sotoguide.ru
Копирование материалов допускается только при указании источника
Как сделать дугу в канве
Кроме прямоугольников canvas позволяет рисовать и более сложные фигуры. Для оформления сложных фигур используется концепция геометрических путей, которые представляют набор линий, окружностей, прямоугольников и других более мелких деталей, необходимых для построения сложной фигуры.
Для создания нового пути надо вызвать метод beginPath() :
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); // начинаем рисование фигуры
После метода beginPath() вызываются методы, которые непосредственно создают различные участки пути.
Методы moveTo() и lineTo()
Для начала рисования пути нам надо зафиксировать начальную точку этого пути. Это можно сделать с помощью метода moveTo() , который имеет следующее определение:
moveTo(x, y)
Метод перемещает нас на точку с координатами x и y.
Метод lineTo() рисует линию. Он имеет похожее определение:
lineTo(x, y)
Метод рисует линию от текущей позиции до точки с координатами x и y.
Теперь нарисуем ряд линий:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.moveTo(20, 100); context.lineTo(140, 10); context.lineTo(260, 100);
Здесь мы устанавливаем начало пути в точку (20, 100), затем от нее рисуем линию до точки (140, 10) (линия вверх) и далее рисуем еще одну линию до точки (260, 100).
Отображение пути
Хотя мы нарисовали несколько линий, пока мы их не увидим, потому что их надо отобразить на экране. Для отображения пути надо использовать метод stroke() :
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.moveTo(20, 100); context.lineTo(140, 10); context.lineTo(260, 100); context.stroke(); // отображаем путь

По умолчанию для отрисовки используется черный цвет, но с помощью свойства strokeStyle можно изменить цвет:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.moveTo(20, 100); context.lineTo(140, 10); context.lineTo(260, 100); context.strokeStyle = "red"; // красный цвет context.stroke(); // отображаем путь
Замыкание пути
Мы нарисовали две линии, и, допустим, мы их хотим соединить, чтобы замкнуть фигуру — в данном случае прямоугольник. В принципе в этом случае мы могли бы нарисовать еще одну линию, и у нас бы получился треугольник. Однако для упрощения Canvas API для этого предоставляет специальный метод — context.closePath() , который позволяет автоматически замкнуть путь, соединив первую и последнюю точки пути, и образовать фигуру:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.moveTo(20, 100); context.lineTo(140, 10); context.lineTo(260, 100); context.closePath(); // закрываем путь context.stroke();

Объекты Path2D
При работе со многими путями может возникнуть путаница. В этом случае для разграниченися отдельных путей можно использовать объект Path2D. Этот объект предоставляет методы, аналогичные методам объекта контекста в отношении создания пути. Например:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const path1 = new Path2D(); // первый путь path1.moveTo(20, 100); path1.lineTo(140, 10); path1.lineTo(260, 100); path1.closePath(); // закрываем путь context.strokeStyle = "blue"; context.stroke(path1); const path2 = new Path2D(); // первый путь path2.moveTo(20, 110); path2.lineTo(140, 200); path2.lineTo(260, 110); path2.closePath(); // закрываем путь context.strokeStyle = "red"; context.stroke(path2);
Здесь создаются два пути, каждый из которых представляет треугольник. Для отрисовки каждого пути вызывается метод context.stroke() , в который передается путь.

Метод rect
Метод rect() создает прямоугольник. Он имеет следующее определение:
rect(x, y, width, height)
Где x и y — это координаты верхнего левого угла прямоугольника относительно canvas, а width и height — соответственно ширина и высота прямоугольника. Нарисуем, к примеру, следующий прямоугольник:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.rect(30, 20, 100, 90); context.closePath(); context.stroke();

Стоит отметить, что такой же прямоугольник мы могли бы создать из линий:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.moveTo(30, 20); context.lineTo(130, 20); context.lineTo(130, 110); context.lineTo(30, 110); context.closePath(); context.stroke();
Метод fill()
Метод fill() заполняет цветом все внутреннее пространство нарисованного пути:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.beginPath(); context.moveTo(20, 100); context.lineTo(140, 10); context.lineTo(260, 100); context.closePath(); context.strokeStyle = "#2e86de"; context.fillStyle = "#4bcffa"; context.fill(); context.stroke();
С помощью свойства fillStyle опять же можно задать цвет заполнения фигуры. В данном случае это цвет «#4bcffa».

Метод clip()
Метод clip() позволяет вырезать из canvas определенную область, а все, что вне этой области, будет игнорироваться при последующей отрисовке.
Для понимания этого метода сначала нарисуем два прямоугольника:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); // рисуем первый красный прямоугольник context.beginPath(); context.moveTo(10, 20); context.lineTo(130, 20); context.lineTo(130, 110); context.lineTo(10, 110); context.closePath(); context.strokeStyle = "red"; context.stroke(); // рисуем второй зеленый прямоугольник context.beginPath(); context.rect(30, 50, 180, 70); context.closePath(); context.strokeStyle = "green"; context.stroke();

Теперь применим метод clip() для ограничения области рисования только первым прямоугольником:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); // рисуем первый красный прямоугольник context.beginPath(); context.moveTo(10, 20); context.lineTo(130, 20); context.lineTo(130, 110); context.lineTo(10, 110); context.closePath(); context.strokeStyle = "red"; context.stroke(); context.clip(); // обрезаем область рисования по первому пути // рисуем второй зеленый прямоугольник context.beginPath(); context.rect(30, 50, 180, 70); context.closePath(); context.strokeStyle = "green"; context.stroke();

Поскольку вызов метода clip() идет после первого прямоугольника, то из второго прямоугольника будет нарисована только та часть, которая попадает в первый прямоугольник.
Метод arc()
Метод arc() добавляет к пути участок окружности или дугу/арку. Он имеет следующее определение:
arc(x, y, radius, startAngle, endAngle, anticlockwise)
Здесь используются следующие параметры:

- x и y : x- и y-координаты, в которых начинается дуга
- radius : радиус окружности, по которой создается дуга
- startAngle и endAngle : начальный и конечный угол, которые усекают окружность до дуги. В качестве единици измерения для углов применяются радианы. Например, полная окружность — это 2π радиан. Если, к примеру, нам надо нарисовать полный круг, то для параметра endAngle можно указать значение 2π. В JavaScript эту веричину можно получить с помощью выражения Math.PI * 2 .
- anticlockwise : направление движения по окружности при отсечении ее части, ограниченной начальным и конечным углом. При значении true направление против часовой стрелки, а при значении false — по часовой стрелке.
Пример рисования дуг и окружностей
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.strokeStyle = "red"; context.beginPath(); context.moveTo(20, 90); context.arc(20, 90, 50, 0, Math.PI/2, false); context.closePath(); context.stroke(); context.beginPath(); context.moveTo(130, 90); context.arc(130, 90, 50, 0, Math.PI, false); context.closePath(); context.stroke(); context.beginPath(); context.moveTo(240, 90); context.arc(240, 90, 50, 0, Math.PI * 3 / 2, false); context.closePath(); context.stroke(); context.beginPath(); context.arc(350, 90, 50, 0, Math.PI*2, false); context.closePath(); context.stroke();

Последний параметр anticlockwise играет важную роль, так как определяет движение по окружности, и в случае изменения true на false и наоборот, мы можем получить совершенно разные фигуры:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.strokeStyle = "red"; context.beginPath(); context.moveTo(80, 90); context.arc(80, 90, 50, 0, Math.PI/2, false); context.closePath(); context.stroke(); context.beginPath(); context.moveTo(240, 90); context.arc(240, 90, 50, 0, Math.PI/2, true); context.closePath(); context.stroke();

Метод arcTo()
Метод arcTo() также рисует дугу. Он имеет следующее определение:
arcTo(x1, y1, x2, y2, radius)
Где x1 и y1 — координаты первой контрольной точки, x2 и y2 — координаты второй контрольной точки, а radius — радиус дуги.

Пример рисования дуг с помощью arcTo() :
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.strokeStyle = "red"; context.beginPath(); context.moveTo(0, 150); context.arcTo(0, 0, 150, 0, 140) context.closePath(); context.stroke();

Здесь мы перемещаемся вначале на точку (0, 150), и от этой точки до первой контрольной точки (0, 0) будет проходить первая касательная. Далее от первой контрольной точки (0, 0) до второй (150, 0) будет проходить вторая касательная. Эти две касательные оформляют дугу, а 140 служит радиусом окружности, на которой усекается дуга.
Метод quadraticCurveTo()
Метод quadraticCurveTo() создает квадратичную кривую. Он имеет следующее определение:
quadraticCurveTo(x1, y1, x2, y2)
Где x1 и y1 — координаты первой опорной точки, а x2 и y2 — координаты второй опорной точки.

Пример квадратичной Безье:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.strokeStyle = "red"; context.beginPath(); context.moveTo(20, 90); context.quadraticCurveTo(130, 0, 280, 90) context.closePath(); context.stroke();

Метод bezierCurveTo(). Кривая Безье
Метод bezierCurveTo() рисует кривую Безье. Он имеет следующее определение:
bezierCurveTo(x1, y1, x2, y2, x3, y3)
Где x1 и y1 — координаты первой опорной точки, x2 и y2 — координаты второй опорной точки, а x3 и y3 — координаты третьей опорной точки.

Пример кривой Безье:
const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); context.strokeStyle = "red"; context.beginPath(); context.moveTo(30, 100); context.bezierCurveTo(110, 0, 190, 200, 270, 100); context.closePath(); context.stroke();

Комплексные фигуры
Объединим несколько фигур вместе и нарисуем более сложную двухмерную сцену:
METANIT.COM
Как сделать дугу в канве
Регистрация: 25.10.2009
Сообщений: 92
Дуга Canvas.Arc
Надо на канве нарисовать дугу окружности, для которой известны 2 ее конца (координаты) и радиус, плюс еще указано направление поворота дуги (по или против часовой стрелки) и угол (не значение угла, а только > 180 градусов или меньше). Допустим так:
x1, y1, x2, y2, r: integer; dir, ang: boolean;
Есть в Делфи функция
procedure Arc(X1,Y1,X2,Y2,X3,Y3,X4,Y4: double);
первые 2 точки здесь определяют прямоугольник, в который вписывается эллипс, вторые две точки — при соединении их с центром эллипса получаются две прямые, которые пересекают эллипс в граничных точках дуги (дуга чертится против часовой стрелки). Пытаюсь тупо найти центр по исходным данным (выразить), с помощью уравнения окружности, получается лажа, ибо квадратное уравнение. Может что-то не так делаю, или есть какой-то более простой способ построения дуги по указанным исходным данным?
Последний раз редактировалось cw_o; 11.12.2009 в 20:17 .