Анимация увеличения для UserControl wpf
Как сделать так, чтобы при наведении мыши на UserControl, он увеличивался? Причём относительно текущих размеров?
Ответы (1 шт):
Предположим, у нас есть такая разметка:
<Grid Background="Silver" VerticalAlignment="Center" HorizontalAlignment="Center" Width="300" Height="150">
<Border Background="#FF1D1D1D" >
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="45" Text="Привет мир!" Foreground="White"/>
</Border>
</Grid>
Она простая, лишь Grid расположенный по центру с установленным цветом, который содержит Border у которого также есть свой цвет, ну и сам он содержит простой TextBlock, расположенный также по центру и с "большим" размером шрифта. Наша задача Border сделать чуть меньше и анимировать его при событии мыши.
Масштабирование
За всякие манипуляции с пропорциями, в XAML отвечает RenderTransform, а именно масштаб, это ScaleTransform. Давайте применим это к разметке выше:
<Grid Background="Silver" VerticalAlignment="Center" HorizontalAlignment="Center" Width="300" Height="150">
<Border Background="#FF1D1D1D" >
<Border.RenderTransform>
<ScaleTransform ScaleX=".5" ScaleY=".5"/>
</Border.RenderTransform>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="45" Text="Привет мир!" Foreground="White"/>
</Border>
</Grid>
Результатом у нас будет такое:
Как видим, внутренний Border изменил свои пропорции, но он не по центру. Чтобы это исправить, нам надо сдвинуть центральную точку, а за это отвечает свойство RenderTransformOrigin, зададим нашему Border' это свойство со значением 0.5 0.5 и увидим то, что нам надо:
Триггеры
Теперь давайте разберемся как нам обработать "наведение мыши" на нужный объект в XAML.
А тут все просто, для взаимодействия с событиями, отлов изменений свойств и так далее, для всего этого существую триггеры, их всего 4:
| Название | Описание |
|---|---|
Trigger (триггер свойств) |
Самый простой триггер, который следит за значением свойства и если оно соответствует заданному, то выполняет указанное действие. |
DataTrigger (триггер данных) |
Его цель аналогична предыдущему, но разница в том, что он поддерживает привязки и мы можем отслеживать тем самым свойства из ViewModel слоя. |
MultiTrigger (Мультитриггер) |
Позволяет отслеживать сразу несколько свойств при помощи коллекции Conditions. |
EventTrigger (триггер событий) |
А он уже следит за тем, какое событие выдал наш элемент. Допустим клик кнопки, либо наведение мыши. |
Исходя из этого вы можете составить любое условие, по которому контрол изменит цвет, запустит анимацию или что-либо еще. В вашей задачи фигурирует "при наведении мыши", а значит нам нужен EventTrigger. Давайте допишем пример выше, добавив в него триггер:
<Grid Background="Silver" VerticalAlignment="Center" HorizontalAlignment="Center" Width="300" Height="150">
<Border Background="#FF1D1D1D" RenderTransformOrigin="0.5 0.5" >
<Border.RenderTransform>
<ScaleTransform ScaleX=".5" ScaleY=".5"/>
</Border.RenderTransform>
<Border.Triggers>
<EventTrigger RoutedEvent="MouseEnter" >
</EventTrigger>
</Border.Triggers>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="45" Text="Привет мир!" Foreground="White"/>
</Border>
</Grid>
Здесь в качестве события мы берем MouseEnter - это событие происходит тогда, когда мы наводим мышью на объект.
Анимация
Наша задача сейчас, это анимировать значения у ScaleTransform, а именно ScaleX и ScaleY, делается это примерно так:
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" To="1" Duration="0:0:.4">
<DoubleAnimation.EasingFunction>
<QuarticEase />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" To="1" Duration="0:0:.4" >
<DoubleAnimation.EasingFunction>
<QuarticEase />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
Поясняю:
- Сначала мы создаем базовый элемент
BeginStoryboard, который будет отвечать за анимацию - Далее мы создаем саму анимацию при помощи
Storyboard. Если дословно перевести, то думаю будет ясно, что это "раскадровка". - Внутри мы можем хоть покадрово анимировать все, что нам необходимо, но в WPF есть ряд готовых объектов, которые отлично анимируют нужные свойства. Для нужных нам свойство нужна анимация
DoubleAnimation(ибо значения типаdouble). У нее мы задаем:Storyboard.TargetProperty- цель анимации (наше свойствоScaleXилиScaleY)To- до какого значение будет плавно идти анимация.From- мы тут не ставим, ибо нам нужна анимация "от текущего до нужного", а если поставим, то будет "от заданного до нужного", что приведет к рывкам анимации.Duration- как долго эта анимация должна идти.- Также тут стоит
EasingFunction- они позволяют анимацию сделать более плавно, например в начале ускорить, а в конце плавно замедлить. Почитать про них можете например тут.
Также я думаю вы заметили, что тут анимируется сразу два свойства, Storyboard как я уже говорил выше, это набор кадров и в нем вы можете без проблем задать их несколько!
Теперь давайте соединим это все и посмотрим на результат:
<Grid Background="Silver" VerticalAlignment="Center" HorizontalAlignment="Center" Width="300" Height="150">
<Border Background="#FF1D1D1D" RenderTransformOrigin="0.5 0.5" >
<Border.RenderTransform>
<ScaleTransform ScaleX=".5" ScaleY=".5"/>
</Border.RenderTransform>
<Border.Triggers>
<EventTrigger RoutedEvent="MouseEnter" >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" To="1" Duration="0:0:.4">
<DoubleAnimation.EasingFunction>
<QuarticEase />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" To="1" Duration="0:0:.4" >
<DoubleAnimation.EasingFunction>
<QuarticEase />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="45" Text="Привет мир!" Foreground="White"/>
</Border>
</Grid>
Собственно, вот и готовая анимация масштабирования, осталось только сделать тоже самое, но в обратную сторону, а это уже думаю вы сможете сделать самостоятельно.


