Blendを使ってButtonのホバーエフェクトを作る Part2
昨日の続きで、また別のホバーエフェクトを真似してみました。
今回はblendの操作手順とかはなしで、xamlコードだけメモしときます。
てか、添付プロパティとかを多用してると、BlendのUI上からアニメーションの設定とかできない。。。
(ContentPresenter内でのTextBlock.Foregroundプロパティの設定とか。。。)
背景・ボーダー・文字カラーをふわっと変更するボタン
<ControlTemplate x:Key="ButtonControlTemplate2" TargetType="{x:Type Button}"> <Border x:Name="border" Background="#FF333333" BorderBrush="#FF333333" BorderThickness="2"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"> <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF333333"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border"> <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF333333"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="contentPresenter"> <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FFFFFFFF"/> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="contentPresenter"> <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF59B1EB"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"> <EasingColorKeyFrame KeyTime="0:0:0.3" Value="White"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border"> <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF59B1EB"/> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="contentPresenter"> <EasingColorKeyFrame KeyTime="0:0:0.2" Value="#FF59B1EB"> <EasingColorKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingColorKeyFrame.EasingFunction> </EasingColorKeyFrame> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border"> <EasingColorKeyFrame KeyTime="0:0:0.2" Value="#FFCDCDCD"> <EasingColorKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingColorKeyFrame.EasingFunction> </EasingColorKeyFrame> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border"> <EasingColorKeyFrame KeyTime="0:0:0.2" Value="#FF59B1EB"> <EasingColorKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingColorKeyFrame.EasingFunction> </EasingColorKeyFrame> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <ContentPresenter x:Name="contentPresenter" TextBlock.Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" OpacityMask="Black"/> </Border> </ControlTemplate>
文字間隔を広げるエフェクト
TextBlockの文字間隔を調整するプロパティはありません。
そこで、以下のサイトに書かれていた方法で、TextBlock内の文字間隔を調整しています。
テキストをItemsControlのItemsSourceに渡して、1文字ずつ描画する、という何ともトリッキーな方法です。
http://stackoverflow.com/questions/5843562/how-can-i-specify-letter-spacing-or-kerning-in-a-wpf-textbox
あと、DataTemplate内の要素のプロパティをStoryBoardから操作できなかったので、以下のような方法でマージンのアニメーションを行っています。
- 画面に表示しないダミーのTextBlockを作成
- DataTemplate内のTextBlockは、↑のダミーのTextBlockのMarginとバインド
- StoryBoardでは、このダミーのTextBlockのMargin値をアニメーションさせる。
これも随分とトリッキーなやり方なので、ここで書いた例はダメなサンプルですね。。。
ただ、「ダミーのオブジェクトを介して無理やりバインドを適用する」ってのは、いざという時のダーティーテクとして使えるかも。
マウスクリック時には、RenderTransformを使って、文字を少し下に移動させてます。
<ControlTemplate x:Key="ButtonControlTemplate3" TargetType="{x:Type Button}"> <Border Background="#FF333333"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"> <Storyboard> <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="txtDummyObject"> <EasingThicknessKeyFrame KeyTime="0:0:0.3" Value="0"> <EasingThicknessKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingThicknessKeyFrame.EasingFunction> </EasingThicknessKeyFrame> </ThicknessAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="txtDummyObject"> <EasingThicknessKeyFrame KeyTime="0:0:0.3" Value="3,0"> <EasingThicknessKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingThicknessKeyFrame.EasingFunction> </EasingThicknessKeyFrame> </ThicknessAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="txtDummyObject"> <EasingThicknessKeyFrame KeyTime="0:0:0.2" Value="3,0"> <EasingThicknessKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingThicknessKeyFrame.EasingFunction> </EasingThicknessKeyFrame> </ThicknessAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="txtDummyObject"> <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="3"> <EasingDoubleKeyFrame.EasingFunction> <CubicEase EasingMode="EaseInOut"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid> <TextBlock x:Name="txtDummyObject" Visibility="Collapsed" Margin="0" RenderTransformOrigin="0.5,0.5"> <TextBlock.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </TextBlock.RenderTransform> </TextBlock> <ItemsControl ItemsSource="{Binding Content, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" TextBlock.Foreground="White"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" Margin="{Binding Margin, ElementName=txtDummyObject}" RenderTransform="{Binding RenderTransform, ElementName=txtDummyObject}" RenderTransformOrigin="0.5,0.5"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Border> </ControlTemplate>
とりあえず、今日はここまで。