我們在設計應用程序界面的時候,為了充分利用界面空間,住住需要靈活的界面布局方式, 比如可以在界面正面空間上定義一個Chart,背面空間上定義一個GridView,通過在Chart上鼠標 雙擊,控件180度旋轉後向用戶顯示出界面背面的GridView,通過在GridView上雙擊鼠標,控件 再一次平滑的180度旋轉向用戶顯示正面的Chart
這個例子就是使用Wpf模擬Apple OS 實現一個包含正反面元素的控件以Y軸為坐標前後180翻 轉的動畫效果,在這裡為方便示例,在正反面各以一個Image來表示,在每一面的Image上雙擊 鼠標,Image將180度反轉,顯示出背面的另一幅Image,下面是示例界面的縮略圖,有興趣的朋友 可以下載源碼:http://files.cnblogs.com/5460600/Rotation.rar
在這個示例中主要采用了GeometryModel3D和VisualBrush這兩個元素,GeometryModel3D用 來在3D場景中建立幾何模型,在Wpf中,任何復雜的3D模型最終都是由多個基本基元組成的,最 小的基本基元被定義為由三個頂點連線組成的三角形,幾何模型的每一面就是由多個這樣的三 角形的三維基元組合而成的。
在Wpf中通過MeshGeometry3D元素的Positions 屬性描述幾何模型的各個頂點, TriangleIndices 屬性描述以怎樣的順序來連接三個頂點以構成一個三角形的基本三維基元, 通過Positions 和TriangleIndices 的組合,我們就可以創建出復雜的幾何3D模型
定義了3D模型後,還需要對3D模型的每一面應用紋理,以使3D模型可見,Material元素被設 計用來描述3D模型的紋理,在本例中使用2D的VisualBrush填充3D模型的Material
在這個示例中實現的是正反面反轉,因此需要分別定義模型正反面的Material,在 GeometryModel3D元素中,由BackMaterial 屬性描述GeometryModel3D元素的背面Material,由 於背面Material位於照相機的另一面,是不可見的,必須使3D模型180度反轉後,才可使照相機 能投影到BackMaterial,於是這裡使用了RotateTransform3D元素180度反轉 GometryModel3D
GeomertyModel3D的定義
1 <GeometryModel3D>
2 <GeometryModel3D.Geometry>
3 <MeshGeometry3D TriangleIndices="0,1,2 2,3,0" TextureCoordinates="0,1 1,1 1,0 0,0"
4 Positions="-0.5,-0.5,0 0.5,-0.5,0 0.5,0.5,0 -0.5,0.5,0" />
5 </GeometryModel3D.Geometry>
6 <GeometryModel3D.Material>
7 <DiffuseMaterial>
8 <DiffuseMaterial.Brush>
9 <VisualBrush Visual="{Binding ElementName=frontHost}" />
10 </DiffuseMaterial.Brush>
11 </DiffuseMaterial>
12 </GeometryModel3D.Material>
13 <GeometryModel3D.BackMaterial>
14 <DiffuseMaterial>
15 <DiffuseMaterial.Brush>
16 <VisualBrush Visual="{Binding ElementName=backHost}">
17 <VisualBrush.RelativeTransform>
18 <ScaleTransform ScaleX="-1" CenterX="0.5" />
19 </VisualBrush.RelativeTransform>
20 </VisualBrush>
21 </DiffuseMaterial.Brush>
22 </DiffuseMaterial>
23 </GeometryModel3D.BackMaterial>
24 <GeometryModel3D.Transform>
25 <RotateTransform3D>
26 <RotateTransform3D.Rotation>
27 <AxisAngleRotation3D x:Name="rotate" Axis="0,1,0" Angle="0" />
28 </RotateTransform3D.Rotation>
29 </RotateTransform3D>
30 </GeometryModel3D.Transform>
31 </GeometryModel3D>
對GometryModel3D的前後反轉定義動畫,在Wpf中,Viewport2DVisual3D用來在3D場景中宿 主2D控件,因此只要把 Image宿主在Viewport2DVisual3D中,就可以在直接在3D場景中反轉 Image,但這不是一個好的方法,因為如果宿主一個比較復雜,比較"重"的2D控件到 Viewport2DVisual3D,並在3D場景中對它應用動畫,將使動畫的畫面出現停頓,因此一個好的 解決方法是用 VisualBrush將2D控件的實時圖像刷新到GometryModel3D的表面Material上,這 樣可使2D控件不用直接參於到3D場景中去,通過顯示隱藏相關元素一樣可以實現反轉界面的動 畫效果
Storyboard的定義
1 <Storyboard x:Key="FrontClick">
2 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Viewport3D"
3 Storyboard.TargetProperty="Visibility">
4 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
5 <DiscreteObjectKeyFrame KeyTime="0:0:1.1" Value="{x:Static Visibility.Hidden}" />
6 </ObjectAnimationUsingKeyFrames>
7 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backWrapper"
8 Storyboard.TargetProperty="Visibility">
9 <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Visible}"/>
10 </ObjectAnimationUsingKeyFrames>
11 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="frontWrapper"
12 Storyboard.TargetProperty="Visibility">
13 <DiscreteObjectKeyFrame KeyTime="0:0:0.05" Value="{x:Static Visibility.Hidden}" />
14 </ObjectAnimationUsingKeyFrames>
15 <DoubleAnimation To="0" Duration="0:0:0.05" Storyboard.TargetName="frontWrapper"
16 Storyboard.TargetProperty="Opacity" />
17 <DoubleAnimation BeginTime="0:0:1.05" Duration="0:0:0.05" To="1"
18 Storyboard.TargetName="backWrapper" Storyboard.TargetProperty="Opacity" />
19 <Point3DAnimation To="0,0,1.1" From="0,0,0.5" BeginTime="0:0:0.05" Duration="0:0:0.5"
20 AutoReverse="True" DecelerationRatio="0.3" Storyboard.TargetName="camera"
21 Storyboard.TargetProperty="(PerspectiveCamera.Position)" />
22 <DoubleAnimation From="0" To="180" AccelerationRatio="0.3" DecelerationRatio="0.3"
23 BeginTime="0:0:0.05" Duration="0:0:1" Storyboard.TargetName="rotate" Storyboard.TargetProperty="Angle" />
24 </Storyboard>
25 <Storyboard x:Key="BackClick" >
26 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Viewport3D"
27 Storyboard.TargetProperty="Visibility">
28 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
29 <DiscreteObjectKeyFrame KeyTime="0:0:1.1" Value="{x:Static Visibility.Hidden}" />
30 </ObjectAnimationUsingKeyFrames>
31 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="frontWrapper"
32 Storyboard.TargetProperty="Visibility">
33 <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Visible}"/>
34 </ObjectAnimationUsingKeyFrames>
35 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backWrapper"
36 Storyboard.TargetProperty="Visibility">
37 <DiscreteObjectKeyFrame KeyTime="0:0:0.05" Value="{x:Static Visibility.Hidden}" />
38 </ObjectAnimationUsingKeyFrames>
39 <DoubleAnimation To="0" Duration="0:0:0.05" Storyboard.TargetName="backWrapper"
40 Storyboard.TargetProperty="Opacity" />
41 <DoubleAnimation BeginTime="0:0:1.05" Duration="0:0:0.05"
42 Storyboard.TargetName="frontWrapper" Storyboard.TargetProperty="Opacity" />
43 <Point3DAnimation To="0,0,1.1" From="0,0,0.5" BeginTime="0:0:0.05"
44 Duration="0:0:0.5" AutoReverse="True" DecelerationRatio="0.3" Storyboard.TargetName="camera"
oryboard.TargetProperty="(PerspectiveCamera.Position)" />
45 <DoubleAnimation From="180" To="360" AccelerationRatio="0.3"
46 DecelerationRatio="0.3" BeginTime="0:0:0.05" Duration="0:0:1"
47 Storyboard.TargetName="rotate" Storyboard.TargetProperty="Angle" />
48 </Storyboard>