簡體   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