具有3D旋转效果的图片组的一种实现

       前段时间看到QQ群里面有朋友问一组图片的3D旋转效果怎么做,虽然之前看到过flash版本的这种效果,但是自己却也没有做过这种效果。于是,就想来练习练习,最终的效果是这样的:

 

 

其实,这个东西就是要利用椭圆的标准方程,然后,你通过一个dispatchertimer 每隔一段时间触发一次动作,使得里面的图片沿着椭圆的轨迹改变坐标点,另外可以再改变图片的大小和透明度,使得效果看起来更好点。

 

关于椭圆及其标准方程:

 

      

 

还有一个需要用到的椭圆的性质是,知道椭圆的两个半轴,根据角度求得在椭圆轨迹上的坐标点:

也就是椭圆的参数方程:

 

其中的角度是离心角:

 

 

具备了这些几何知识,接下来的应该很简单了,无非就是利用silverlight中的属性,变幻效果等等,使得每隔一定时间,让你的图片在如上图那样的椭圆轨迹上运动。好了,分析完毕,开始写代码:

首先,在xaml文件中如下写:

 

  < Canvas  x:Name ="MainCanvas"  Background ="Black" >

    
</ Canvas >

 

 

是不是很简单,因为这次把大多数的操作,包括图片的加载都放到隐藏代码中了,这里并没有鄙视xaml的意思,其实我很喜欢xaml声明式的代码,但是标记代码和后台的逻辑代码都是必不可少的,这也是silverlight和WPF的一大特色。只是,这次用到的逻辑比较多,在xmal中去做就不太合适。好了,接下来,看下代码隐藏文件中是怎么回事:

首先在MainPage控件类中定义这么些私有变量:

 

  private   double  _speed;                                                         // 图片移动速度
         private  List < double >  _angles;                                                 // 离心角角度集合
         private   const   double  _MAX_SPEED  =   0.009 ;                                       // 定义的最大速度值
         private  DispatcherTimer _disp;                                                    // 定时器
         private  List < ScaleTransform >  scaleTransforms  =   new  List < ScaleTransform > ();         // 缩放变换集合

 

 

然后,我们需要一个初始化的函数,包括加载图片啊,设置图片大小,初始离心角角度集合的初始化

 

ExpandedBlockStart.gif 代码
   public   void  InitContainer()
        {
            _angles 
=   new  List < double > ();
            _speed 
=  _MAX_SPEED;
            _disp 
=   new  DispatcherTimer();
            _disp.Interval 
=  TimeSpan.FromMilliseconds( 25 );                               // 每隔25毫秒,图片移动一次
            _disp.Tick  +=   new  EventHandler(_disp_Tick);
           
            
for  (var i  =   0 ; i  <   6 ; i ++ )
            {
                Canvas ca 
=   new  Canvas();
                BitmapImage bit
= new  BitmapImage( new  Uri( @" Images/ " + (i + 1 ) + " .jpg " ,UriKind.Relative));
                Image img
= new  Image();
                img.Width 
=   200 ;
                img.Height 
=   250 ;
                img.Source
= bit;
                ca.Width 
=   200 ;
                ca.Height 
=   250 ;
                
// ca.Background = new SolidColorBrush(Colors.Red);
                ca.Children.Add(img);
                _angles.Add ( (Math.PI 
*   2   /   6 *  i);
                ScaleTransform sc 
=   new  ScaleTransform();
                scaleTransforms.Add(sc);
                sc.ScaleX 
=   1 ;
                sc.ScaleY 
=   1 ;
                sc.CenterX 
=   100 ;
                sc.CenterY 
=   125 ;
                ca.RenderTransform 
=  sc;
                MainCanvas.Children.Add(ca);
            }
            _disp.Start();
        }

 

 

然后再写一个移动图片的函数,主要功能:根据离心角的角度通过椭圆参数方程计算出此刻图片位于椭圆轨迹上的坐标点,然后再进行图片缩放,透明度改变等效果

 

  public   void  SetMove()
        {
            
double  RadiusX  =   300 ;                                        // 设定椭圆的长半轴
             double  RadiusY  =   80 ;                                         // 设定椭圆的短半轴
             double  CenterX  =   550 ;                                         // 设定图片组的中心
             double  CenterY  =   220 ;                                         // 设定图片组的中心
            Canvas aCanvas;
            
for  ( int  i  =   0 ; i  <   6 ; i ++ )
            {
               aCanvas 
=  MainCanvas.Children[i]  as  Canvas;
               
double  NewX  =  Math.Cos(_angles[i])  *  RadiusX  +  CenterX;                          // 计算x坐标
                double  NewY  =  Math.Sin(_angles[i])  *  RadiusY  +  CenterY;                          // 计算y坐标
               aCanvas.SetValue(Canvas.LeftProperty, NewX);                                    // 对图片集合中的每张图片进行重新定位
               aCanvas.SetValue(Canvas.TopProperty, NewY);
               _angles[i] 
+=  _speed;                                                           // 根据速度改变离心角的角度
               aCanvas.SetValue(Canvas.ZIndexProperty, System.Convert.ToInt32(NewY));          // 设置图片的zIndex属性,防止位于底层的图片遮挡上层的图片
                double  opacity  =  Math.Sin(_angles[i])  +   1.5 ;                                    // 改变图片透明度,其实这里是改变画布透明度
               aCanvas.SetValue(Canvas.OpacityProperty, opacity);
               var curr 
=  scaleTransforms[i];
               var change 
=  NewY   /  (CenterY  +  RadiusY  -  curr.ScaleY);                         // 重新计算画布大小
               curr.ScaleX  =  change;                                     
               curr.ScaleY 
=  change;


            }
        
        }

 

最后,把SetMove()函数放到dispatchertimer的tick触发函数中,每隔25ms 调用,更新每张图片的位置和大小及其透明度

 

void  _disp_Tick( object  sender, EventArgs e)
        {
            SetMove();
        }

 

 

这样一个旋转图片组的效果就做好了 :)

 

总结:这次其实没有直接去控制图片的位置,而是把图片放到画布中,通过改变画布的位置而改变图片的位置,这样做的好处是,可复用性更强一些,以后不只是做图片,可以把文本,按钮,或者其它控件甚至视频放到其中,产生这样的效果。当然,更好的做法是自己把它封装成控件,以便以后更方便使用,另外,这个效果目前还是比较基础和粗糙的,还有很多地方可以改进,例如,可以加入鼠标的交互,当鼠标移到上面不同位置产生加速,减速,改变方向,改变椭圆中心等等~

转载于:https://www.cnblogs.com/vimsk/archive/2010/11/16/1878838.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值