Как нарисовать линейный градиент круга в. NET? - PullRequest
0 голосов
/ 17 января 2020

Как можно нарисовать такой круг в VB. NET или в C#?

enter image description here

1 Ответ

2 голосов
/ 17 января 2020

Вы можете приблизить кольцо с большим количеством трапеций и использовать разные цвета заливки для каждого прямоугольника.

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

Результат:

Coloured ring

Лучших результатов, вероятно, можно достичь, используя Bru sh, который позволяет градиент цвета в правильном направлении для каждого прямоугольника.


Также возможно сделать круг из кольцевого секторы, которые дают точные границы вместо прямых краев трапеций:

    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

Обратите внимание на меньшее количество шагов, поэтому цветов меньше, но края по-прежнему имеют круг:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...