Создание программы с видом наподобие рабочего стола маков в Delphi с помощью библиотеки LayerFormEffect
Для начала нам понадобятся качественные иконки, желательно в формате Portable Network Graphics с использованием канала прозрачности. Архив иконок для этой статьи можно скачать здесь. Создаем новый проект, устанавливаем у формы BorderStyle в bsNone и кидаем на нее компоненты из библиотеки LayerFormEffect.
Связываем компоненты lfeLayerForm1, lfeLayerEffectList1 и lfeLayerEffectControl1 между собой, у компонента lfeLayerForm1 свойство FormNormalState устанавливаем в fsBottom. Устанавливаем у lfeLayerEffectControl1 размеры 200 на 200.
Грузим иконки в lfeBitmapsList1.
Я хотел попробовать сделать у иконок тень и эффект блеска, поэтому нарисовал и добавил в список еще два рисунка - звездочку и тени. У 6-ой и 7-ой картинок (у меня звездочка и тень соответственно) обрезаем края (кнопка "Обрезать"). Подготовка завершена, теперь будем колдовать над эффектами Пару слов о том как это работает изнутри - компонент lfeLayerEffectList1 через lfeLayerForm1 перехватывает события (на которые назначены эффекты) приходящие в lfeLayerEffectControl1, объявленные в секции published и начинающиеся на "On". Событие "OnDesigned" используется только в Design стиле, все остальные в рабочем. Итак начнем. Я задумал так - у иконки будет тень, при наведении мышки, она будет увеличиваться из угла в центр и после увеличения будет мерцать звездочка. На нажатие иконка будет эмулировать нажатие. Выбираем lfeLayerEffectList1, привязываем к компоненту эффект,
назначаем на компонент событиe "OnDesigned"
и добавляем первый шаг.
Анимация может проходить в несколько шагов (на событии "OnMouseEnter" мы это увидим), сейчас достаточно одного. Пару слов об эффектах, их образно можно отнести к двум видам, те которые могут исполняться на любом этапе (этапов три: инициализация, анимация и финализация) и те, у которых процедура выполнения предопределена. К первому типу относятся сбросы, очистки, а так же эффект "рисовать компонент". Рисование происходит следующим образом, все действия производятся с временным холстом, далее он копируется на холст компонента. Добавим к Step1 сбросы матрицы преобразований, матрицы цветов, а также очистку холста компонента и временного. Учитывая, что у этого события анимации не будет, ставим у всех эффектов в свойстве TypeAnimates только lfetaInit (хотя тут можно выставить и lfetaAnimate).
Для качественного отображения иконок мы их изначально уменьшим, поэтому выбираем и добавляем эффект "Масштабирование" и устанавливаем значения в секции ValueAnimate в 0,75, TypeScale в tsRightBottom:
Добавляем эффект "Переместить", в секции ValueAnimate устанавливаем -25 (нам нужно будет засунуть тень под иконку), добавляем эффект "Рисовать на холсте" с Image=0 и ImageState=isRightBottom. Добавим тень под иконку, добавляем "Переместить" c -6, 22 координатами в секции ValueAnimate , "Рисовать на холсте" с Image=7 и ImageState=isRightBottom. И на конец добавим "Рисовать компонент" с lfetaAnimate = True. Жмем тестировать и вуаля:
Выбираем событие "OnDesigned", копируем его и вставляем в "OnLoad", "OnMouseDown", "OnMouseUp" В двух последних событиях удаляем эффект "Масштабирование" и шаманим с перемещением у "OnMouseDown" (у первого "Перемещения" ставим -20, -20, у второго -4, 19). Далее шаманим с размерами изображения, делаем так - выбираем "OnMouseUp" и жмем тестировать. Теперь на форме подгоняем размеры компонента так, чтобы изображение в нем умещалось:
Добавляем на форму еще 4-е компонента. Выбираем в "Коллекция эффектов" lfeLayerEffectControl1, копируем дерево эффектов и вставляем на вновь созданные. Меняем у всех компонентов у эффектов "Рисовать на холсте" изображения на нужные и подгоняем их размеры по выше приведенной методике:
Возвращаемся к первому компоненту. Выбираем событие "OnDesigned", копируем его и вставляем в "OnMouseEnter". Так как подразумевается анимация делаем следующее:
- у эффектов "Сбросить матрицу преобразований", "Очистить компонент", "Очистить холст" lfetaAnimate = True;
- "масштабировать" настраиваем так:
т.е. будем изменять линейно масштабы для обоих координат с 0,75 до 1 за 10 шагов. С первым шагом все, добавляем шаг2 и шаг3. Приведу порядок эффектов и их настройки:
Step2
- "Очистить холст", "Сбросить матрицу цветов", "Сбросить матрицу преобразований", "Очистить компонент" устанавливаем lfetaAnimate = True;
- "Рисовать холст" не изменяем (т.е. мы скопировали холст предыдущего шага на холст этого шага);
- "Рисовать компонент", "Очистить холст" устанавливаем lfetaAnimate = True;
- "Изменить цвет" у ValueInitial.Alpha.TypeInitialValue = tivValue (использовать начальное значение) и ValueInitial.Alpha.Value = 0 (устанавливает начальное значение в 0). ValueAnimate.Alpha.Value = 255 (устанавливает конечное значение в 255), ValueAnimate.Alpha.Animate.Animation = True (будем анимировать), ValueAnimate.Alpha.Animate.CountStep = 40 (за 40 шагов) и ValueAnimate.Alpha.Animate.TypeChange = tcSin (и менять значение по синусоиде);
- "Повернуть" ValueAnimate.Angle.Value = 90 (повернуть на 900) ValueAnimate.Angle.Animate.Animation = True (будем анимировать) ValueAnimate.Angle.Animate.CountStep = 50 (за 50 шагов), ValueAnimate.X.Value = 102 и ValueAnimate.Y.Value = 24. Маленькое отступление - вращается весь холст относительно координат ValueAnimate.X.Value и ValueAnimate.Y.Value, поэтому, чтобы выбранная точка вращения оставалась на месте, следующим эффектом должен быть эффект "Переместить" с компенсирующим смещением координат. Определить X, Y обоих эффектов просто, информация выводиться под изображением, надо только определить точку вращения. Я выставил так, у "Повернуть" 102, 24 у "Переместить" 29, -56 (размер компонента 146, 160) Больше у координат ничего не меняем:
- "Переместить" ValueAnimate.X.Value = 29 и ValueAnimate.Y.Value = -56;
- "Рисовать на холсте" Image = 6 (рисуем звездочку);
- "Рисовать компонент" lfetaAnimate = True.
Step3
- "Очистить холст", "Сбросить матрицу цветов", "Сбросить матрицу преобразований", "Очистить компонент" устанавливаем lfetaAnimate = True;
- "Переместить" ValueAnimate.X.Value = -25 и ValueAnimate.Y.Value = -25;
- "Рисовать на холсте" Image = 0 ImageState = isRightBottom;
- "Переместить" ValueAnimate.X.Value = -6 и ValueAnimate.Y.Value = -22;
- "Рисовать на холсте" Image = 7 ImageState = isRightBottom;
- "Рисовать компонент" lfetaAnimate = True;
- "Очистить холст" lfetaAnimate = True;
- "Сбросить матрицу преобразований" lfetaAnimate = True;
- "Изменить цвет" у ValueInitial.Alpha.TypeInitialValue = tivValue и ValueInitial.Alpha.Value = 255. ValueAnimate.Alpha.Value = 0, ValueAnimate.Alpha.Animate.Animation = True, ValueAnimate.Alpha.Animate.CountStep = 50 и ValueAnimate.Alpha.Animate.TypeChange = tcSin;
- "Повернуть" ValueInitial.Angle.Value = 90, ValueInitial.Angle.TypeInitialValue = tivValue. ValueAnimate.Angle.Value = 180 ValueAnimate.Angle.Animate.Animation = True, ValueAnimate.Angle.Animate.CountStep = 50, ValueAnimate.X.Value = 102 и ValueAnimate.Y.Value = 24;
- "Переместить" ValueInitial.X.Value = 29 ValueInitial и ValueInitial.Y.Value = -56;
- "Рисовать на холсте" Image = 6;
- "Рисовать компонент" lfetaAnimate = True.
Выбираем событие "OnDesigned", копируем его и вставляем в "OnMouseLeave" и будем изменять линейно масштабы для обоих координат с 1 до 0,75 за 10 шагов. Приведу порядок эффектов и их настройки:
- "Очистить холст", "Сбросить матрицу цветов", "Сбросить матрицу преобразований", Очистить компонент" устанавливаем lfetaAnimate = True;
- "Масштабировать" ValueInitial.X.Value = 1 ValueInitial.TypeInitialValue = tivValue и ValueInitial.Y.Value = 1 ValueInitial.TypeInitialValue = tivValue. ValueAnimate.X.Value = 0,75 ValueAnimate.X.Animate.Animation = True, ValueAnimate.X.Animate.CountStep = 10 и ValueAnimate.Y.Value = 0,75 ValueAnimate.Y.Animate.Animation = True, ValueAnimate.Y.Animate.CountStep = 10;
- "Переместить" ValueAnimate.X.Value = -25 и ValueAnimate.Y.Value = -25;
- "Рисовать на холсте" Image = 0 ImageState = isRightBottom;
- "Переместить" ValueAnimate.X.Value = -6 и ValueAnimate.Y.Value = -22;
- "Рисовать на холсте" Image = 9 ImageState = isRightBottom;
- "Рисовать компонент" lfetaAnimate = True.
Уф
Приведу порядок эффектов и их настройки для компонента lfeLayerEffectControl2, который будет столом:
- "Очистить холст", "Сбросить матрицу преобразований", Очистить компонент" устанавливаем lfetaInit= True;
- "Рисовать на холсте" Image = 5 ImageState = isBottom;
- "Рисовать компонент" lfetaAnimate = True;
- "Сдвинуть" ValueAnimate.X.Value = -0,6;
- "Переместить" ValueAnimate.X.Value = 80 и ValueAnimate.Y.Value = -8;
- "Рисовать текст" тут я ввел текст и поигрался с размерами и прозрачностью;
- "Рисовать компонент" lfetaAnimate = True.
Копируем "OnDesigned" на "OnLoaded". Добавляем Popup меню на форму, добавляем в него строчку "Close" и привязываем к lfeLayerEffectControl2. В lfeLayerEffectList1 к lfeLayerEffectControl2 добавляем эффект "Обработать" к событию OnMouseUp (соответственно добавляем событие и шаг) и в отклике на событие вставляем:
procedure TForm1.lfeLayerEffectControl2MouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbRight then lfeLayerEffectControl2.PopupAtCursor;
end;
procedure TForm1.Close1Click(Sender: TObject);
begin
Close;
end;