[英]How can I fade in/out an image to make effect that the screen get dark slowly?
[英]How can i make on the pixels fade in/out like effect?
今天,即時通訊正在繪制事件中的像素閃爍。 在form1中,我在計時器滴答事件中將此代碼設置為1000ms。
private void timer1_Tick(object sender, EventArgs e)
{
CloudEnteringAlert.cloudColorIndex = (CloudEnteringAlert.cloudColorIndex + 1) % CloudEnteringAlert.cloudColors.Length;
pictureBox1.Invalidate();
}
在CloudEntering類中,我位於頂部:
public static Brush[] cloudColors = new[] { Brushes.Yellow, Brushes.Transparent };
然后在paint方法中,此paint方法是從form1 pictureBox1 paint事件調用的:
foreach (PointF pt in clouds)
{
e.FillEllipse(cloudColors[cloudColorIndex], pt.X * (float)currentFactor, pt.Y * (float)currentFactor, 7f, 7f);
}
所以我現在看到的是像素為黃色的一秒鍾,像素為透明的一秒鍾。
現在我想做的是:
每個像素將從半徑5開始。
每個像素半徑將增大到25。
動畫將自上而下。
到達半徑25的每個像素將開始變小,回到半徑5。
當第一個像素從5開始時將變為半徑15,下一個像素將開始變得更大。
因此,如果第一個像素從5開始,現在是15,那么下一個像素將開始變大,第一個像素將繼續增加到25,而第一個像素是25時它將變小。 第二個在其15時變大,第三個將變大,依此類推。
所有像素將以半徑5開始,但是只有第一個像素開始變大,然后變為15,然后是下一個像素;當第一個為25時,它將變小。
這是每個像素之間的時間。
並且每個像素半徑大小的變化應花費300ms!
我該怎么做 ?
首先,您需要將渲染單個橢圓所需的所有信息封裝到一個單獨的類中。 就像這樣:
public class Ellipse
{
public PointF Center { get; set; }
public Brush Brush { get; set; }
public float Diameter { get; set; }
public float DiameterDelta { get; set; }
public Ellipse(float x, float y)
{
Center = new PointF(x, y);
Brush = Brushes.Blue;
Diameter = 5;
DiameterDelta = 1;
}
}
Ellipse.DiameterDelta
屬性是將用於動畫的delta值,它可以是正值(從直徑5
到直徑25
),也可以是負值(反向時)。 此屬性的值(我在上面使用過1
)和Timer.Interval
一起將影響動畫的速度。
更好的OOP設計可能會主張將動畫相關的屬性移出此類,但為簡單起見,最好從此開始。
在您的計時器事件中,您可能會遇到以下情況:
private void timer_Tick(object sender, EventArgs e)
{
// presuming that you made a separate user control
// which has a collection of ellipses in a `Clouds` property
foreach (var c in cloudBox.Clouds)
Animate(c);
cloudBox.Invalidate();
}
private void Animate(Ellipse c)
{
// update diameter
c.Diameter += c.DiameterDelta;
// when you reach bounds, change delta direction
if ((c.DiameterDelta < 0 && c.Diameter <= 5) ||
(c.DiameterDelta > 0 && c.Diameter >= 25))
c.DiameterDelta = -c.DiameterDelta;
}
為了獲得平滑,不閃爍的動畫,您很可能必須使用在其構造函數中設置了ControlStyles.AllPaintingInWmPaint
和ControlStyles.OptimizedDoubleBuffer
的自定義控件,所以我要做的不是PictureBox
,而是:
public partial class CloudBox : UserControl
{
public CloudBox()
{
InitializeComponent();
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
private readonly List<Ellipse> _clouds = new List<Ellipse>();
public List<Ellipse> Clouds
{
get { return _clouds; }
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
foreach (var cloud in _clouds)
{
e.Graphics.FillEllipse(
cloud.Brush, cloud.Center.X, cloud.Center.Y,
cloud.Diameter, cloud.Diameter);
}
base.OnPaint(e);
}
}
我尚未對此進行測試,但我相信您可以填寫詳細信息。 將Timer.Interval
設置為10或20 ms應該會產生非常流暢的動畫恕我直言。
[編輯]要用一些測試數據實例化整個事情(我不知道從哪里獲得),可以在Form.Load
事件處理程序中使用類似以下內容的東西:
for (int i = 0; i < 400; i += 50)
for (int j = 0; j < 400; j += 50)
cloudBox.Clouds.Add(new Ellipse(i, j));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.