WPF 3D穿梭效果,用WPF也湊湊熱鬧


CSS 效果博客地址:

3D 穿梭效果?使用 CSS 輕松搞定 - ChokCoco - 博客園 (cnblogs.com)

UWP效果博客地址

3D 穿梭效果?使用 UWP 也能搞定 - dino.c - 博客園 (cnblogs.com)

大佬們真實登峰造極啊。

真是能學到很多東西啊。

 

我也就湊湊熱鬧,用WPF來試試,效果不算太好,勉強過得去吧。

 

 

相對CSS和UWP,老牌的WPF對於3D效果的操作是相對繁瑣的。 要首先做出3D模型,接着旋轉XY軸,其次調整Z軸拉伸,最后一步調整FOV。 穿梭效果要靠這Z軸拉伸的數字決定,圖中是10-20。

當然最難的是動畫的首尾銜接。

我們來一步一步的做。

 

制作3D模型

這一塊可以直接用不用2D控件其實沒啥可以研究,所以就直接是3D模型,讓圖片以貼圖的形式存在。

至於3D模型制作,總結一點就是由左到右開始。

1.Positions

3D模型是三角組成,所以描述一個物體的樣子時候,盡可能畫三角形。每個點就是頂點,如果存在相同的頂點,選擇一個就行。

描述頂點的時候是XYZ,當你正面看物體,物體的Z軸是指向你的方向為正方向。Y軸是向上為正,X軸是向右為正。

這里值得注意的是,為了方便 ,建議使用左  左下 右下 右上的順序去定義點。 

 

這個模型的頂點定義就是 P1(x,y,z), P2(x,y,z) ,P3(x,y,z) ,P4(x,y,z)

 

2.TriangleIndices

這個就是 描述 這些頂點是如何組成三角形。當我們認為一個面是正面時,要記得逆時針定義頂點集合下標。頂點集合就是Positions,內容就是你輸入的坐標點,下標由0開始。

背面為順時針。

 

3.TextureCoordinates

這個是材質的定位順序,這個比較2D坐標系,和其他的不同。也就是左上角為0,0 右下角為1,1,也就是普通的屏幕坐標系

 

做好模型,要做四個哦。

 

 

 

 

 

旋轉3d模型

這個就比較有意思了,上面模型做好了四個,我們要組成四個面,也就是旋轉Y軸,旋轉X軸,但是方向是不一樣的。旋轉我們使用Transform就可以了。

 看起來還行。

我們來做四個圖片並試試。

方便調試,我們帶着進度條。

資源

  <MeshGeometry3D x:Key="Rect3D_O">
            <MeshGeometry3D.Positions>
                -50,  50, 0,
              -50, -50, 0,
               50, -50, 0,
               50,  50, 0
            </MeshGeometry3D.Positions>
            <MeshGeometry3D.TriangleIndices>
                0 1 2 2 3 0
            </MeshGeometry3D.TriangleIndices>
            <MeshGeometry3D.TextureCoordinates>
                0,0 0,1 1,1 1,0
            </MeshGeometry3D.TextureCoordinates>
            <MeshGeometry3D.Normals>
                0,0,1,
                0,0,1,
                0,0,1, 
                0,0,1
            </MeshGeometry3D.Normals>
        </MeshGeometry3D>
        <DiffuseMaterial  x:Key="Img">
            <DiffuseMaterial.Brush>
                <ImageBrush ImageSource="start.jpg" />
            </DiffuseMaterial.Brush>
        </DiffuseMaterial>

 

 <Viewport3D  x:Name="View3D_2"    >
            <Viewport3D.Camera>
                <PerspectiveCamera   FieldOfView="{Binding ElementName=FOV, Path=Value}" Position="0,0,100" LookDirection="0,0,-1"/>
            </Viewport3D.Camera>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <AmbientLight Color="White"/>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Left_Top_Z, Path=Value}" Axis="0 1 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Left_Top_Z, Path=Value}" Axis="1 0 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Right_Bottom_Z, Path=Value}" Axis="0 1 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Right_Bottom_Z, Path=Value}" Axis="1 0 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                    </Model3DGroup>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>
      
        <Slider   Grid.Row="1" x:Name="Left_Top_Z" Minimum="-90" Value="12"  Maximum="90" ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>
        <Slider   Grid.Row="2" x:Name="Right_Bottom_Z" Minimum="-90"  Value="-12" Maximum="0"  ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>
        <Slider   Grid.Row="3" x:Name="ScaleZ_2" Background="Red" Minimum="10"  Maximum="100"  ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}">
            <Slider.Style >
                <Style TargetType="Slider">
                    <Style.Triggers>
                        <Trigger Property="Tag" Value="1">
                            <Trigger.EnterActions>
                                <BeginStoryboard >
                                    <Storyboard>
                                        <DoubleAnimation  RepeatBehavior="Forever"  Storyboard.TargetProperty="Value"   From="11" To="20" BeginTime="0:0:0"   Duration="0:0:10" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Slider.Style>
        </Slider>
        <Slider   Grid.Row="4" x:Name="FOV" Minimum="0"  Maximum="180" Value="176" ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>

 

運行,看看

 

看起來,有點味道了。

剩下就是調試動畫了。

我們想要首尾銜接的動畫,實際上就是要兩段動畫看不出首尾的區別。參考大佬們的基本思路,依靠透明度,延遲播放讓首尾看不出區別。

 

 

也就是說要

 

 

 

 

 

 

這里呢,我們純用XAML來實現這個方案。

首先要解決定時問題,首先頁面加載時,我們通過動畫修改某個對象的某個值 ,這個對象上存在一個觸發器,監控這個對象並開始定時,之后播放動畫。

修改值,我們要用ObjectAnimationUsingKeyFrames動畫。

觸發器,數值觸發器,因為可以綁定。

整個過程中,最重要的就是時間線,兩組動畫再何時出現,何時隱藏。

 

最終代碼

    <Window.Resources>
        <Storyboard  RepeatBehavior="Forever"  Storyboard.TargetName="ScaleZ_2"  Duration="0:0:10"  x:Key="sb" >
            <DoubleAnimation Storyboard.TargetName="ScaleZ_2" Storyboard.TargetProperty="Value"  From="11" To="20"     BeginTime="0:0:0"  Duration="0:0:10" />
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="View3D_2"   BeginTime="0:0:0" >
                <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
                <LinearDoubleKeyFrame KeyTime="0:0:6" Value="1"/>
                <LinearDoubleKeyFrame KeyTime="0:0:10" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>                                                                                                          
        <MeshGeometry3D x:Key="Rect3D_O">
            <MeshGeometry3D.Positions>
                -50,  50, 0,
              -50, -50, 0,
               50, -50, 0,
               50,  50, 0
            </MeshGeometry3D.Positions>
            <MeshGeometry3D.TriangleIndices>
                0 1 2 2 3 0
            </MeshGeometry3D.TriangleIndices>
            <MeshGeometry3D.TextureCoordinates>
                0,0 0,1 1,1 1,0
            </MeshGeometry3D.TextureCoordinates>
            <MeshGeometry3D.Normals>
                0,0,1,
                0,0,1,
                0,0,1, 
                0,0,1
            </MeshGeometry3D.Normals>
        </MeshGeometry3D>
        <DiffuseMaterial  x:Key="Img">
            <DiffuseMaterial.Brush>
                <ImageBrush ImageSource="start.jpg" />
            </DiffuseMaterial.Brush>
        </DiffuseMaterial>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded" SourceName="ScaleZ">
            <BeginStoryboard>
                <Storyboard Storyboard.TargetName="ScaleZ" Storyboard.TargetProperty="Tag"     Duration="0:0:5.1" >
                    <ObjectAnimationUsingKeyFrames>
                        <DiscreteObjectKeyFrame KeyTime="0:0:5" >
                            <DiscreteObjectKeyFrame.Value>
                                1
                            </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
            <BeginStoryboard Storyboard="{StaticResource sb}"/>
        </EventTrigger>
    </Window.Triggers>
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition  Height="auto"/>
            <RowDefinition  Height="auto"/>
            <RowDefinition  Height="auto"/>
            <RowDefinition  Height="auto"/>
            <RowDefinition  Height="auto"/>
            <RowDefinition  Height="auto"/>
        </Grid.RowDefinitions>
        <Viewport3D x:Name="View3D_1"    >
            <Viewport3D.Style>
                <Style TargetType="Viewport3D" >
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=ScaleZ,Path=Value}" Value="1">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard >
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames  RepeatBehavior="Forever" Storyboard.TargetProperty="Opacity"  BeginTime="0:0:0"  Duration="0:0:10">
                                            <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                                            <LinearDoubleKeyFrame KeyTime="0:0:5" Value="1"/>
                                            <LinearDoubleKeyFrame KeyTime="0:0:8" Value="1"/>
                                            <LinearDoubleKeyFrame KeyTime="0:0:10" Value="0"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Viewport3D.Style>
            <Viewport3D.Camera>
                <PerspectiveCamera   FieldOfView="{Binding ElementName=FOV, Path=Value}" Position="0,0,100" LookDirection="0,0,-1"/>
            </Viewport3D.Camera>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <AmbientLight Color="White"/>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Left_Top_Z, Path=Value}" Axis="0 1 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Left_Top_Z, Path=Value}" Axis="1 0 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Right_Bottom_Z, Path=Value}" Axis="0 1 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Right_Bottom_Z, Path=Value}" Axis="1 0 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                    </Model3DGroup>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>
        <Viewport3D  x:Name="View3D_2"    >
            <Viewport3D.Camera>
                <PerspectiveCamera   FieldOfView="{Binding ElementName=FOV, Path=Value}" Position="0,0,100" LookDirection="0,0,-1"/>
            </Viewport3D.Camera>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <AmbientLight Color="White"/>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Left_Top_Z, Path=Value}" Axis="0 1 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Left_Top_Z, Path=Value}" Axis="1 0 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Right_Bottom_Z, Path=Value}" Axis="0 1 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                        <GeometryModel3D   Geometry="{StaticResource Rect3D_O}"  Material="{StaticResource Img}" BackMaterial="{StaticResource Img}" >
                            <GeometryModel3D.Transform>
                                <Transform3DGroup>
                                    <RotateTransform3D CenterX="0" CenterY="1" CenterZ="0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="{Binding ElementName=Right_Bottom_Z, Path=Value}" Axis="1 0 0"/>
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <ScaleTransform3D ScaleZ="{Binding  ElementName=ScaleZ_2, Path=Value}"/>
                                </Transform3DGroup>
                            </GeometryModel3D.Transform>
                        </GeometryModel3D>
                    </Model3DGroup>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>
      
        <Slider   Grid.Row="1" x:Name="Left_Top_Z" Minimum="-90" Value="12"  Maximum="90" ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>
        <Slider   Grid.Row="2" x:Name="Right_Bottom_Z" Minimum="-90"  Value="-12" Maximum="0"  ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>
        <Slider   Grid.Row="3" x:Name="ScaleZ" Background="Red" Minimum="10"  Maximum="100"  ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}">
            <Slider.Style >
                <Style TargetType="Slider">
                    <Style.Triggers>
                        <Trigger Property="Tag" Value="1">
                            <Trigger.EnterActions>
                                <BeginStoryboard >
                                    <Storyboard>
                                        <DoubleAnimation  RepeatBehavior="Forever"  Storyboard.TargetProperty="Value"   From="11" To="20" BeginTime="0:0:0"   Duration="0:0:10" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Slider.Style>
        </Slider>
        <Slider   Grid.Row="4" x:Name="FOV" Minimum="0"  Maximum="180" Value="176" ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>
        <Slider   Grid.Row="5" x:Name="ScaleZ_2" Background="Black" Minimum="10"  Maximum="100"  ToolTip="{Binding  RelativeSource={RelativeSource Mode=Self}, Path=Value}"/>
        <StackPanel    Grid.Row="6" Orientation="Vertical">
            <TextBlock>
                <Run Text=" View3D_1 透明度"/>
                <Run Text="{Binding ElementName=View3D_1, Path=Opacity}"/>
                <Run Text=" View3D_1 value"/>
                <Run Text="{Binding ElementName=ScaleZ, Path=Value}"/>
                <Run Text=" Tag value"/>
                <Run Text="{Binding ElementName=ScaleZ, Path=Tag}"/>
                <Run Text=" Zindex value"/>
                <Run Text="{Binding ElementName=View3D_1, Path=(Panel.ZIndex)}"/>
            </TextBlock>
            <TextBlock>
                <Run Text=" View3D_2 透明度"/>
                <Run Text="{Binding ElementName=View3D_2, Path=Opacity}"/>
                <Run Text=" View3D_2 value"/>
                <Run Text="{Binding ElementName=ScaleZ_2, Path=Value}"/>
                <Run Text=" Zindex value"/>
                <Run Text="{Binding ElementName=View3D_2, Path=(Panel.ZIndex)}"/>
            </TextBlock>

        </StackPanel>
    </Grid>

 

這樣呢,我們就不用任何C#代碼來完成這個效果了。

 

 必須承認,在開頭0秒時做的不是很好,略有重影,所以還有很多地方需要學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM