我正在尝试编写一个程序,它会在屏幕顶部显示一条图标,以便快速访问文件。为了进行早期测试,我正在绘制一个矩形,我正在按照一个临时位置来检查它在屏幕上移动的顺畅程度。
public Pen defaultPen;
public PointF tempLocation = new PointF( 10, 10 );
public Timer updateTimer = new Timer();
public DesktopStrip()
{
this.Size = new Size( Screen.PrimaryScreen.Bounds.Width, 88 );
this.Top = 10;
this.FormBorderStyle = FormBorderStyle.None;
this.BackColor = Color.Black;
this.Paint += new PaintEventHandler( PaintDesktop );
this.SetStyle( ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint, true );
this.defaultPen = new Pen( Color.White );
this.updateTimer.Interval = 30;
this.updateTimer.Tick += new EventHandler( anim_Tick );
this.updateTimer.Start();
}
private void anim_Tick( object sender, EventArgs e )
{
tempLocation.X++;
Refresh();
}
private void PaintDesktop( object sender, PaintEventArgs e )
{
Graphics g = e.Graphics;
g.InterpolationMode = InterpolationMode.Low;
g.PixelOffsetMode = PixelOffsetMode.None;
g.SmoothingMode = SmoothingMode.None;
g.DrawRectangle( defaultPen, new Rectangle( (int)tempLocation.X, (int)tempLocation.Y, 64, 64 ) );
}
我的问题是,当它在屏幕上移动时,我可以看到它在点上口吃,我需要它尽可能地平滑。我有什么遗失或者我可以改变吗?
我尝试过使用invalidate而不是刷新,但它不会在视觉上改变任何东西。
有没有其他方法可以做到这一点而不是使用winforms?什么东西可能更适合动画?
编辑:我更改了anim_Tick方法以合并插值:
tempLocation.X = (float)Lerp( tempLocation.X, moveLoc.X, 0.05 );
我的插值方法是:
public double Lerp( double value1, double value2, double amount )
{
value1 = value1 + ( value2 - value1 ) * amount;
return value1;
}
我还将定时器间隔更改为30ms。尽管如此,我仍然可以看到动作中的一个口吃。
答案 0 :(得分:0)
你的问题就是问题。
您要求UI每隔1 ms刷新一次位置。那太频繁了。计算偏移量并达到实际渲染代码所需的时间最多可能需要5倍(如果不是10倍)。考虑在更新之间使用插值位置,并将它们隔开,每30毫秒说一次。
基本上你需要每秒移动矩形几个像素。您需要使用Lerp函数来执行此操作。
以下是open source project应该有用的链接。