【转】Silverlight用代码实现对任意控件向4个方向进行3D旋转
用了一天来写代码并测试,感觉还算可以,写代码时用了几种Timer来尝试控制动画,包括使用Thread,发现还是用storyboard来做Timer比较合适,没有过多的限制和线程外控件等问题,所以类中的动画主要用了两个storyboard来做Timer,分别控控制一进一出,实现动画则用PlaneProjection类来控制。3D旋转的主要实现方法是对PlaneProjection类的LocalOffsetZ和GlobalOffsetZ属性值进行正确的设置,左右旋转时LocalOffsetZ设置为控件的Widh/2,上下旋转则为Height/2,GlobalOffsetZ设置为相应的负值,也就是GlobalOffsetZ=-LocalOffsetZ,如果不写这句,控件会被拉伸大一截,要加上这一句花了我好长时间在HELP看了老半天,其次就是RotationX和RotationY的角度设置问题,弄清楚后就基本可以写完成了。
下面是类代码,大家可以把类引用到工程里或者是编译成DLL引用,后面还写了一个基本的应用例子:
应用图例:
-----------------类代码(c3dplane.cs)------------------------------------------------
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 大家共同交流,共同进步 * QQ:16277488 * MAIL:fanxiaokaitp@163.com * * */using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;namespace c3dplane{ public enum enumDirection { Up, Down, Left, Right }; public class cShow3DPlane { public cShow3DPlane() { m_IsMoveOverIn = true; m_IsMoveOverOut = true; m_MoveSpeed = 2; sbTimeIn = new Storyboard(); sbTimeOut = new Storyboard(); SetTime(10, 10); sbTimeIn.Completed += new EventHandler(sbTimeIn_Completed); sbTimeOut.Completed += new EventHandler(sbTimeOut_Completed); } private int m_TimeSpeed1, m_TimeSpeed2,m_MoveSpeed,m_PlaneSpeed,m_InEnd,m_OutEnd; private double m_InLocalZ,m_OutLocalZ; private PlaneProjection m_pInPlane,m_pOutPlane; private Storyboard sbTimeIn, sbTimeOut; private enumDirection m_Direction; private bool m_IsMoveOverIn,m_IsMoveOverOut; //根据方向初始化两个planeProjection的相关值 private void InitPlaneData() { m_pInPlane.RotationX = 0; m_pInPlane.RotationY = 0; m_pInPlane.RotationZ = 0; m_pInPlane.CenterOfRotationX = 0.5; m_pInPlane.CenterOfRotationY = 0.5; m_pInPlane.CenterOfRotationZ = 0; m_pOutPlane.RotationX = 0; m_pOutPlane.RotationY = 0; m_pOutPlane.RotationZ = 0; m_pOutPlane.CenterOfRotationX = 0.5; m_pOutPlane.CenterOfRotationY = 0.5; m_pOutPlane.CenterOfRotationZ = 0; m_pOutPlane.LocalOffsetZ = m_OutLocalZ; m_pOutPlane.GlobalOffsetZ = -m_OutLocalZ; m_pInPlane.LocalOffsetZ = m_InLocalZ; m_pInPlane.GlobalOffsetZ = -m_InLocalZ; switch (m_Direction) { case enumDirection.Up: m_pInPlane.RotationX = -90; m_InEnd = 0; m_pOutPlane.RotationX = 0; m_OutEnd = 90; m_PlaneSpeed = m_MoveSpeed; break; case enumDirection.Down: m_pInPlane.RotationX = 90; m_InEnd = 0; m_pOutPlane.RotationX = 0; m_OutEnd = -90; m_PlaneSpeed = -m_MoveSpeed; break; case enumDirection.Left: m_pInPlane.RotationY = 90; m_InEnd = 0; m_pOutPlane.RotationY = 0; m_OutEnd = -90; m_PlaneSpeed = -m_MoveSpeed; break; case enumDirection.Right: m_pInPlane.RotationY = -90; m_InEnd = 0; m_pOutPlane.RotationY = 0; m_OutEnd = 90; m_PlaneSpeed = m_MoveSpeed; break; } } public void Begin() { m_IsMoveOverIn = false; m_IsMoveOverOut = false; sbTimeIn.Begin(); sbTimeOut.Begin(); } //设置进入和离开对象 public void SetInOutPlane(Grid gridIn, Grid gridOut, enumDirection eDirection) { m_pInPlane = new PlaneProjection(); m_pOutPlane = new PlaneProjection(); gridIn.Projection = m_pInPlane; gridOut.Projection = m_pOutPlane; if (eDirection == enumDirection.Left || eDirection == enumDirection.Right) { m_InLocalZ = gridIn.ActualWidth / 2; m_OutLocalZ = gridOut.ActualWidth / 2; } else { m_InLocalZ = gridIn.ActualHeight / 2; m_OutLocalZ = gridOut.ActualHeight / 2; } m_Direction = eDirection; InitPlaneData(); } //重载 public void SetInOutPlane(Control controlIn, Control controlOut, enumDirection eDirection) { m_pInPlane = new PlaneProjection(); m_pOutPlane = new PlaneProjection(); controlIn.Projection = m_pInPlane; controlOut.Projection = m_pOutPlane; if (eDirection == enumDirection.Left || eDirection == enumDirection.Right) { m_InLocalZ = controlIn.ActualWidth / 2; m_OutLocalZ = controlOut.ActualWidth / 2; } else { m_InLocalZ = controlIn.ActualHeight / 2; m_OutLocalZ = controlOut.ActualHeight / 2; } m_Direction = eDirection; InitPlaneData(); } public bool MoveOver() { if (!m_IsMoveOverIn || !m_IsMoveOverOut) return false; else return true; } //设置进入和离开动画的速度 public void SetTime(int timeSpeed1, int timeSpeed2) { m_TimeSpeed1 = timeSpeed1; m_TimeSpeed2 = timeSpeed2; sbTimeIn.Duration = new Duration(TimeSpan.FromMilliseconds(m_TimeSpeed1)); sbTimeOut.Duration = new Duration(TimeSpan.FromMilliseconds(m_TimeSpeed2)); } //离开对象的动画 void sbTimeOut_Completed(object sender, EventArgs e) { //throw new NotImplementedException(); if (m_Direction == enumDirection.Left || m_Direction == enumDirection.Right) { m_pOutPlane.RotationY += m_PlaneSpeed; if (m_pOutPlane.RotationY == m_OutEnd) m_IsMoveOverOut = true; } if (m_Direction == enumDirection.Up || m_Direction == enumDirection.Down) { m_pOutPlane.RotationX += m_PlaneSpeed; if (m_pOutPlane.RotationX == m_OutEnd) m_IsMoveOverOut = true; } if (!m_IsMoveOverOut) sbTimeOut.Begin(); else { m_pOutPlane.LocalOffsetZ = 0; m_pOutPlane.GlobalOffsetZ = 0; } } //进入对象的动画 void sbTimeIn_Completed(object sender, EventArgs e) { //throw new NotImplementedException(); if (m_Direction == enumDirection.Left || m_Direction == enumDirection.Right) { m_pInPlane.RotationY += m_PlaneSpeed; if (m_pInPlane.RotationY == m_InEnd) m_IsMoveOverIn = true; } if (m_Direction == enumDirection.Up || m_Direction == enumDirection.Down) { m_pInPlane.RotationX += m_PlaneSpeed; if (m_pInPlane.RotationX == m_InEnd) m_IsMoveOverIn = true; } if (!m_IsMoveOverIn) sbTimeIn.Begin(); else { m_pInPlane.LocalOffsetZ = 0; m_pInPlane.GlobalOffsetZ = 0; } } }}
下面是应用例子:
-----------------(MainPage.xaml)------------------------------------------------
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<UserControl x:Class="_3dPlaneTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="480" d:DesignWidth="640"> <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition ></RowDefinition> <RowDefinition ></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Grid Grid.Row="0" Grid.Column="0"> <Button x:Name="btnUp" Content="上" VerticalAlignment="Top" HorizontalAlignment="Center" Width="200" Margin="20" Click="btnUp_Click"></Button> <Button x:Name="btnDown" Content="下" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="200" Margin="20" Click="btnDown_Click"></Button> <Button x:Name="btnLeft" Content="左" VerticalAlignment="Center" HorizontalAlignment="Left" Height="200" Margin="20" Click="btnLeft_Click"></Button> <Button x:Name="btnRight" Content="右" VerticalAlignment="Center" HorizontalAlignment="Right" Height="200" Margin="20" Click="btnRight_Click"></Button> <Grid x:Name="gridUp" Background="Red" Width="200" Height="100"> <TextBlock Text="这是上喔" Foreground="White" VerticalAlignment="Top" HorizontalAlignment="Center"/> </Grid> <Grid x:Name="gridDown" Background="Green" Width="200" Height="100"> <TextBlock Text="这是下喔" Foreground="White" VerticalAlignment="Bottom" HorizontalAlignment="Center"/> </Grid> <Grid x:Name="gridLeft" Background="Blue" Width="200" Height="100"> <TextBlock Text="这是左喔" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Left"/> </Grid> <Grid x:Name="gridRight" Background="Cornsilk" Width="200" Height="100"> <TextBlock Text="这是右喔" Foreground="Red" VerticalAlignment="Center" HorizontalAlignment="Right"/> </Grid> </Grid> <Grid Grid.Row="0" Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition ></RowDefinition> <RowDefinition ></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Button x:Name="btnTest1" Content="QQ:16277488,返回了" Width="220" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnTest1_Click"></Button> <Button x:Name="btnTest2" Content="这是测试控件旋转" Width="220" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnTest2_Click"></Button> <Button x:Name="btnTest3" Content="mail:fanxiaokaitp@163.com,返回了" Grid.Row="1" Width="220" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnTest3_Click"></Button> <Button x:Name="btnTest4" Content="这也是测试控件旋转" Grid.Row="1" Width="220" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnTest4_Click"></Button> </Grid> </Grid></UserControl>
-----------------(MainPage.xaml.cs)------------------------------------------------
using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using c3dplane;namespace _3dPlaneTest{ public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); PlaneProjection pp = new PlaneProjection(); pp.RotationY = 90; gridUp.Projection = pp; gridDown.Projection = pp; gridLeft.Projection = pp; gridCur = gridRight; } private cShow3DPlane c3d=new cShow3DPlane(); private Grid gridCur=new Grid(); private void btnUp_Click(object sender, RoutedEventArgs e) { if (gridCur ==gridUp ) { MessageBox.Show("现在已经是 上 了"); return; } if (c3d.MoveOver()) { c3d.SetInOutPlane(gridUp, gridCur, enumDirection.Up); gridCur = gridUp; c3d.Begin(); } } private void btnRight_Click(object sender, RoutedEventArgs e) { if (gridCur == gridRight) { MessageBox.Show("现在已经是 右 了"); return; } if (c3d.MoveOver()) { c3d.SetInOutPlane(gridRight, gridCur, enumDirection.Right); gridCur = gridRight; c3d.Begin(); } } private void btnLeft_Click(object sender, RoutedEventArgs e) { if (gridCur == gridLeft) { MessageBox.Show("现在已经是 左 了"); return; } if (c3d.MoveOver()) { c3d.SetInOutPlane(gridLeft, gridCur, enumDirection.Left); gridCur = gridLeft; c3d.Begin(); } } private void btnDown_Click(object sender, RoutedEventArgs e) { if (gridCur == gridDown) { MessageBox.Show("现在已经是 下 了"); return; } if (c3d.MoveOver()) { c3d.SetInOutPlane(gridDown, gridCur, enumDirection.Down); gridCur = gridDown; c3d.Begin(); } } private void btnTest2_Click(object sender, RoutedEventArgs e) { if (c3d.MoveOver()) { c3d.SetInOutPlane(btnTest1, btnTest2, enumDirection.Left); c3d.Begin(); } } private void btnTest1_Click(object sender, RoutedEventArgs e) { if (c3d.MoveOver()) { c3d.SetInOutPlane(btnTest2, btnTest1, enumDirection.Right); c3d.Begin(); } } private void btnTest3_Click(object sender, RoutedEventArgs e) { if (c3d.MoveOver()) { c3d.SetInOutPlane(btnTest4, btnTest3, enumDirection.Up); c3d.Begin(); } } private void btnTest4_Click(object sender, RoutedEventArgs e) { if (c3d.MoveOver()) { c3d.SetInOutPlane(btnTest3, btnTest4, enumDirection.Down); c3d.Begin(); } } }}
posted on 2010-10-24 21:34 dongxiaoling1029 阅读(719) 评论(1) 编辑 收藏 举报