隨着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; }
其實就是移動距離的變化算法實現的
該demo界面
全部代碼下載,本項目用vs2010編繹
http://files.cnblogs.com/easywebfactory/3d_Gallery.rar