Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Исправление ошибки анимации в TBCFluentProgressRing и улучшение визуальных элементов в BGRAControls

Delphi , Компоненты и Классы , TImage и TImageList

 

Введение

В сообществе разработчиков на Delphi и Lazarus недавно была обнаружена и исправлена ошибка в компоненте TBCFluentProgressRing из библиотеки BGRAControls. Эта ошибка вызывала прерывистую анимацию кольца прогресса. В данной статье мы подробно разберем суть проблемы, предложенное решение и обсудим перспективы развития визуальных компонентов в экосистеме Pascal.

Описание проблемы

Ошибка была обнаружена в коде компонента TBCFluentProgressRing, который реализует анимированное кольцо прогресса в стиле Fluent Design от Microsoft. Пользователь hedgehog заметил, что анимация работает рывками, что значительно ухудшает пользовательский опыт.

Исходный код, содержащий ошибку, находился в методе TimerEvent:

procedure TBCFluentProgressRing.TimerEvent(Sender: TObject);
var
  TickCount: QWord;
begin
  TickCount:= GetTickCount64;
  FAnimationTime:= (TickCount - FStartTickCount) mod FPeriod;
  DiscardBitmap;
end;

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

Решение проблемы

Для исправления ошибки было предложено:

  1. Удалить вычисление времени анимации из метода TimerEvent
  2. Перенести это вычисление в метод RedrawBitmapContent, где происходит непосредственная отрисовка компонента

Исправленный код выглядит следующим образом:

procedure TBCFluentProgressRing.TimerEvent(Sender: TObject);
begin
  DiscardBitmap;
end;

А в метод RedrawBitmapContent было добавлено вычисление времени анимации:

if FIndeterminate and FTimer.Enabled then
begin
  FAnimationTime:= (GetTickCount64 - FStartTickCount) mod FPeriod;
  a:= 3*FAnimationTime*pi2/FPeriod - pi;
  da:= 2*abs(1 - 2*FAnimationTime/FPeriod);
  if da<0.01 then da:=0.01;
  DoDrawArc(a-da, a+da, FLineColor);
end

Это изменение обеспечивает более плавную анимацию, так как время теперь вычисляется непосредственно перед отрисовкой, а не в обработчике таймера.

Альтернативное решение

В качестве альтернативного решения можно предложить использование высокоточного таймера с фиксированным интервалом:

procedure TBCFluentProgressRing.SetupTimer;
begin
  FTimer := TBCTimer.Create(Self);
  FTimer.Interval := 15; // ~60 FPS
  FTimer.OnTimer := @TimerEvent;
  FTimer.Enabled := True;
end;

Также можно рассмотреть возможность использования анимаций на основе физики, где движение будет более естественным:

procedure TBCFluentProgressRing.UpdateAnimation;
var
  CurrentTime: QWord;
  Elapsed: Single;
begin
  CurrentTime := GetTickCount64;
  Elapsed := (CurrentTime - FLastUpdateTime) / 1000; // в секундах
  FLastUpdateTime := CurrentTime;

  // Применяем физику к анимации
  FVelocity := FVelocity + FAcceleration * Elapsed;
  FAnimationTime := (FAnimationTime + FVelocity * Elapsed) mod FPeriod;

  // Замедление при отсутствии взаимодействия
  if Abs(FVelocity) > 0 then
    FVelocity := FVelocity * (1 - FFriction * Elapsed);
end;

Обсуждение будущего визуальных компонентов

В ходе обсуждения ошибки участники сообщества затронули важную тему - необходимость модернизации визуальных компонентов для Pascal. Были высказаны следующие идеи:

  1. Стандартные контролы устарели - их внешний вид не соответствует современным требованиям UX/UI.
  2. BGRA позволяет создавать красивые контролы - но текущая реализация BGRAControls представляет собой набор разрозненных элементов без единого стиля.
  3. Необходима новая система визуальных компонентов - с единым стилем, анимациями и поддержкой современных тенденций (Material Design, Fluent Design).

Подходы к модернизации

  1. Темы vs свойства - стоит ли использовать темы (как в CSS) или множество свойств для настройки внешнего вида.
  2. Производительность vs функциональность - как сохранить малый объем памяти при добавлении новых возможностей.
  3. Нативные контролы vs кастомная отрисовка - использовать ли системные контролы или рисовать все самостоятельно.

Пример реализации стилизуемого кнопки:

type
  TBCButtonStyle = class(TPersistent)
  private
    FNormal: TBGRABitmap;
    FHover: TBGRABitmap;
    FActive: TBGRABitmap;
    // ... другие состояния
  public
    constructor Create;
    destructor Destroy; override;
    // ... методы загрузки стилей
  end;

  TBCModernButton = class(TBGRACustomControl)
  private
    FStyle: TBCButtonStyle;
    FState: TBCButtonState;
    procedure SetStyle(AValue: TBCButtonStyle);
  protected
    procedure DrawControl; override;
    procedure MouseEnter; override;
    procedure MouseLeave; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Style: TBCButtonStyle read FStyle write SetStyle;
    // ... другие свойства
  end;

Заключение

Исправление ошибки в TBCFluentProgressRing - это не только решение конкретной технической проблемы, но и повод задуматься о будущем визуальных компонентов в экосистеме Pascal. Сообщество стоит перед выбором пути развития: продолжать улучшать существующие решения или создать новую систему компонентов с нуля, учитывая современные тенденции дизайна и UX.

Для разработчиков, использующих BGRAControls, рекомендуется:

  1. Обновить библиотеку до последней версии, чтобы получить исправление анимации
  2. Экспериментировать с созданием собственных стилизованных компонентов на основе BGRA
  3. Участвовать в обсуждении будущего визуальных компонентов для Pascal

Пример простого анимированного кольца прогресса:

procedure TForm1.DrawFluentProgressRing(ABitmap: TBGRABitmap; Center: TPoint; 
  Radius, Thickness: Integer; Progress: Single; AColor: TBGRAPixel);
var
  StartAngle, EndAngle: Single;
begin
  StartAngle := -90;
  EndAngle := -90 + 360 * Progress;

  ABitmap.FillEllipseLinearColor(Center.x, Center.y, Radius, Radius, 
    BGRAPixelTransparent, AColor);
  ABitmap.FillEllipseLinearColor(Center.x, Center.y, Radius - Thickness, 
    Radius - Thickness, BGRAPixelTransparent, ColorToBGRA(clBackground));
end;

Будущее визуальных компонентов в Pascal зависит от активности сообщества. Каждый разработчик может внести свой вклад - будь то исправление ошибок, создание новых компонентов или участие в обсуждении архитектуры.

Создано по материалам из источника по ссылке.

Исправление ошибки анимации в компоненте TBCFluentProgressRing и обсуждение перспектив развития визуальных компонентов в экосистеме Pascal.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: TImage и TImageList ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-07-15 13:51:43/0.0063300132751465/0