SilverLight用代码实现对任意控件向4个方向进行3D旋转的类

转载地址:http://www.cnblogs.com/fanxiaokaitp/archive/2010/05/21/1740532.html

最近在做一个SilverLight项目,两个屏幕面板切换(比如从一个Grid切换到另一个Grid)时需要用到3D旋转的方式,部分文字、按钮切换时也要用到3D旋转的方式,刚开始看到这样需求的时候,自然而然的想到了用storyboard来做动画,于是开始动起手来画,研究了一阵3D旋转的方式,画出了第一个面板的3D左切换方式,但随之而来的问题让人头疼,不光有右、上、下的不同甚至随机的切换方式,还有不同控件、动画速度等需要控制,用动画的方式做出来似乎程序的伸缩很小,也不是太方便,于是有了写一个实现这样功能的类来用的想法,日后如果碰到需要这类功能的需要还可以重复使用。

  用了一天来写代码并测试,感觉还算可以,写代码时用了几种Timer来尝试控制动画,包括使用Thread,发现还是用storyboard来做Timer比较合适,没有过多的限制和线程外控件等问题,所以类中的动画主要用了两个storyboard来做Timer,分别控控制一进一出,实现动画则用PlaneProjection类来控制。3D旋转的主要实现方法是对PlaneProjection类的LocalOffsetZ和GlobalOffsetZ属性值进行正确的设置,左右旋转时LocalOffsetZ设置为控件的Widh/2,上下旋转则为Height/2,GlobalOffsetZ设置为相应的负值,也就是GlobalOffsetZ=-LocalOffsetZ,如果不写这句,控件会被拉伸大一截,要加上这一句花了我好长时间在HELP看了老半天,其次就是RotationX和RotationY的角度设置问题,弄清楚后就基本可以写完成了。

      找到了个可以上传XAP在线演示的地方,大家可以先看看在线演示,地址: http://www.bbniu.com/matrix/ShowApplication.aspx?id=122

  下面是类代码,大家可以把类引用到工程里或者是编译成DLL引用,后面还写了一个基本的应用例子:

应用图例:

2010052100505141.jpg      2010052100510776.jpg    2010052100511741.jpg

-----------------类代码(c3dplane.cs)------------------------------------------------

 

 

ContractedBlock.gif ExpandedBlockStart.gif c3dplane.cs代码
 
   
/*
* 大家共同交流,共同进步
* 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)------------------------------------------------

 

ContractedBlock.gif ExpandedBlockStart.gif MainPage.xaml代码
 
   
< 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)------------------------------------------------

 

ContractedBlock.gif ExpandedBlockStart.gif 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();
}
}


}
}

 

 

 

 

以上是类和应用代码。

转载于:https://www.cnblogs.com/jiewei915/archive/2010/07/14/1777393.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值