繁体   English   中英

无限滚动渐变背景

[英]Infinite scrolling gradient background

我已经搜索过,但没有在 SO 上找到这个问题的答案,所以我直接在这里问。

有没有人有一个干净的方法来创建一个无限滚动的渐变背景? (渐变变化,因此您可以从一侧/角落到另一侧跟随颜色)

我在 15 年前就用 VB 做过这个,但是我已经很久没有接触 VB 了,它对我来说都是希腊语。

假设以前有人在 C# 中做过类似的事情——想想演示场景类的动画。

VB 代码片段来自我多年前做的一个工作表单背景,它不会滚动太多,而是从一个边缘到另一个边缘来回弹跳。

Private Sub picCanvas_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
    Dim rect As New Rectangle(-10, -10, Me.ClientSize.Width + 20, Me.ClientSize.Height + 20)
    Dim halfw As Integer = CType(Me.ClientSize.Width, Integer)
    Dim br As New LinearGradientBrush(New Point(-120, 500), New Point(Me.ClientSize.Width + 120, 0), Color.Red, Color.Blue)
    Dim color_blend As New ColorBlend
    color_blend.Colors = New Color() {Color.Black, Color.Purple, Color.Teal, Color.Purple, Color.Black}
    m_Theta += m_Delta
    color_blend.Positions = New Single() {0, 0.01, m_Theta, 0.99, 1}
    br.InterpolationColors = color_blend
    e.Graphics.FillRectangle(br, rect)
    br.Dispose()
    If (m_Theta > 0.75) Or (m_Theta < 0.25) Then m_Delta = -m_Delta
End Sub

我将不胜感激任何帮助让这种东西在 WinForms 中工作只使用 GDI 和画笔,没有 XML 或任何东西请 ^^/

我不太确定这是你想要做的,无论如何,从此处提供的半伪代码来看,你似乎想要沿轴移动渐变填充的位置。

看起来填充是倾斜的,所以我添加了确定旋转角度的方法。
我保留了 LinearGradientBrush 来生成混合填充,尽管 GraphicsPath 和PathGradientBrush的组合可能更灵活。

为了移动渐变填充,我使用了标准的System.Windows.Forms.Timer 它用于平移填充,递增一个值,然后在用作画布的双缓冲 Form 的 OnPaint 覆盖中设置为Matrix的平移组件(当然,您可以改用 PictureBox)

Matrix 还用于旋转填充,以备不时之需

计时器的Tick处理程序还验证可用于更改填充的其他条件(bool 字段):

  • useThetaShift启用混合间隔的半动态运动( Position属性)
  • useTriangular启用和交替混合功能,由SetBlendTriangularShape()方法生成,它仅考虑 LinearGradientBrush 的起始和结束颜色,并定义颜色衰减的中心点

此处显示的示例窗体也可以设置为自动滚动,混合扩展到 DisplayRectangle
当显示模态对话框时,混合也会动画化(你提到了一个关于窗口......)

internal class SomeForm : Form {
    private System.Windows.Forms.Timer gradientTimer = null;

    public SomeForm() {
        InitializeComponent();
        if (components is null) components = new Container();
        ResizeRedraw = true;

        startColor = blendColors[0];
        meanColor = blendColors[1];
        endColor = blendColors[blendColors.Length - 1];
        gradientTimer = new System.Windows.Forms.Timer(components) { Interval = 100 };
        gradientTimer.Tick += GradientTimer_Tick;
        gradientTimer.Start();
    }

    float theta = .0f;
    float delta = .005f;
    float tringularShift = .25f;
    float tringularShiftDelta = .015f;
    float speed = 7.5f;
    float rotation = 0f;

    private Color[] blendColors = new[]{ 
        Color.Black, Color.Purple, Color.Teal, Color.Purple, Color.Black
    };
    Color startColor = Color.Empty;
    Color endColor = Color.Empty;
    Color meanColor = Color.Empty;
    PointF translateMx = PointF.Empty;
    bool useThetaShift = false;
    bool useTriangular = false;

    private void GradientTimer_Tick(object sender, EventArgs e)
    {
        if (useTriangular) {
            tringularShift += tringularShiftDelta;
            tringularShift = Math.Max(Math.Min(tringularShift, 1.0f), .35f);
            if ((tringularShift >= 1.0f) | (tringularShift <= .35f)) tringularShiftDelta*= -1;
        }

        if (useThetaShift) {
            theta += delta;
            theta = Math.Max(Math.Min(theta, .15f), 0f);
            if ((theta >= .15f) | (theta <= 0f)) delta*= -1;
        }

        translateMx = PointF.Add(translateMx, new SizeF(speed, speed));
        if (Math.Abs(translateMx.X) >= short.MaxValue) translateMx = PointF.Empty;
        Invalidate();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        var display = DisplayRectangle;
        using (var mx = new Matrix(1f, 0f, 0f, 1f, translateMx.X, translateMx.Y))
        using (var brush = new LinearGradientBrush(display, startColor, endColor, rotation)) {
            var colorBlend = new ColorBlend(blendColors.Length) {
                Colors = blendColors,
                Positions = new float[] { .0f, .25f + theta, .5f + theta, .75f + theta, 1.0f },
            };
            brush.InterpolationColors = colorBlend;
            mx.Rotate(rotation);
            brush.Transform = mx;
            if (useTriangular) brush.SetBlendTriangularShape(.5f, tringularShift);
            e.Graphics.FillRectangle(brush, display);
        }
        base.OnPaint(e);
    }

    protected override void OnFormClosing(FormClosingEventArgs e) {
        // Move to OnFormClosed() if this action can be canceled
        gradientTimer.Stop();
        base.OnFormClosing(e);
    }
}

由于尺寸原因,我无法在此处发布动画。 你可以直接在 Imgur 上看到它是如何工作的:
动画线性渐变路径

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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