Jump to content
View in the app

A better way to browse. Learn more.

FGX Native

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Добрый день,

В скором времени выйдет новое крупное обновление 1.18.14.0, в которое войдет новый функционал, который вам однозначно пригодится. В этой статье рассмотрим новые графические возможности по работе с канвой TfgCanvas.

Работа с состоянием канвы

Перед тем, как мы перейдем к новым возможностям, мы обязаны рассмотреть изменения в работе с состоянием канвы. Поскольку эти изменения необходимы для корректной работы с обрезанием изображений по произвольным кривым.

Напомню, что при работе с канвой TfgCanvas разработчик постоянно меняет ее параметры (настройки кисти, матрицы трансформации и т.д.). Поэтому, очень удобно иметь контрольные точки при отрисовке, к которым можно сбросить состояние канвы, чтобы не устанавливать все настройки заново. Для этих целей используются методы SaveState / RestoreState. Метод SaveState возвращал объект состояния, который в дальнейшем нужно было передавать в парный метод RestoreState для восстановления состояния. В новой версии, объект состояния больше не нужно использовать.

Было:

var
  State: IFGXSaveState;

State := ACanvas.SaveState;
try
  // Задаем параметры отрисовки
  // Выполняем отрисовку  
finally 
  ACanvas.RestoreState(State);
end;

Стало:

ACanvas.SaveState;
try
  // Задаем параметры отрисовки
  // Выполняем отрисовку  
finally 
  ACanvas.RestoreState;
end;

Теперь при вызове SaveState, канва автоматически сохраняет состояние во внутренний стек, а при вызове RestoreState извлекает его из стека и восстанавливает.

Зачем?

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

Вторая причина: Чаще всего при выполнении последовательной отрисовки, восстановление канвы требуется не на произвольное состояние, а именно на предыдущее состояние.

{ State 1 }
ACanvas.SaveState; // Save State 1
{ State 2 }    
try
  // Задаем параметры отрисовки
  // Выполняем отрисовку  
  ACanvas.SaveState; // Save State 2
  try
    // Другая вложенная отрисовка
  finally 
    ACanvas.RestoreState; // Rollback to State 2
  end;
finally 
  ACanvas.RestoreState; // Rollback to State 1
end;

Внимание: Не смотря на то, что старый подход по работе с состоянием сохранился, он может не корректно работать при использовании областей отсечения TfgCanvas.ClipPath.

Обрезание по пути

Одна из самых интересных графических возможностей - это ограничение области отрисовки на канве произвольной фигурой или путем. Накладывание ограничения выполняется при помощи нового метода TfgCanvas.ClipPath.

    /// <summary>
    ///   Выполняет накладывание области отсечения будущих команд отрисовки. Чтобы отменить наложенную область ограничения
    ///   необходимо использовать методы <c>SaveState</c> / <c>RestoreState</c>. Перед наложение области сохранить состояние
    ///   канвы, а после завершения работы - восстановить.
    /// </summary>
    procedure ClipPath(const APath: TfgPath);

Рассмотрим пример, где мы хотим нарисовать два овала красного и синего цветов. Красный обрезать по вписанному овалу в область отрисовки, а синий - не обрезать.

simulator_screenshot_6444AD7F-C9BF-4EA5-BD3B-A26C91255748.png

Тогда код по отрисовке будет выглядить так:

procedure TFormMain.fgPaintBoxPaint(Sender: TObject; const ACanvas: TfgCanvas);
var
  CirclePath: TfgPath;
begin
  // Сохраняем состояние, чтобы в будущем убрать область отсечения
  ACanvas.SaveState;
  CirclePath := TfgPath.Create(nil);
  try
    // Формируем область отсечения в виде эллипса, вписанного в область отрисовки.
    CirclePath.AddArc(fgPaintBox.LocalBounds, 0, 360)
              .ClosePath;
    ACanvas.ClipPath(CirclePath);

    // Рисуем красный круг, он будет обрезан 
    ACanvas.Fill.Kind := TfgBrushKind.Solid;
    ACanvas.Fill.Color := TAlphaColorRec.Red;
    ACanvas.FillCircle(TPointF.Create(0, fgPaintBox.Height / 2), fgPaintBox.Height / 2);
  finally
    CirclePath.Free;
  end;
  // Сбрасываем область отсечения
  ACanvas.RestoreState;
  
  // Рисуем синий круг без ограничений
  ACanvas.Fill.Color := TAlphaColorRec.Blue;
  ACanvas.FillCircle(TPointF.Create(fgPaintBox.Width, fgPaintBox.Height / 2), fgPaintBox.Height / 2);

Где это может пригодиться? Одной из областей применения может стать динамическая отрисовка изображений, обрезанных по произвольной фигуре. Например, вы хотите вывести фотографии или аватарки пользователей в виде круга или какой-нибудь декоративной рамки. Раньше вы могли использовать для этой цели маски. Для этого вам надо было сформировать изображение маски, и затем выполнить отрисовки битмапа с учетом этой маски. Теперь эта операция может выполняться гораздо проще, быстрее и без использования дополнительной памяти.

simulator_screenshot_66B9A973-8B5E-42AD-8E90-4762BE9D9677.png

У нас есть изображение, которое мы хотим вывести в круглом варианте и декорировать белым кольцом. Код может выглядить следующим образом. Фотография находится в менеджере ресурсов.

procedure TFormMain.fgPaintBox1Paint(Sender: TObject; const ACanvas: TfgCanvas);
var
  PhotoBitmap: TfgBitmap;
  FramePath: TfgPath;
  FrameBounds: TRectF;
begin
  // Извлекаем изображение
  if not TfgAssetsManager.Current.TryGetBitmap(R.Bitmap.PHOTO, PhotoBitmap) then
    Exit;

  ACanvas.SaveState;
  try
    // Формируем круглую форму рамки и рисуем битмап
    FramePath := TfgPath.Create(nil);
    try
      FrameBounds := fgPaintBox1.LocalBounds;
      FramePath.AddArc(FrameBounds, 0, 360)
              .ClosePath;
      ACanvas.ClipPath(FramePath);
      ACanvas.DrawBitmap(PhotoBitmap, FrameBounds);
    finally
      FramePath.Free;
    end;
  finally
    ACanvas.RestoreState;
  end;

  // Декорируем белым кольцом
  ACanvas.Stroke.Thickness := 10;
  ACanvas.Stroke.Color := TAlphaColorRec.White;
  ACanvas.DrawCircle(FrameBounds.CenterPoint, FrameBounds.Width / 2 - 10);
end;

Заполнение пути

Есть как минимум два способа заливки кривых фигур по пути TfgPath. По умолчанию, в FGX Native использовался способ заливки правой фигуры. Теперь же вы можете выбирать способ заливки и указывать его через свойство TfgCanvas.FillPathRule. Помимо этого, теперь это свойство так же доступно в компоненте TfgSvgPath.

image.png

Детали о двух способах заливки доступны здесь.

Внимание: Данная настройка пока не поддерживается в дизайнере, так как не поддерживается на уровне FMX, которая используется для реализации в дизайнере.

Штрихи кисти

Теперь вы можете использовать свои варианты штрихов при отрисовки кривых. На уровне кисти TfgStrokeBrush доступен новый вид линии - Dash = Custom. Параметры штриха задаются через новый метод TfgStrokeBrush.SetCustomDash.

procedure TfgStrokeBrush.SetCustomDash(const ADash: TDashArray; const AOffset: Single);
  • ADash - это массив парных значений. Первое - это длина штриха, второе - длина пробела.

SVG

В этом релизе расширена поддержка параметров SVG, а именно добавлена поддержка следующих атрибутов: stroke-dasharray, stroke-dashoffset, stroke-linecap, stroke-linejoin, fill-rule.

Редактор градиента

Мы добавили дизайнер для управления параметрами градиента. Новое окно доступно через кнопку, встроенную в свойство типа TfgGradient.

image.png

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

  1. Добавлять и удалять точки градиента. Чтобы добавить точку, нужно нажать в свободное место на нижнем компоненте с отображением градиента. Чтобы удалить, точку надо утянуть за пределы компонента.

  2. Менять тип градиента - линейный или радиальный

  3. Менять направление градиента при помощи точек на правой панели просмотра градиента.

  4. Сбросить параметры градиента до значений по умолчанию.

Итог

В следующей статье нас ждет обзор новой функции перетаскивания компонентов Drag & Drop.

2 Comments

Recommended Comments

Mineev

Active subscription

А в SVG поддержку clipPath не добавили?

  • Administrators
7 hours ago, Mineev said:

А в SVG поддержку clipPath не добавили?

В этом релизе нет. Но зато улучшили поддержку вашего файла svg, где используются штрихи.

Recently Browsing 0

  • No registered users viewing this page.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.