本案例實現控制項雙面內容 (正面 Chart / 背面 GridView) 沿 Y 軸 180° 平滑翻轉,雙擊任一面即觸發翻轉顯示另一面,完美模擬 Apple OS 風格交互。

原始碼下載:Rotation.rar
使用 MeshGeometry3D 定義矩形:4 個頂點 (Positions) + 2 個三角形 (TriangleIndices="0,1,2 2,3,0") + 貼圖座標 (TextureCoordinates)。
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D TriangleIndices="0,1,2 2,3,0" TextureCoordinates="0,1 1,1 1,0 0,0"
Positions="-0.5,-0.5,0 0.5,-0.5,0 0.5,0.5,0 -0.5,0.5,0" />
</GeometryModel3D.Geometry>
<!-- 正面材質:綁定 frontHost 視覺樹 -->
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<VisualBrush Visual="{Binding ElementName=frontHost}" />
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<!-- 背面材質:綁定 backHost,ScaleX=-1 修正鏡像翻轉 -->
<GeometryModel3D.BackMaterial>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<VisualBrush Visual="{Binding ElementName=backHost}">
<VisualBrush.RelativeTransform>
<ScaleTransform ScaleX="-1" CenterX="0.5" />
</VisualBrush.RelativeTransform>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.BackMaterial>
<!-- 旋轉變換:動畫目標 -->
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="rotate" Axis="0,1,0" Angle="0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
Viewport2DVisual3D 可直接在 3D 場景承載互動式 2D 控制項,但若控制項複雜/「重」,動畫會卡頓。VisualBrush 僅捕獲視覺樹的即時渲染畫面作為貼圖,2D 控制項留在 2D 視覺樹中,3D 場景僅顯示其「截圖」,大幅降低動畫渲染負擔。
兩組 Storyboard (FrontClick/BackClick) 協同控制:
ObjectAnimationUsingKeyFrames 控制 Viewport3D、正面/背面容器 (frontWrapper/backWrapper) 的 Visibility,配合 Opacity 淡入淡出;Point3DAnimation 讓攝影機前後移動 (Z: 0.5 → 1.1 → 0.5) 增強立體感;DoubleAnimation 驅動 rotate.Angle: 0→180 或 180→360,AccelerationRatio=DecelerationRatio=0.3 實現平滑緩動。
<Storyboard x:Key="FrontClick">
<!-- Viewport3D 顯示/隱藏 -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Viewport3D" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
<DiscreteObjectKeyFrame KeyTime="0:0:1.1" Value="{x:Static Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
<!-- 正面容器淡出 -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="frontWrapper" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0.05" Value="{x:Static Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="frontWrapper" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.05" />
<!-- 背面容器淡入 -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backWrapper" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="backWrapper" Storyboard.TargetProperty="Opacity" BeginTime="0:0:1.05" To="1" Duration="0:0:0.05" />
<!-- 攝影機動畫 -->
<Point3DAnimation Storyboard.TargetName="camera" Storyboard.TargetProperty="(PerspectiveCamera.Position)"
From="0,0,0.5" To="0,0,1.1" BeginTime="0:0:0.05" Duration="0:0:0.5" AutoReverse="True" DecelerationRatio="0.3" />
<!-- 核心旋轉 -->
<DoubleAnimation Storyboard.TargetName="rotate" Storyboard.TargetProperty="Angle"
From="0" To="180" BeginTime="0:0:0.05" Duration="0:0:1" AccelerationRatio="0.3" DecelerationRatio="0.3" />
</Storyboard>
雙擊事件分別觸發對應 Storyboard,實現雙向 180° 翻轉循環。