В этой статье мы рассмотрим различные способы создания эффекта вращающегося текста в средах Delphi и Lazarus, используя библиотеку BGRABitmap. Мы проанализируем несколько подходов, предложенных сообществом, и предложим оптимизированные решения.
Введение в BGRABitmap
Библиотека BGRABitmap - это мощный инструмент для работы с графикой в Delphi и Lazarus. Она предоставляет:
- Расширенные возможности рисования
- Поддержку прозрачности и альфа-канала
- Аппаратное ускорение
- Дополнительные эффекты и фильтры
Базовый вариант с Canvas2D
Рассмотрим первоначальный вариант реализации вращающегося текста, предложенный Gigatron:
procedure TForm1.RenderToBuffer;
var
centerX, centerY, radius: Integer;
i: Integer;
charAngle: Single;
x, y: Integer;
canvas2D: TBGRACanvas2D;
begin
FBuffer.Fill(BGRA($77, $77, $77));
centerX := Width div 2;
centerY := Height div 2;
radius := 220;
canvas2D := FBuffer.Canvas2D;
for i := 0 to CIndex - 1 do
begin
charAngle := (i * 2 * Pi / Length(txt)) + RotAngle;
x := centerX + Round(radius * Cos(charAngle));
y := centerY + Round(radius * Sin(charAngle));
canvas2D.save;
canvas2D.translate(x, y);
canvas2D.rotate(charAngle + Pi/2);
canvas2D.fillStyle(BGRA($ee,$ee,$ee));
canvas2D.font := 'bold 64px Arial';
canvas2D.fillText(txt[i+1], 0, 0);
canvas2D.fillStyle(BGRA($ff,$00,$00));
canvas2D.fillText(txt[i+1], 8, 0);
canvas2D.restore;
end;
RotAngle := RotAngle + 0.04;
end;
Плюсы этого подхода:
- Простота реализации
- Использование Canvas2D, похожего на HTML5 Canvas
- Поддержка сложных трансформаций
Минусы:
- Более низкая производительность по сравнению с прямым использованием BGRABitmap
- Ограниченная гибкость в настройке эффектов
Оптимизированный вариант с BGRAVirtualScreen
Gigatron предложил более производительное решение с использованием BGRAVirtualScreen:
procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
var
centerX, centerY, radius: Integer;
i: Integer;
charAngle: Single;
x, y: Integer;
begin
Bitmap.Fill(BGRA($77, $77, $77));
centerX := BGRAVirtualScreen1.Width div 2;
centerY := BGRAVirtualScreen1.Height div 2;
radius := 220;
bitmap.FontFullHeight := 72;
bitmap.FontName := 'Arial';
bitmap.FontStyle := [fsBold];
for i := 0 to CIndex - 1 do
begin
charAngle := (i * 2 * Pi / Length(txt)) + RotAngle;
x := centerX + Round(radius * Cos(charAngle));
y := centerY + Round(radius * Sin(charAngle));
bitmap.TextOutAngle(x,y-30, Round(charAngle),txt[i+1],BGRA(255,255,255));
bitmap.TextOutAngle(x+4,y-30,Round(charAngle),txt[i+1],BGRA(255,0,0));
end;
end;
Улучшения:
- Использование BGRAVirtualScreen для автоматического управления перерисовкой
- Прямая работа с TBGRABitmap для лучшей производительности
- Метод TextOutAngle для упрощения вывода повернутого текста
Расширенный вариант с эффектом прокрутки
Для более сложных эффектов, таких как бесконечная прокрутка текста по кругу, можно использовать следующий подход:
type
TChr = record
Char: Char;
Angle: Single;
Rotations: Integer;
Age: Integer;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer;
angleStep, newAngle, angleDiff: Single;
posfree: Boolean;
charAppearSpeed, totalChr: Integer;
rotationSpeed, chrFullRotated: Single;
begin
charAppearSpeed := 11;
rotationSpeed := 1.2 * Pi / 180;
totalChr := 60;
angleStep := (2 * Pi) / totalChr;
// Добавление новых символов
if (FrameCount mod charAppearSpeed = 0) and (CCharIndex < Length(txt) * 2) then
begin
posfree := False;
newAngle := 0;
for i := 0 to Length(ChrArray) - 1 do
begin
angleDiff := Abs(ChrArray[i].Angle - newAngle);
if angleDiff < angleStep * 0.8 then
begin
posfree := True;
Break;
end;
end;
if not posfree then
begin
SetLength(ChrArray, Length(ChrArray) + 1);
ChrArray[Length(ChrArray) - 1].Char := txt[(CCharIndex mod Length(txt)) + 1];
ChrArray[Length(ChrArray) - 1].Angle := newAngle;
ChrArray[Length(ChrArray) - 1].Rotations := 0;
ChrArray[Length(ChrArray) - 1].Age := 0;
Inc(CCharIndex);
end;
end;
// Обновление позиций символов
for i := Length(ChrArray) - 1 downto 0 do
begin
ChrArray[i].Angle := ChrArray[i].Angle - rotationSpeed;
ChrArray[i].Age := ChrArray[i].Age + 1;
chrFullRotated := 2 * Pi - (40 * Pi / 180);
if Abs(ChrArray[i].Angle) >= chrFullRotated then
begin
if i < Length(ChrArray) - 1 then
ChrArray[i] := ChrArray[Length(ChrArray) - 1];
SetLength(ChrArray, Length(ChrArray) - 1);
Continue;
end;
if ChrArray[i].Angle <= -2 * Pi then
begin
ChrArray[i].Angle := ChrArray[i].Angle + 2 * Pi;
ChrArray[i].Rotations := ChrArray[i].Rotations + 1;
end;
end;
// Перезапуск анимации
if (CCharIndex >= Length(txt)) and (Length(ChrArray) = 0) then
CCharIndex := 0;
Inc(FrameCount);
BGRAVirtualScreen1.RedrawBitmap;
end;
Оптимизация вычислений
Для улучшения производительности можно применить следующие оптимизации:
Предварительный расчет координат:
// В объявлении класса
FCoords: array of record
X, Y: Integer;
Angle: Single;
end;
// Инициализация
procedure TForm1.InitCoords;
var
i: Integer;
begin
SetLength(FCoords, Length(txt));
for i := 0 to High(FCoords) do
begin
FCoords[i].Angle := i * 2 * Pi / Length(txt);
FCoords[i].X := Round(Cos(FCoords[i].Angle) * 220);
FCoords[i].Y := Round(Sin(FCoords[i].Angle) * 220);
end;
end;
Использование кэширования:
// Кэширование отрисованных символов
var
CharCache: array[Char] of TBGRABitmap;
// Инициализация кэша
procedure TForm1.InitCharCache;
var
c: Char;
begin
for c := #32 to #126 do
begin
CharCache[c] := TBGRABitmap.Create(100, 100, BGRAPixelTransparent);
CharCache[c].FontFullHeight := 72;
CharCache[c].FontName := 'Arial';
CharCache[c].FontStyle := [fsBold];
CharCache[c].TextOut(0, 0, c, BGRAWhite);
end;
end;
Дополнительные эффекты
Для создания более впечатляющих визуальных эффектов можно добавить:
Плавное появление и исчезание символов:
// В процедуре отрисовки
var
alpha: Byte;
begin
alpha := Round(255 * (1 - Abs(ChrArray[i].Angle)/(2*Pi)));
bitmap.TextOutAngle(x, y-30, Round(charAngle), txt[i+1], BGRA(255,255,255,alpha));
end;
Изменение размера символов в зависимости от позиции:
var
scale: Single;
begin
scale := 0.5 + 0.5 * Cos(ChrArray[i].Angle);
bitmap.FontFullHeight := Round(72 * scale);
end;
Заключение
Мы рассмотрели несколько подходов к созданию анимированного вращающегося текста в Delphi и Lazarus. Оптимальный выбор зависит от конкретных требований:
Для простых случаев подойдет вариант с BGRAVirtualScreen
Для сложных анимаций лучше использовать массив символов с индивидуальными параметрами
Для максимальной производительности стоит применять предварительные вычисления и кэширование
Библиотека BGRABitmap предоставляет богатые возможности для создания впечатляющих графических эффектов с относительно небольшими усилиями. Экспериментируя с параметрами и комбинируя различные подходы, можно достичь профессиональных результатов в визуализации текста.
В статье рассматриваются методы создания анимированного вращающегося текста в Delphi и Lazarus с использованием библиотеки BGRABitmap, включая базовые и оптимизированные подходы, а также дополнительные эффекты.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.