version : 1.1
time : 20170523 12:30
author : 秋后夜雨coconut9325的博客
虽然不是什么大工程,但是依然保留所有权
在工作了一定时间之后,你会发现静态 UI 实在是让人受不了了!!!
所以接下来,我将对动态UI进行研究,给自己的工作时间予以肯定,以及提高兴趣。
在我们平常生活接触过的软件当中,我们发现了很多动态的控件。
例如:
1.展开折叠,在展开或收起控件时的动画效果。
2.进入结束,在进入或者结束某一场景、软件时的动画效果。
3.放大缩小,在放大或缩小地图时的动画效果。
4.滑动移动,在自定义slider中,自定义控件的滑动移动。
因为快速打的第一篇原创,一下没想到更多的动态信息,待以后补充,更欢迎留言讨论。
在开始之前,我们要清楚认识到物理学的重要性,因为这可以帮助我们设计UI更加贴近生活规律,或者说更加逼真,让你的UI不再干枯无味。
环境:CSharp (.Net framework 4.0)
#region Fields & Variants & model
// GroupBoxFilter move distance.
private int moveDistanceX = 705;
// GroupBoxFilter move distance.
private int moveDistanceY = 165;
// GroupBoxFilter begin move Point (X,Y). final move Distance (X,Y).
private Point beginPoint = new Point(0, 0);
private Point finalPoint = new Point(0, 0);
// Simulation range.
private const int curvesAccuracy = 3;
private const decimal startCurves = -5.0m; // normally not change
// Simulation curves.
private int moveCurves = 0;
private const decimal curvesSpeed = 0.1m;
private const int curvesRange = (int)((0 - startCurves * 2) / curvesSpeed) + 1;
private double[] curvesArray = new double[curvesRange];
#endregion
初始化:
private void Form1_Load(object sender, EventArgs e)
{
try
{
InitUI();
}
catch (Exception ex)
{
#if DEBUG
MessageBox.Show(ex.ToString());
#endif
throw;
}
}
public void InitUI()
{
// Init simulation curves
for (int i = 0; i < curvesRange; i++)
{
if (i == 0)
curvesArray[i] = 0;
else if (i + 1 >= curvesRange)
curvesArray[i] = 1;
else
curvesArray[i] = Math.Round(((Math.Tanh((double)startCurves + (double)curvesSpeed * i) + 1) / 2), curvesAccuracy, MidpointRounding.AwayFromZero);
}
}
折叠展开按钮:
private void btnFold_Click(object sender, EventArgs e)
{
if (groupBoxFilter.Width < this.Width / 2)
{
// move to right.
beginPoint = new Point(groupBoxFilter.Width, groupBoxFilter.Height);
finalPoint = new Point(groupBoxFilter.Width + moveDistanceX, groupBoxFilter.Height + moveDistanceY);
tmFold.Enabled = true;
}
else
{
// move to left.
beginPoint = new Point(groupBoxFilter.Width, groupBoxFilter.Height);
finalPoint = new Point(groupBoxFilter.Width - moveDistanceX, groupBoxFilter.Height - moveDistanceY);
tmFold.Enabled = true;
}
}
定时器(100ms):
private void tmFold_Tick(object sender, EventArgs e)
{
string foldString = "Fold";
double movePercent = curvesArray[moveCurves];
Point smallChange = new Point(1, 1);
Point finalMoveDistance = new Point(Math.Abs(finalPoint.X - beginPoint.X), Math.Abs(finalPoint.Y - beginPoint.Y));
Point nowMoveDistance = new Point(Math.Abs(groupBoxFilter.Width - beginPoint.X), Math.Abs(groupBoxFilter.Height - beginPoint.Y));
// calculate smallChange to prepare moving.
if (groupBoxFilter.Width == finalPoint.X)
smallChange.X = 0;
else
smallChange.X = (int)(finalMoveDistance.X * curvesArray[moveCurves] - nowMoveDistance.X);
if (groupBoxFilter.Height == finalPoint.Y)
smallChange.Y = 0;
else
smallChange.Y = (int)(finalMoveDistance.Y * curvesArray[moveCurves] - nowMoveDistance.Y);
// begin move.
if (beginPoint.X < this.Width / 2)
{
//move to right.
groupBoxFilter.Size = new Size(groupBoxFilter.Width + smallChange.X, groupBoxFilter.Height + smallChange.Y);
int moveBtn = (groupBoxFilter.Height - btnFold.Height) / 2 + 4;
btnFold.Location = new Point(btnFold.Location.X, moveBtn);
foldString = "Fold";
}
else
{
//move to left.
groupBoxFilter.Size = new Size(groupBoxFilter.Width - smallChange.X, groupBoxFilter.Height - smallChange.Y);
int moveBtn = (groupBoxFilter.Height - btnFold.Height) / 2 + 4;
btnFold.Location = new Point(btnFold.Location.X, moveBtn);
foldString = "Unfold";
}
// move Curves.
if (moveCurves == curvesRange - 1)
moveCurves = 0;
else
moveCurves++;
// end move.
if (groupBoxFilter.Width == finalPoint.X && groupBoxFilter.Height == finalPoint.Y)
{
moveCurves = 0;
btnFold.Text = foldString;
this.tmFold.Enabled = false;
}
}
建议定时器时间参数与CurvesSpeed参数稍稍相互调节一下,即可看到连贯的效果
动态设计:
曲线采用的是tanh函数(Time/Distance),模拟加速度的逐渐增加及减少的物理运动。
动态效果图:
version : 1.1
time : 20170523 12:30
author : 秋后夜雨coconut9325的博客