Давайте познакомимся на примерах со средствами анимации графических объектов, которые есть в Delphi, и рассмотрим несколько вариантов, как в Delphi быстро реализовать практически любые нетривиальные потребности заказчика.
Уверен, что все уже заметили, насколько часто в последние годы мы сталкиваемся с таким явлением, как «Тыж<…>» — Тыжврач, Тыжучитель, Тыжархитектор и много еще таких же «Тыж..» — Generics, которые должны знать и уметь все, что по мнению друзей и знакомых входит в область их деятельности.
Недавно мне повезло узнать, что я — «ТЫЖПРОГРАММИСТ!» и даже с восклицательным знаком!. Этот знак, в конечном счете, вынудил меня срочно заняться тем, чем никогда раньше не приходилось — анимацией в пользовательском интерфейсе.
Приятель раскритиковал все существующие индикаторы работы на мобильных устройствах — все эти песочные часы, прогресс-бары, секторные и другие «бабочки». Для его задачи нужен только индикатор в виде карманных часов с вращающимися в них шестеренками.
И правда, в современных мобильных приложениях пользовательский интерфейс и привлекательность внешнего представления имеют определяющую роль, а успех приходит к приложениям с удобным и оригинальным воплощением пользовательских функций.
Так или иначе, давайте откроем Delphi и создадим приложение, которое будет передвигать окружность по внутренней поверхности другой окружности, вращаясь по мере движения — как основу для «часиков».
Как всегда в информатике, все можно сделать тремя-пятью и более способами. Для начала, покажу способ, предложенный Всеволодом Леоновым — потерянной нами Delphi-звездой, непререкаемым для меня авторитетом в области 2D и 3D графики. С его разрешения, покажем этот пример, который весьма прост, но прекрасно показывает всю возможную мощь анимации в FireMonkey.
На форму помещены два круга: большой и маленький, вложенный в большой. Для наглядности внутрь малого круга помещен еще меньший квадрат. Параметрически движение по окружности можно задать при помощи пары sin / cos функций. Поэтому для горизонтали и вертикали используются по 2 анимации типа TFloatAnimation, у которых установлена синусоидальная интерполяция.
Circle1: TCircle
Size.Width = 400
Size.Height = 400
Circle2: TCircle
Size.Width = 80
Size.Height = 80
faRotation: TFloatAnimation
Duration = 5.
Loop = True
RotationAngle StartValue = 0.
StopValue = 360.
faX1: TFloatAnimation
AutoReverse = True
Enabled = True
Duration = 4.
Interpolation = Sinusoidal
Inverse = True
OnFinish = faX1Finish
PropertyName = 'Position.X'
StartValue = 320.
StopValue = 160.
faX2: TFloatAnimation
AutoReverse = True
Duration = 4.
Interpolation = Sinusoidal
Inverse = True
OnFinish = faX2Finish
PropertyName = 'Position.X'
StartValue = 0.
StopValue = 160.
faY0: TFloatAnimation
Enabled = True
Duration = 4.
Interpolation = Sinusoidal
OnFinish = faY0Finish
PropertyName = 'Position.Y'
StartValue = 320.
StopValue = 160.
faY1: TFloatAnimation
AutoReverse = True
Duration = 4.
Interpolation = Sinusoidal
Inverse = True
OnFinish = faY1Finish
PropertyName = 'Position.Y'
StartValue = 0.
StopValue = 160.
faY2: TFloatAnimation
AutoReverse = True
Duration = 4.
Interpolation = Sinusoidal
Inverse = True
PropertyName = 'Position.Y'
StartValue = 320.
StopValue = 160.
Рассмотрим горизонталь:
- faX1 – отвечает за движение из центра вправо и обратно<
- faX2 – отвечает за движение из центра влево и обратно
Если использовать такую пару, то можно подобрать правильную комбинацию StartValue/StopValue + Inverse (true/false).
- у каждой анимации выключен Loop (зацикливание, бесконечное повторение);
- у каждой анимации включён AutoReverse (чтобы сделать автоматически «туда-и-обратно»)
- по окончании работы faX1 на событие «конец» включается faX2
- по окончании работы faX2 на событие «конец» включается faX1
Чтобы синхронизировать эти анимации выполняется простая процедура: попеременно включая-выключая друг друга эти анимации двигают объект: «из центра вправо и обратно» и «из центра влево и обратно»
Чуть сложнее с вертикальной анимацией. Тут двумя объектам TFloatAnimation обойтись нельзя, так как начальное положение объекта не в центре, а в нижней точке. Поэтому faY0 – работает с начала и один раз, переводя объект в «центральное положение». За это время объект по горизонтали уже ушёл в крайнюю правую точку. Потом уже пара faY1 и faY2 работает также, как и faX1 и faX2.
Управление по горизонтали и вертикали должны работать так, что когда по вертикали — крайняя точка, по горизонтали – центральная. И – наоборот.
Обработчики события OnFinish очень просты
procedure TForm1.faX1Finish(Sender: TObject);
begin
faX2.Start;
end;
procedure TForm1.faX2Finish(Sender: TObject);
begin
faX1.Start;
end;
procedure TForm1.faY0Finish(Sender: TObject);
begin
faY1.Start;
end;
procedure TForm1.faY1Finish(Sender: TObject);
begin
faY2.Start;
end;
procedure TForm1.faY2Finish(Sender: TObject);
begin
faY1.Start;
end;
Но есть и другой способ создания такого приложения. Об этом я расскажу в следующем посте
Часть 2. Анимация графических объектов в Dephi на примерах