WPF 大數據加載過程中的等待效果——圓圈轉動
大家肯定遇到過或將要遇到加載大數據的時候,如果出現長時間的空白等待,一般人的概念會是:難道卡死了?
作為一個懂技術的挨踢技術,即使你明知道數據量太大正在加載,但是假如看不到任何動靜,自己覺得還是一種很不好的體驗。
之前做項目的時候有這方面的要求,我的前輩們早已給出了完美的解決方案。最近自己在努力學習,今天拿出來與大家一起分享,我想一定會有幫助的。看過之後大家會佩服我的前輩的,呵呵,好,廢話少說,下面開始。
因為怕自己班門弄斧,所以在網上先查了資料,確定很難找到這樣的實例才敢拿出來與大家見面。不過確實也找到了一個相似效果的案例,但那位高手用的全是前臺實現,而我的前輩是在後臺寫了一個類BusyDecorator,用起來更加方便。喜歡前臺xaml實現的可以去看一下那位高手的代碼:http://blog.csdn.net/qqamoon/article/details/7001693 他的代碼我沒做試驗,看他的那個實現效果跟我的是一樣的。
我的陋代碼又要上臺表現了,諸位扶好眼鏡框了哈~~
首先我們需要定義一些屬性用來保存位置,大小,角度,透明度之類:
/// <summary> /// 條的數量 /// </summary> int _elementCount; /// <summary> /// 圓的半徑 /// </summary> double _radious = 10; /// <summary> /// 執行動畫的DispatcherTimerView Code/// </summary> DispatcherTimer _animationTimer; /// <summary> /// 當前條的索引位置 /// </summary> int _currentElementIndex = 0; /// <summary> /// 需要變換的透明度個數 /// </summary> int _opacityCount; /// <summary>/// 透明度間的間隔 /// </summary> double _opacityInterval; /// <summary> /// 透明度 /// </summary> double _opacity; /// <summary> /// 最小透明度 /// </summary> double _minOpacity; /// <summary> /// 條的數組 /// </summary> object[] _elements; /// <summary> /// 畫布 /// </summary> private Canvas _canvas;
由於我們是定義在一個類BusyDecorator裏面,所以需要在構造函數裏定義最初的靜態畫布效果。然後利用計時器控制動畫的啟動與停止。
重點便是靜態畫布的設計與Timer_Tick事件的實現。
我的前輩給出的靜態畫布設計如下:
private void CreateElements(Canvas canvas, double Left, double Top) { _elementCount = 12; _opacity = 1; _minOpacity = 0.3; double surplusOpacity = _opacity - _minOpacity; _opacityCount = (int)(_elementCount * 0.5); _opacityInterval = surplusOpacity / _opacityCount; _elements = new object[_elementCount]; for (int i = 0; i < _elementCount; i++) { Rectangle rect = new Rectangle(); rect.Fill = new SolidColorBrush(Colors.Black); rect.Width = 5; rect.Height = 5; rect.RadiusX = 2; rect.RadiusY = 2; if (i < _opacityCount) { rect.Opacity = _opacity - i * _opacityInterval; } else { rect.Opacity = _minOpacity; } rect.SetValue(Canvas.LeftProperty, Left + _radious * Math.Cos(360 / _elementCount * i * Math.PI / 180)); rect.SetValue(Canvas.TopProperty, Top - 2.5 - _radious * Math.Sin(360 / _elementCount * i * Math.PI / 180)); rect.RenderTransform = new RotateTransform(360 - 360 / _elementCount * i, 0, 2.5); canvas.Children.Add(rect); _elements[i] = rect; } _currentElementIndex = 0; }View Code
接下來就是Timer_Tick事件了,一般人想不到這樣處理吧:
private void _animationTimer_Tick(object sender, EventArgs e) { try { _currentElementIndex--; _currentElementIndex = _currentElementIndex < 0 ? _elements.Length - 1 : _currentElementIndex; int opacitiedCount = 0; for (int i = _currentElementIndex; i < _currentElementIndex + _elementCount; i++) { int j = i > _elements.Length - 1 ? i - _elements.Length : i; if (opacitiedCount < _opacityCount) { ((Rectangle)_elements[j]).Opacity = _opacity - opacitiedCount * _opacityInterval; opacitiedCount++; } else { ((Rectangle)_elements[j]).Opacity = _minOpacity; } } } catch (Exception ex) { } }View Code
好了,重點結束後就是剩下的構造函數BusyDecorator了:
public BusyDecorator(Canvas canvas) { this._canvas = canvas; _animationTimer = new DispatcherTimer(); _animationTimer.Interval = TimeSpan.FromMilliseconds(40); _animationTimer.Tick += new EventHandler(_animationTimer_Tick); CreateElements(canvas, canvas.Width / 2, canvas.Height / 2); }View Code
註意:此構造函數由於用到了canvas.width和canvas.height,所以,前臺定義canvas時一定要設置其width和height屬性。
然後是啟動動畫與停止動畫事件:
public void StartDecorator() { _canvas.Visibility = Visibility.Visible; _animationTimer.Start(); } public void StopDecorator() { _canvas.Visibility = Visibility.Hidden; _animationTimer.Stop(); }View Code
好了,類BusyDecorator設計好了,下面做一個實例測試一下吧:
做一個前臺頁面:
<Window x:Class="testFlowDocument.zhuanquanFlash" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="zhuanquanFlash" Height="300" Width="300"> <Grid> <Canvas Name="canvas_bu" Width="200" Height="200" VerticalAlignment="Top" Background="LightBlue"> </Canvas> <Button Name="btn_start" Content="開始" Height="50" VerticalAlignment="Bottom" Click="Button_Click" /> </Grid> </Window>View Code
後臺代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace testFlowDocument { /// <summary> /// zhuanquanFlash.xaml 的交互邏輯 /// </summary> public partial class zhuanquanFlash : Window { public zhuanquanFlash() { InitializeComponent(); busy = new BusyDecorator(this.canvas_bu); } BusyDecorator busy; bool isstart = false; private void Button_Click(object sender, RoutedEventArgs e) { if (isstart == false) { busy.StartDecorator(); isstart = true; this.btn_start.Content = "停止"; } else { busy.StopDecorator(); isstart = false; this.btn_start.Content = "開始"; } } } }View Code
靜態效果圖:
PS:如何快速制作動態gif圖?像上邊鏈接地址裏的那樣的gif圖。不會photoshop,求推薦好使工具~~
本文地址:http://www.cnblogs.com/jying/p/3230391.html 轉載請寫明出處~~
ok,到此為止,謝謝大家捧場~~
個人小站歡迎來踩:駕校教練評價平臺 | 為愛豆砌照片墻
WPF 大數據加載過程中的等待效果——圓圈轉動