欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WPF实现转圈进度条效果

程序员文章站 2022-03-22 08:05:41
在设计界面时,有时会遇到进度条,本次讲解wpf如何设计自定义的绕圈进度条,直接上代码:    1、控件界面

在设计界面时,有时会遇到进度条,本次讲解wpf如何设计自定义的绕圈进度条,直接上代码:

 WPF实现转圈进度条效果

 1、控件界面

<usercontrol x:class="progressbarcontrol" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       mc:ignorable="d" d:designheight="200" d:designwidth="300"
       background="gray" loaded="progressbarcontrol_onloaded">

  <grid>
    <grid.resources>
      <style targettype="ellipse">
        <setter property="height" value="{binding eclipsesize}"></setter>
        <setter property="width" value="{binding eclipsesize}"></setter>
        <setter property="stretch" value="fill"></setter>
        <!--设置圆的颜色-->
        <setter property="fill" value="white"></setter>
      </style>
    </grid.resources>
    <stackpanel  horizontalalignment="center" 
      verticalalignment="center">
      <viewbox width="{binding viewboxsize}" height="{binding viewboxsize}" 
      horizontalalignment="center" 
      verticalalignment="center">
        <grid x:name="layoutroot"  
        background="transparent" 
        horizontalalignment="center" 
        verticalalignment="center">
          <!--此处有canvas的加载和卸载事件-->
          <canvas x:name="progressbarcanvas" rendertransformorigin="0.5,0.5" 
          horizontalalignment="center" 
          verticalalignment="center" width="{binding canvassize}" 
          height="{binding canvassize}" loaded="handleloaded" 
          unloaded="handleunloaded" >
            <!--画圆-->            
            <canvas.rendertransform>
              <rotatetransform x:name="spinnerrotate" angle="0" />
            </canvas.rendertransform>
          </canvas>
        </grid>
      </viewbox>
    </stackpanel>
  </grid>
</usercontrol> 

2、控件后台逻辑:

 控件后台:

/// <summary>
  /// 进度条
  /// </summary>
  public partial class progressbarcontrol : usercontrol
  {
    //集成到按指定时间间隔和指定优先级处理的 system.windows.threading.dispatcher 队列中的计时器。
    private dispatchertimer animationtimer;
    private progressbardatamodel _datamodel;
    private int index = 0;
    #region 构造方法与加载
    /// <summary>
    /// 构造方法
    /// </summary>
    public progressbarcontrol()
    {
      initializecomponent();
      
    }
    /// <summary>
    /// 加载后刷新
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void progressbarcontrol_onloaded(object sender, routedeventargs e)
    {
      animationtimer = new dispatchertimer(dispatcherpriority.contextidle, dispatcher);
      //指定时间间隔
      animationtimer.interval = new timespan(0, 0, 0, 0, timespan);
      if (ellipsecount < 1)
      {
        ellipsecount = 12;
      }
      for (int i = 0; i < ellipsecount; i++)
      {
        progressbarcanvas.children.add(new ellipse());
      }
      var datamodel = new progressbardatamodel()
      {
        canvassize = canvassize,
        eclipsesize = ellipsesize
      };
      _datamodel = datamodel;
      this.datacontext = datamodel;
    }
    #endregion

    #region 属性
    /// <summary>
    /// 获取或设置圆圈数量
    /// 默认12
    /// </summary>
    public double ellipsecount
    {
      get { return (double)getvalue(ellipsecountproperty); }
      set { setvalue(ellipsecountproperty, value); }
    }
    public static readonly dependencyproperty ellipsecountproperty =
      dependencyproperty.register("ellipsecount", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(10.0, frameworkpropertymetadataoptions.affectsrender));

    /// <summary>
    /// 获取或设置圆圈大小
    /// 默认10
    /// </summary>
    public double ellipsesize
    {
      get { return (double)getvalue(ellipsesizeproperty); }
      set { setvalue(ellipsesizeproperty, value); }
    }
    public static readonly dependencyproperty ellipsesizeproperty =
      dependencyproperty.register("ellipsesize", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(10.0, frameworkpropertymetadataoptions.affectsrender));

    /// <summary>
    /// 获取或设置面板大小
    /// 默认80
    /// </summary>
    public double canvassize
    {
      get { return (double)getvalue(canvassizeproperty); }
      set { setvalue(canvassizeproperty, value); }
    }
    public static readonly dependencyproperty canvassizeproperty =
      dependencyproperty.register("canvassize", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(80.0, frameworkpropertymetadataoptions.affectsrender));

    /// <summary>
    /// 获取或设置每次旋转角度
    /// 默认10.0
    /// </summary>
    public double stepangle
    {
      get { return (double)getvalue(stepangleproperty); }
      set { setvalue(stepangleproperty, value); }
    }

    public static readonly dependencyproperty stepangleproperty =
      dependencyproperty.register("stepangle", typeof(double), typeof(progressbarcontrol),
      new frameworkpropertymetadata(10.0, frameworkpropertymetadataoptions.affectsrender));
    /// <summary>
    /// 获取或设置每次旋转间隔时间(毫秒)
    /// 默认100毫秒
    /// </summary>
    public int timespan
    {
      get { return (int)getvalue(timespanproperty); }
      set { setvalue(timespanproperty, value); }
    }
    public static readonly dependencyproperty timespanproperty =
      dependencyproperty.register("timespan", typeof(int), typeof(progressbarcontrol),
      new frameworkpropertymetadata(100, frameworkpropertymetadataoptions.affectsrender));
    
    #endregion

    #region 方法
    /// <summary>
    /// canvas加载
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void handleloaded(object sender, routedeventargs e)
    {
      //设置设置圆的位置和旋转角度
      seteclipseposition(_datamodel);
      //designerproperties  提供用于与设计器进行通信的附加属性。
      if (!designerproperties.getisindesignmode(this))
      {
        if (this.visibility == system.windows.visibility.visible)
        {
          //超过计时器间隔时发生。
          animationtimer.tick += handleanimationtick;
          animationtimer.start();
        }
      }
    }

    /// <summary>
    /// 设置圆的位置和旋转角度
    /// </summary>
    private void seteclipseposition(progressbardatamodel datamodel)
    {
      //圆周长就是:c = π * d 或者c=2*π*r(其中d是圆的直径,r是圆的半径)
      double r =datamodel.r;

      var children=progressbarcanvas.children;
      int count = children.count;
      double step = (math.pi * 2) / count;

      //根据圆中正弦、余弦计算距离
      int index = 0;
      foreach (var element in children)
      {
        var ellipse = element as ellipse;
        //透明度
        var opacity = convert.todouble(index)/(count - 1);
        ellipse.setvalue(uielement.opacityproperty, opacity<0.05?0.05:opacity);
        //距离
        double left = r + math.sin(step*index)*r;
        ellipse.setvalue(canvas.leftproperty,left);
        double top = r - math.cos(step*index)*r;
        ellipse.setvalue(canvas.topproperty, top);

        index++;
      }
    }

    /// <summary>
    /// canvas卸载时
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void handleunloaded(object sender, routedeventargs e)
    {
      animationtimer.stop();
      //除去委托
      animationtimer.tick -= handleanimationtick;
    }

    /// <summary>
    /// 超过计时器间隔时发生。
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void handleanimationtick(object sender, eventargs e)
    {
      //设置旋转角度
      spinnerrotate.angle = (spinnerrotate.angle + stepangle) % 360;
    }
    #endregion
}

数据model类:

/// <summary>
  /// 进度条model类
  /// </summary>
  public class progressbardatamodel
  {
    public double eclipsesize { get; set; }
    public double canvassize { get; set; }
    public double viewboxsize
    {
      get
      {
        double length = convert.todouble(canvassize) - convert.todouble(eclipsesize);
        return length;
      }
    }
    public double eclipseleftlength
    {
      get
      {
        double length = convert.todouble(canvassize) / 2;
        return length;
      }
    }
    public double r
    {
      get
      {
        double length = (convert.todouble(canvassize) - convert.todouble(eclipsesize)) / 2;
        return length;
      }
    }
}

3、取用控件

<control:progressbarcontrol canvassize="100" ellipsecount="10" ellipsesize="10" stepangle="36" timespan="60"/>

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。