標籤:
原文: wpf做的3d滑動gallery
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
wpf做的3d滑動gallery