wpf做的3d滑動gallery


隨着iphone\ipad的流行及熱捧,現在做移動產品不管是什么平台的,領導總想做成像ios系統的樣子。自從微軟發布了window8預覽版之后,領導就想着把公司的移動產品移殖到window8上去了。公司的移動產品的主界面是做成3d gallery的立體畫冊效果的,如下圖:

window8是不帶這樣的控件的,究竟有沒有實現如此效果的控件我就不清楚了,我認為是沒有的,因為我在vs上找不到,也不符合window8風格,我找遍了互聯網也沒有找到這樣效果的第三方控件,所以只好自已去開發實現了。雖然我認為做這樣的效果放上window8上比較搞笑,但領導想要如此就沒辦法了,領導說怎么做就怎么做!

window8的metro風格開發需要在window8平台上開發,雖然開發框架並不是wpf ,不過也是差不多的,就是xaml加c#(這個效果其實用silverlight來實現會更簡單一些,因為它有將2d視圖直接模擬3D動畫的類), window8只在虛擬機上裝了,所以就用wpf來研究了。

在互聯網只找到一種模擬環繞滾動效果的開源代碼,圖片及滾動效果都有了(只是2D圖效果),就拿它來開刀改造成我們要的效果。需要增加四個功能效果,一是讓它支持用鼠標滑動控制,二是讓圖片有透視立體效果,三是當前圖滑動到左右時能且有動畫效果在正面與則面視角間轉換,四是為每張圖增加點擊觸發事件。

一、鼠標滑動控制功能

因為涉及到的功能比較復雜,具體同學們自已看源碼研究了,這里主要是把入口代碼告訴大家。只要實現控件的OnMouseMove事件去控制圖片的滑動:

        private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                IsPressed = true;
                tempi += 1;
                if (tempp.X > e.GetPosition(LayoutRoot).X)
                {
                    if (tempi > MOVE_DISTANCE)
                    {
                       //鼠標滑到一定距離后圖片自動滑動到下一張 
                        MoveRight();
                        tempi = 0;
                    }
                     _touch_move_distance += 1;

                }
                else if (tempp.X < e.GetPosition(LayoutRoot).X)
                {
                    if (tempi > MOVE_DISTANCE)
                    {
                         //鼠標滑到一定距離后圖片自動滑動到下一張 
                        MoveLeft();
                        tempi = 0;
                    }
                   _touch_move_distance -= 1;

                }
                tempp = e.GetPosition(LayoutRoot);

            }
            else if (e.LeftButton == MouseButtonState.Released)
            {
                IsPressed = false;
                tempi = 0;
                tempp = new Point(0, 0);
            }
            else
            {
                tempi = 0;
                tempp = new Point(0, 0);
            }
        }

二、讓圖片有透視立體效果,動畫效果在正面與則面視角間轉換

立體效果需要有控件或類支持才行,xaml提供了一種實現方法就是用Viewport3D類,首先自定義一個具有把2d圖轉3D的圖片view控件,用xaml實現,涉及的代碼較多這里不列出來了,只說一下轉換的動畫效果實現,以下只是其實一種

            GeometryModel3D current = this.contentView;
            var transform3DGroup = current.Transform as Transform3DGroup;
            var rotate = (transform3DGroup.Children[0] as RotateTransform3D).Rotation as AxisAngleRotation3D;
            AnimationVisualElement(rotate, 45);

AnimationVisualElement是自定義的實現動畫效果的方法,只實現在立體旋轉,其他如大小縮放也是需要的

        private void AnimationVisualElement(AxisAngleRotation3D rotate, double angel)
        {
            Duration duration = new Duration(TimeSpan.FromSeconds(.1));
            //對AxisAngleRotation3D的Angle屬性應用動畫
            DoubleAnimation animationAngel = new DoubleAnimation();
            animationAngel.To = angel;
            animationAngel.AccelerationRatio = 0.3;
            animationAngel.DecelerationRatio = 0.7;
            animationAngel.Duration = duration;
            rotate.BeginAnimation(AxisAngleRotation3D.AngleProperty, animationAngel);
        }

三、為每張圖增加點擊觸發事件

點擊事件在添加子圖片時添加進去

        public void AddImage(ImageSource bitmapImage)
        {
            Viewport3DControl image = new Viewport3DControl();
            image.SetImageSource(ref bitmapImage);
            image.Index = _images.Count;
            image.Width = ChildViewWidth;
            image.Height = ChildViewHeight;
            image.MouseDown += new MouseButtonEventHandler(image_MouseDown);
            LayoutRoot.Children.Add(image);
            posImage(image, _images.Count);
            _images.Add(image);
        }

        void image_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Viewport3DControl view = (Viewport3DControl)sender;
         // 用委托輸出觸發事件到主線程 ,需要注意的是,在引用此控件時必須實現此委托方法
            OnTouchDownEvent(view, view.Index);
        }
        public delegate void TouchDownHander(UIElement view, int index);
        public event TouchDownHander OnTouchDownEvent;

比較特別的是,此控件擁有滑動時會產生慣性滑動效果,實現此效果的關鍵代碼是這部分

        void _timer_Tick(object sender, EventArgs e)
        {
            //還原位置
            if (IsPressed == false && _touch_move_distance != 0)
            {
                //回彈
                _touch_move_distance += (-_touch_move_distance) * SPRINESS;
            }
            for (int i = 0; i < _images.Count; i++)
            {
                Viewport3DControl image = _images[i];
                posImage(image, i);
            }
            if (Math.Abs(_target - _current) < CRITICAL_POINT && IsPressed == false) return;
//慣性滑動效果
            _current += (_target - _current) * SPRINESS;
        }
其實就是移動距離的變化算法實現的
此控件實現在效果跟ios或android上的gallery控件的效果是一模一樣的。同學們學會制件此控件后,應該也就會對模擬自然物理動畫效果的實現有些了解了,首先控件本身是自帶計時器的,然后是需要相關效果的模擬效果數值算法。給同學們奉上全部源代碼及demo, 還有一個gallery的變種,效果更復雜一些的,這里就不解說它的實現原理了,同學們自已研究。 
gallery變種效果圖:

該demo界面

全部代碼下載,本項目用vs2010編繹

http://files.cnblogs.com/easywebfactory/3d_Gallery.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM