1. 程式人生 > >WPF 大數據加載過程中的等待效果——圓圈轉動

WPF 大數據加載過程中的等待效果——圓圈轉動

system end from collect 鏈接 handle inter summary 設計

原文:WPF 大數據加載過程中的等待效果——圓圈轉動

大家肯定遇到過或將要遇到加載大數據的時候,如果出現長時間的空白等待,一般人的概念會是:難道卡死了?

作為一個懂技術的挨踢技術,即使你明知道數據量太大正在加載,但是假如看不到任何動靜,自己覺得還是一種很不好的體驗。

之前做項目的時候有這方面的要求,我的前輩們早已給出了完美的解決方案。最近自己在努力學習,今天拿出來與大家一起分享,我想一定會有幫助的。看過之後大家會佩服我的前輩的,呵呵,好,廢話少說,下面開始。

因為怕自己班門弄斧,所以在網上先查了資料,確定很難找到這樣的實例才敢拿出來與大家見面。不過確實也找到了一個相似效果的案例,但那位高手用的全是前臺實現,而我的前輩是在後臺寫了一個類BusyDecorator,用起來更加方便。喜歡前臺xaml實現的可以去看一下那位高手的代碼:http://blog.csdn.net/qqamoon/article/details/7001693 他的代碼我沒做試驗,看他的那個實現效果跟我的是一樣的。

我的陋代碼又要上臺表現了,諸位扶好眼鏡框了哈~~

首先我們需要定義一些屬性用來保存位置,大小,角度,透明度之類:

技術分享圖片
        /// <summary>
        /// 條的數量
        /// </summary>
        int _elementCount;

        /// <summary>
        /// 圓的半徑
      /// </summary>
        double _radious = 10;

        /// <summary>
        /// 執行動畫的DispatcherTimer
        
/// </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;
View Code

由於我們是定義在一個類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 大數據加載過程中的等待效果——圓圈轉動