WPF实现转圈进度条效果
程序员文章站
2022-06-23 21:58:00
在设计界面时,有时会遇到进度条,本次讲解wpf如何设计自定义的绕圈进度条,直接上代码:
1、控件界面
在设计界面时,有时会遇到进度条,本次讲解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"/>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。