読者です 読者をやめる 読者になる 読者になる

SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

Blendを使ってButtonのホバーエフェクトを作る Part3

ボタンのホバーエフェクト、さらに続きます。
今回も、xamlだけメモ。

背景を透過させ、ホバー時にうっすらと背景色を出す

これはシンプルですね。
以下のようにボタン背景の透明度を変化させてるだけです。
で、このボタンを画像の上に配置しています。

        <ControlTemplate x:Key="ButtonControlTemplate4" TargetType="{x:Type Button}">
            <Border x:Name="border" BorderThickness="2" BorderBrush="#FFFFFFFF" Background="Transparent" OpacityMask="Black" >
                <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="Transparent">
                                        <EasingColorKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingColorKeyFrame.EasingFunction>
                                    </EasingColorKeyFrame>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border">
                                    <EasingColorKeyFrame KeyTime="0:0:0.3" Value="#33FFFFFF">
                                        <EasingColorKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingColorKeyFrame.EasingFunction>
                                    </EasingColorKeyFrame>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="border">
                                    <EasingColorKeyFrame KeyTime="0:0:0.2" Value="#66888888">
                                        <EasingColorKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingColorKeyFrame.EasingFunction>
                                    </EasingColorKeyFrame>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <ContentPresenter TextBlock.Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </ControlTemplate>

ボーダースタイルを変更する

ボタンの周囲の線を破線にできるように、
BorderではなくRectangleを使用して周囲の枠を書いています。
また、破線の定義を行うStrokeDashArrayプロパティはStoryBoardでアニメーションができませんでした。
そこで、StrokeDashArrayプロパティの値が異なる、複数のRectangleを配置しておき、VisualStateの状態に合わせてVisibilityを切り替えています。

        <ControlTemplate x:Key="ButtonControlTemplate5" TargetType="{x:Type Button}">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="rectangle">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="rectangle1">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="rectangle">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="rectangle2">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Rectangle x:Name="rectangle" Fill="White" Stroke="#FF333333" StrokeThickness="2"/>
                <Rectangle x:Name="rectangle1" Fill="White" Stroke="#FF333333" StrokeThickness="2" StrokeDashArray="2 2" Visibility="Collapsed"/>
                <Rectangle x:Name="rectangle2" Fill="White" Stroke="#FF333333" StrokeThickness="2" StrokeDashArray="1 1" Visibility="Collapsed"/>
                <ContentPresenter TextBlock.Foreground="#FF333333" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Grid>
        </ControlTemplate>

内側にブロックを表示する

        <ControlTemplate x:Key="ButtonControlTemplate6" TargetType="{x:Type Button}">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                </DoubleAnimationUsingKeyFrames>
                                <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="rectangle">
                                    <EasingThicknessKeyFrame KeyTime="0:0:0.2" Value="2">
                                        <EasingThicknessKeyFrame.EasingFunction>
                                            <CubicEase EasingMode="EaseInOut"/>
                                        </EasingThicknessKeyFrame.EasingFunction>
                                    </EasingThicknessKeyFrame>
                                </ThicknessAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Rectangle Fill="White" Stroke="#FF333333" StrokeThickness="2"/>
                <Rectangle x:Name="rectangle" Fill="White" Stroke="#FF333333" StrokeThickness="2" Margin="4" Opacity="0"/>
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Grid>
        </ControlTemplate>

まだまだ続くかも。