【问题标题】:How to draw a linear gradient circle in .NET?如何在 .NET 中绘制线性渐变圆?
【发布时间】:2020-01-17 12:12:26
【问题描述】:

我可以在 VB.NET 或 C# 中画出这样的圆圈吗?

【问题讨论】:

  • 如果你能在minimal reproducible example 上分享你目前的进展,那就太棒了。
  • 最简单的解决方案可能是截取图像,将其保存为位图,然后将该位图添加到您的表单中。
  • 你想在哪里“画”这个?在表格上?成位图?在 OpenGL 中?通过将位置和颜色发送到无人机网络以将其绘制在天空中?
  • 决定使用其中一种语言,从零到 2π 循环,将 x 坐标计算为半径 * cos(角度),将 y 坐标计算为半径 * sin(角度)。创建一个适当厚的纯色画笔并使用一些 Color.FromArgb(...) 指定颜色,其中参数是角度的函数。

标签: c# vb.net


【解决方案1】:

您可以用许多梯形来近似环,并为每个矩形使用不同的填充颜色。

Imports System.Drawing.Drawing2D

Public Class Form1

    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint

        Dim centre = New PointF(160, 140)
        Dim r1 = 100
        Dim r2 = 105

        Dim colourStart = 90 * Math.PI / 180

        Dim col1 As Color
        col1 = Color.FromArgb(0, 0, 0)

        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias

        Using br As New SolidBrush(col1)

            Dim nSteps = 180
            Dim aInc = 2 * Math.PI / nSteps

            For i = 0 To nSteps - 1
                Dim a = i * aInc

                Dim t1 = a
                Dim t2 = a + aInc

                Dim p1 = New PointF(CSng(r2 * Math.Cos(t1)) + centre.X, CSng(r2 * Math.Sin(t1)) + centre.Y)
                Dim p2 = New PointF(CSng(r1 * Math.Cos(t1)) + centre.X, CSng(r1 * Math.Sin(t1)) + centre.Y)
                Dim p3 = New PointF(CSng(r1 * Math.Cos(t2)) + centre.X, CSng(r1 * Math.Sin(t2)) + centre.Y)
                Dim p4 = New PointF(CSng(r2 * Math.Cos(t2)) + centre.X, CSng(r2 * Math.Sin(t2)) + centre.Y)

                Dim pts = {p1, p2, p3, p4}

                col1 = HSL2RGB(a + colourStart, 1, 0.5)
                br.Color = col1

                e.Graphics.FillPolygon(br, pts)

            Next

        End Using

    End Sub

    ' HSL2RGB from https://dotnetfiddle.net/aORkec (with translation and bugfix).
    ''' <summary>
    ''' Convert HSL to RGB.
    ''' </summary>
    ''' <param name="h">Hue 0..2pi</param>
    ''' <param name="s">Saturation 0..1</param>
    ''' <param name="l">Lightness 0..1</param>
    ''' <returns>RGB color.</returns>
    <DebuggerHidden>
    Function HSL2RGB(h As Double, s As Double, l As Double) As Color
        If h > 2 * Math.PI Then h -= 2 * Math.PI
        If h < 0 Then h += 2 * Math.PI

        h = h / (2 * Math.PI)
        Dim v As Double

        Dim r, g, b As Double
        r = l
        g = l
        b = l
        v = If(l <= 0.5, l * (1.0 + s), l + s - l * s)

        If (v > 0) Then
            Dim m As Double
            Dim sv As Double
            Dim sextant As Integer
            Dim fract, vsf, mid1, mid2 As Double
            m = l + l - v
            sv = (v - m) / v
            h *= 6.0
            sextant = CInt(Math.Floor(h))
            fract = h - sextant
            vsf = v * sv * fract
            mid1 = m + vsf
            mid2 = v - vsf
            Select Case sextant
                Case 0, 6
                    r = v
                    g = mid1
                    b = m
                Case 1
                    r = mid2
                    g = v
                    b = m
                Case 2
                    r = m
                    g = v
                    b = mid1
                Case 3
                    r = m
                    g = mid2
                    b = v
                Case 4
                    r = mid1
                    g = m
                    b = v
                Case 5
                    r = v
                    g = m
                    b = mid2
            End Select
        End If

        Return Color.FromArgb(Convert.ToByte(r * 255.0F), Convert.ToByte(g * 255.0F), Convert.ToByte(b * 255.0F))

    End Function

End Class

结果:

使用允许每个矩形在正确方向上的颜色渐变的画笔可能会获得更好的结果。


也可以用环形扇形制作圆,它给出了准确的边界,而不是梯形的直边:

    Function Rad2Deg(x As Double) As Single
        Return Convert.ToSingle(x * 180 / Math.PI)
    End Function

    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint

        Dim centreF = New PointF(160, 140)
        Dim centre = New Point(CInt(centreF.X), CInt(centreF.Y))
        Dim r1 = 100
        Dim r2 = 105

        Dim boundingRectInner = New Rectangle(-r1, -r1, r1 * 2, r1 * 2)
        boundingRectInner.Offset(centre)

        Dim boundingrectOuter = New Rectangle(-r2, -r2, r2 * 2, r2 * 2)
        boundingrectOuter.Offset(centre)

        Dim colourStart = 90 * Math.PI / 180

        Dim col1 As Color
        col1 = Color.FromArgb(0, 0, 0)

        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias

        Using br As New SolidBrush(col1)

            Dim nSteps = 12
            Dim aInc = 2 * Math.PI / nSteps
            Dim sweepAngle = Rad2Deg(aInc)

            For i = 0 To nSteps - 1
                Dim a = i * aInc

                Dim t1 = a
                Dim t2 = a + aInc

                Dim p3 = New PointF(CSng(r1 * Math.Cos(t2)) + centreF.X, CSng(r1 * Math.Sin(t2)) + centreF.Y)
                Dim p4 = New PointF(CSng(r2 * Math.Cos(t2)) + centreF.X, CSng(r2 * Math.Sin(t2)) + centreF.Y)

                Using gp As New GraphicsPath()
                    gp.AddArc(boundingRectInner, Rad2Deg(a), sweepAngle)
                    gp.AddLine(p3, p4)
                    gp.AddArc(boundingrectOuter, Rad2Deg(a + aInc), -sweepAngle)
                    gp.CloseFigure()

                    col1 = HSL2RGB(a + colourStart, 1, 0.5)
                    br.Color = col1

                    e.Graphics.FillPath(br, gp)
                End Using

            Next

        End Using

    End Sub

注意步数越少,颜色越少,但边缘仍然是圆形:

【讨论】:

    猜你喜欢
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多