简体   繁体   English

如何使像素像效果一样淡入/淡出?

[英]How can i make on the pixels fade in/out like effect?

Today im doing the pixels in the paint event to blink. 今天,即时通讯正在绘制事件中的像素闪烁。 In form1 i have this code in a timer tick event that the interval is set to 1000ms. 在form1中,我在计时器滴答事件中将此代码设置为1000ms。

private void timer1_Tick(object sender, EventArgs e)
        {
            CloudEnteringAlert.cloudColorIndex = (CloudEnteringAlert.cloudColorIndex + 1) % CloudEnteringAlert.cloudColors.Length;
            pictureBox1.Invalidate();
        }

In the CloudEntering class i have on the top: 在CloudEntering类中,我位于顶部:

public static Brush[] cloudColors = new[] { Brushes.Yellow, Brushes.Transparent };

Then in a paint method this paint method im calling from the form1 pictureBox1 paint event: 然后在paint方法中,此paint方法是从form1 pictureBox1 paint事件调用的:

foreach (PointF pt in clouds)
                {
                    e.FillEllipse(cloudColors[cloudColorIndex], pt.X * (float)currentFactor, pt.Y * (float)currentFactor, 7f, 7f);
                }

So what i see now is one second the pixels are in yellow and one second the pixels are in Transparent. 所以我现在看到的是像素为黄色的一秒钟,像素为透明的一秒钟。

Now what i want to do is: 现在我想做的是:

  1. Each pixel will start from radius 5. 每个像素将从半径5开始。

  2. Each pixel radius will get bigger to 25. 每个像素半径将增大到25。

  3. The animation will be from the top to the bottom. 动画将自上而下。

  4. Each pixel that got to radius 25 will start to get smaller back to radius 5. 到达半径25的每个像素将开始变小,回到半径5。

  5. When the first pixel is started from 5 will get to radius 15 the next one will start to get bigger. 当第一个像素从5开始时将变为半径15,下一个像素将开始变得更大。

So if the first pixel is start at 5 now its 15 the next one will start to get bigger and the first one will continue to 25 when the first one is 25 it will get smaller. 因此,如果第一个像素从5开始,现在是15,那么下一个像素将开始变大,第一个像素将继续增加到25,而第一个像素是25时它将变小。 The second one when its 15 the third one will get bigger and so on. 第二个在其15时变大,第三个将变大,依此类推。

All the pixels will start at radius 5 but only the first one will start get bigger get to 15 then the next one and when the first is 25 it will get smaller . 所有像素将以半径5开始,但是只有第一个像素开始变大,然后变为15,然后是下一个像素;当第一个为25时,它将变小。

This is the time between each pixel. 这是每个像素之间的时间。

And each pixel radius size change should take 300ms ! 并且每个像素半径大小的变化应花费300ms!

How can i do it ? 我该怎么做 ?

You want to start by encapsulating all information needed to render a single ellipse into a separate class. 首先,您需要将渲染单个椭圆所需的所有信息封装到一个单独的类中。 That would be something like: 就像这样:

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;
    }
}

The Ellipse.DiameterDelta property is the delta value which will be used for animation, and it can be positive (when going from diameter 5 to diameter 25 ), or negative (when going backwards). Ellipse.DiameterDelta属性是将用于动画的delta值,它可以是正值(从直径5到直径25 ),也可以是负值(反向时)。 The value of this property (I've used 1 above) together with the your Timer.Interval will influence the speed of your animation. 此属性的值(我在上面使用过1 )和Timer.Interval一起将影响动画的速度。

A better OOP design would probably advocate moving animation-related properties out of this class, but for simplicity sake, it's better to start with this. 更好的OOP设计可能会主张将动画相关的属性移出此类,但为简单起见,最好从此开始。

In your timer event, you might have something like: 在您的计时器事件中,您可能会遇到以下情况:

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;
}

To get a smooth, non flickering animation, you will most likely have to use a custom control with ControlStyles.AllPaintingInWmPaint and ControlStyles.OptimizedDoubleBuffer set in its constructor, so instead of a PictureBox , I would do something like: 为了获得平滑,不闪烁的动画,您很可能必须使用在其构造函数中设置了ControlStyles.AllPaintingInWmPaintControlStyles.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);
    }
}

I haven't tested this, but I believe you'll be able to fill in the details. 我尚未对此进行测试,但我相信您可以填写详细信息。 Setting Timer.Interval to 10 or 20 ms should yield a pretty fluid animation IMHO. Timer.Interval设置为10或20 ms应该会产生非常流畅的动画恕我直言。

[Edit] To instantiate the whole thing with some test data (I don't know where you get it from), you could use something like this in your Form.Load event handler: [编辑]要用一些测试数据实例化整个事情(我不知道从哪里获得),可以在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM