Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shake animation (3d version)

I want to use this animation on errors, like the one shown here:

How to achieve that in wpf? I have feeling this should be a combination (composition?) of multiple transformations, but which ones and how exactly?

Here is a starter (mcve or call it "my attempt"), which is ugly and is not even close to what I want:

<Grid>
    <Border x:Name="border"
            Width="200"
            Height="200"
            BorderBrush="Black"
            BorderThickness="1"
            CornerRadius="4"
            Background="LightBlue"
            RenderTransformOrigin="0.5,0">
        <Border.RenderTransform>
            <TransformGroup>
                <ScaleTransform />
                <SkewTransform />
                <RotateTransform />
                <TranslateTransform />
            </TransformGroup>
        </Border.RenderTransform>
        <Border.Effect>
            <DropShadowEffect BlurRadius="20" />
        </Border.Effect>
        <Button VerticalAlignment="Bottom"
                HorizontalAlignment="Center"
                Margin="0,0,0,10"
                Padding="5"
                Content="Click">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard FillBehavior="Stop">
                            <DoubleAnimation Storyboard.TargetName="border"
                                             Storyboard.TargetProperty="RenderTransform.Children[1].(SkewTransform.AngleX)"
                                             To="5" Duration="0:0:0.1"/>
                            <DoubleAnimation Storyboard.TargetName="border"
                                             Storyboard.TargetProperty="RenderTransform.Children[1].(SkewTransform.AngleX)"
                                             To="-5"
                                             BeginTime="0:0:0.1"
                                             Duration="0:0:0.2" />
                            <DoubleAnimation Storyboard.TargetName="border"
                                             Storyboard.TargetProperty="RenderTransform.Children[1].(SkewTransform.AngleX)"
                                             To="5"
                                             BeginTime="0:0:0.3"
                                             Duration="0:0:0.2" />
                            <DoubleAnimation Storyboard.TargetName="border"
                                             Storyboard.TargetProperty="RenderTransform.Children[1].(SkewTransform.AngleX)"
                                             BeginTime="0:0:0.5"
                                             Duration="0:0:0.1" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </Border>
</Grid>

There are many 2d shake posts around (click, click), but I need animation which tells "you are wrong" and not the one which says "let's dance".

like image 713
Sinatr Avatar asked Aug 10 '15 11:08

Sinatr


2 Answers

So far the best effect can be achieved like this:

<Grid>
    <Border Width="200"
            Height="200"
            BorderBrush="Black"
            BorderThickness="1"
            CornerRadius="4"
            Background="LightBlue"
            RenderTransformOrigin="0.5,0">
        <Border.RenderTransform>
            <RotateTransform x:Name="transform" />
        </Border.RenderTransform>
        <Border.Effect>
            <DropShadowEffect BlurRadius="20" />
        </Border.Effect>
        <Button VerticalAlignment="Bottom"
                HorizontalAlignment="Center"
                Margin="0,0,0,10"
                Padding="5"
                Content="Click">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard FillBehavior="Stop">
                            <DoubleAnimation Storyboard.TargetName="transform"
                                             Storyboard.TargetProperty="Angle"
                                             From="5"
                                             Duration="0:0:0.5">
                                <DoubleAnimation.EasingFunction>
                                    <ElasticEase EasingMode="EaseOut"
                                                 Oscillations="2"
                                                 Springiness="1" />
                                </DoubleAnimation.EasingFunction>
                            </DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </Border>
</Grid>

This giving that immerse feeling "something is wrong". I am satisfied until a better answer appears.

like image 57
Sinatr Avatar answered Nov 12 '22 08:11

Sinatr


Here is the animation you describe. I have used a Viewport3D with a Viewport2DVisual3D to host the controls.

3DShake

You could use this to build you own reusable custom shake control.

It is not possible to replicate this exact animation using simple 2D RenderTransforms.

<Grid>
    <Viewport3D>
        <Viewport3D.Camera>
            <PerspectiveCamera Position="0, 0, 4"/>
        </Viewport3D.Camera>
        <Viewport2DVisual3D x:Name="DVisual3D">
            <Viewport2DVisual3D.Transform>
                <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                        <AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
                    </RotateTransform3D.Rotation>
                </RotateTransform3D>
            </Viewport2DVisual3D.Transform>
            <Viewport2DVisual3D.Geometry>
                <MeshGeometry3D Positions="-1,1,0 -1,-1,0 1,-1,0 1,1,0"
                        TextureCoordinates="0,0 0,1 1,1 1,0" TriangleIndices="0 1 2 0 2 3"/>
            </Viewport2DVisual3D.Geometry>
            <Viewport2DVisual3D.Visual>
                <Border x:Name="border"
                        Width="200"
                        Height="200"
                        BorderBrush="Black"
                        BorderThickness="1"
                        CornerRadius="4"
                        Background="LightBlue">
                    <Border.Effect>
                        <DropShadowEffect BlurRadius="20" />
                    </Border.Effect>
                    <Button VerticalAlignment="Bottom"
                            HorizontalAlignment="Center"
                            Margin="0,0,0,10"
                            Padding="5"
                            Content="Click">
                        <Button.Triggers>
                            <EventTrigger RoutedEvent="Button.Click">
                                <BeginStoryboard>
                                    <Storyboard FillBehavior="Stop">
                                        <DoubleAnimation Storyboard.TargetName="DVisual3D"
                                        Storyboard.TargetProperty="Transform.(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"
                                        To="10" Duration="0:0:0.07"/>
                                        <DoubleAnimation Storyboard.TargetName="DVisual3D"
                                        Storyboard.TargetProperty="Transform.(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"
                                        To="-10"
                                        BeginTime="0:0:0.07"
                                        Duration="0:0:0.14" />
                                        <DoubleAnimation Storyboard.TargetName="DVisual3D"
                                        Storyboard.TargetProperty="Transform.(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"
                                        To="10"
                                        BeginTime="0:0:0.21"
                                        Duration="0:0:0.14" />
                                        <DoubleAnimation Storyboard.TargetName="DVisual3D"


                    Storyboard.TargetProperty="Transform.(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"
                                    BeginTime="0:0:0.35"
                                    Duration="0:0:0.07" />
                            </Storyboard>
                        </BeginStoryboard>
                        </EventTrigger>
                        </Button.Triggers>
                </Button>
            </Border>
        </Viewport2DVisual3D.Visual>
        <Viewport2DVisual3D.Material>
            <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
        </Viewport2DVisual3D.Material>
    </Viewport2DVisual3D>
    <ModelVisual3D>
        <ModelVisual3D.Content>
            <DirectionalLight Color="#FFFFFFFF" Direction="0,0,-1"/>
        </ModelVisual3D.Content>
    </ModelVisual3D>
</Viewport3D>

like image 36
Glen Thomas Avatar answered Nov 12 '22 06:11

Glen Thomas