-3

当我打开游戏启动器时,我注意到新闻是如何在那里实现的。我真的很喜欢这个想法,所以我决定在我的项目中这样做,首先我做了一个面板,在里面塞了几张图片,然后实际上做了两个按钮,我打算用它们来翻阅图片。但是如何顺利进行呢?这就是问题所在,我不明白如何使图像平滑翻转

用鼠标指点

在此处输入图像描述

4

1 回答 1

1

我不知道图像是如何滑动、翻转、拉伸或其他的,但我认为带有 GDI+ 的 WinForms 不是最佳选择。我认为WPF会更好。我还建议为这些图像处理使用合适的库。

但是,如果你想要它非常(!)简单,你可以使用这个类:

public class SlideAnimation
{
    public event EventHandler<AnimationEventArgs> AnimationFinished;

    private readonly Control Control;
    private readonly Timer Timer;
    private float fromXPosition;

    public SlideAnimation(Control ctrl)
    {
        Control = ctrl;
        Timer = new Timer();
        Timer.Interval = 10;
        Timer.Tick += Timer_Tick;
        Control.Paint += Control_Paint;
    }

    public float Speed { get; set; }
    public Image From { get; set; }
    public Image To { get; set; }
    public AnimationDirection Direction { get; set; }

    public bool IsRunning
    {
        get
        {
            return Timer.Enabled;
        }
    }

    public void StartAnimation()
    {
        // maybe move those checks into the setter of the corresponding property
        if (this.From == null)
            throw new InvalidOperationException();
        if (this.To == null)
            throw new InvalidOperationException();
        if (this.Speed <= 0)
            throw new InvalidOperationException();

        fromXPosition = 0;
        Timer.Enabled = true;
    }

    protected void OnAnimationFinished(AnimationEventArgs e)
    {
        AnimationFinished?.Invoke(this, e);
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        // increase or decrease the position of the first image
        fromXPosition = fromXPosition + (this.Speed * this.Direction);
        Control.Invalidate();
        if (Math.Abs(fromXPosition) >= this.From.Width)
        {
            Timer.Enabled = false;
            OnAnimationFinished(new AnimationEventArgs(this.Direction));
        }
    }

    private void Control_Paint(object sender, PaintEventArgs e)
    {
        if (!Timer.Enabled)
            return;

        // draw both images next to each other depending on the direction
        e.Graphics.DrawImage(this.From, new PointF(fromXPosition, 0));
        e.Graphics.DrawImage(this.To, new PointF(fromXPosition - (this.From.Width * this.Direction), 0));
    }
}

public enum AnimationDirection
{
    Forward = -1,
    Backward = 1
}

public class AnimationEventArgs : EventArgs
{
    public AnimationEventArgs(AnimationDirection direction)
    {
        Direction = direction;
    }

    public AnimationDirection Direction { get; }
}

此类仅在动画处于活动状态时绘制图像。其他所有失效都不会触发该Control_Paint方法。

为您的表单使用以下代码:

public class Form1
{
    private List<Image> imgList = new List<Image>();
    private int currentIndex = 0;
    private SlideAnimation animation;

    public Slideshow()
    {
        InitializeComponent();

        imgList.Add(Image.FromFile("pic1.bmp"));
        imgList.Add(Image.FromFile("pic2.bmp"));
        imgList.Add(Image.FromFile("pic3.bmp"));
        imgList.Add(Image.FromFile("pic4.bmp"));
        imgList.Add(Image.FromFile("pic5.bmp"));
        animation = new SlideAnimation(this.Panel1);
        animation.Speed = 20;
        animation.AnimationFinished += AnimationFinished;
    }

    private void btnPrev_Click(object sender, EventArgs e)
    {
        if (currentIndex == 0)
            return;
        if (animation.IsRunning)
            return;
        animation.Direction = AnimationDirection.Backward;
        animation.From = imgList[currentIndex];
        animation.To = imgList[currentIndex - 1];
        animation.StartAnimation();
    }

    private void btnNext_Click(object sender, EventArgs e)
    {
        if (currentIndex == imgList.Count - 1)
            return;
        if (animation.IsRunning)
            return;
        animation.Direction = AnimationDirection.Forward;
        animation.From = imgList[currentIndex];
        animation.To = imgList[currentIndex + 1];
        animation.StartAnimation();
    }

    private void AnimationFinished(object sender, AnimationEventArgs e)
    {
        currentIndex = currentIndex - (1 * e.Direction);
    }

    private void Panel1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImage(imgList[currentIndex], 0, 0);
    }
}

由于有很多绘图操作,您可以使用支持 DoubleBuffer 的面板。

public class DoubleBufferedPanel : Panel
{
    public DoubleBufferedPanel()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
    }
}

请记住,这个例子非常简单,远非“花哨”。

于 2020-07-19T21:36:01.757 回答