Appunti
Il concetto
Prima di iniziare a disegnare, bisogna capire come simulare il famoso effetto vetro. Dopo aver analizzato alcuni esempi, sono giunto a una conclusione
alquanto semplice, ma di grande impatto. Il procedimento fondamentale che si dovrebbe utilizzare si può riassumere in questi punti:
- Prima di tutto, è necessario scegliere un colore di base per la forma voluta. In questo caso sceglierò un rettangolo di colore
verde, ma la stessa tecnica è applicabile a qualsiasi altra forma senza molto sforzo in più. Ovviamente si può spaziare in
tutta la gamma di oltre 16'000'000 di colori offerta, ma per produrre un buon effetto sarebbe meglio scegliere una tonalità abbastanza
scura, ad esempio così:
Step 1
- Il secondo passo consiste nel dare una sfumatura più chiara ad entrambi i lati. Ho già scritto un articolo su come creare una
sfumatura, perciò non mi dilungherò oltre. Tuttavia, come è possibile conoscere quale sia la giusta combinazione di componenti
RGB (rosso, verde e blu) per ottenere un colore "più chiaro"? Qui entra in gioco un'altra scala di colorazione, chiamata HSL, dal nome dei
suoi parametri: Hue (tonalità), Saturation (saturazione) e Luminosity (lumonisità). Ora, per fare delle buone conversioni bisognerebbe
sapere come queste grandezze sono correlate alle altre tre, cosa che non sappiamo. Per fortuna, qualche persona misericordiosa su Internet -
e mi riferisco al signor Rich Newman - ci ha pensato prima di noi e ha scritto una bella classe HslColor in C# per gestire questa nuova scala, che
analizzerò nel codice successivamente. Ora, aumentando la luminosità del colore, si otterrà lo stesso colore, ma più
chiaro, e questo dovrà essere posto come sfumatura a entrambi i lati:
Step 2
- Bisogna ancora aggiungere il classico riflesso del vetro. Per far questo basta porre sul rettangolo un leggero velo di bianco per metà
della sua altezza. In questo caso, useremo il canale Alpha per aumentarne la trasparenza:
Step 3
- Come ultimo tocco si può aggiungere un contorno esterno più scuro per fare risaltare il tutto, ma l'uso di questo dettaglio
dipende dal contesto in cui operate: certe occasioni lo richiederanno, mentre in altre sembrerà fuori luogo. Ad ogni modo, il risultato:
Step 4
E questo è il codice, da usare, per esempio, in un form:Imports SystemImports System.Collections.GenericImports System.TextImports System.Drawing 'Questo codice è stato scritto da Rich Newman, ed è reperibile 'all'indirizzo Classe HslColor 'E' stato convertito in Vb.Net per metà con un conertitore online free, 'per metà a mano Public Class HSLColor 'Private data members below are on scale 0-1 'They are scaled for use externally based on scale Private _hueAs Double = 1.0Private _saturationAs Double = 1.0Private _luminosityAs Double = 1.0Private Const scaleAs Double = 240.0Public Property Hue()As Double Get Return _hue * scaleEnd Get Set (ByVal ValueAs Double ) _hue = CheckRange(Value / scale)End Set End Property Public Property Saturation()As Double Get Return _saturation * scaleEnd Get Set (ByVal ValueAs Double ) _saturation = CheckRange(Value / scale)End Set End Property Public Property Luminosity()As Double Get Return _luminosity * scaleEnd Get Set (ByVal ValueAs Double ) _luminosity = CheckRange(Value / scale)End Set End Property Private Function CheckRange(ByVal valueAs Double )As Double If value < 0.0Then value = 0.0ElseIf value > 1.0Then value = 1.0End If Return valueEnd Function Public Overrides Function ToString()As String Return String .Format("H: {0:N2} S: {0:N1} L: {2:N2}", _ Hue, Saturation, Luminosity)End Function Public Function ToRGBString()As String Dim colorAs Color = CType(Me, Color)Return String .Format("R: {0:N2} G: {0:N1} B: {2:N2}", _ color.R, color.G, color.B)End Function Public Shared Widening Operator CType (ByVal HslColorAs HSLColor) _As ColorDim rAs Double = 0, gAs Double = 0, bAs Double = 0If HslColor.Luminosity <> 0Then If HslColor.Saturation = 0Then r = g = b = HslColor.LuminosityElse Dim temp2As Double = GetTemp2(HslColor)Dim temp1As Double = 2.0 * HslColor.Luminosity - temp2 r = GetColorComponent(temp1, temp2, _ HslColor.Hue + 1.0 / 3.0) g = GetColorComponent(temp1, temp2, HslColor.Hue) b = GetColorComponent(temp1, temp2, _ HslColor.Hue - 1.0 / 3.0)End If End If Return Color.FromArgb(255, (255 * r), (255 * g), (255 * b))End Operator 'Questa funzione l'ho aggiunta io Public Function ToColor()As ColorReturn CType(Me, Color)End Function Private Shared Function GetColorComponent(ByVal temp1As Double , _ByVal temp2As Double ,ByVal temp3As Double )As Double temp3 = MoveIntoRange(temp3)If temp3 < 1.0 / 6.0Then Return temp1 + (temp2 - temp1) * 6.0 * temp3ElseIf temp3 < 0.5Then Return temp2ElseIf temp3 < 2.0 / 3.0Then Return temp1 + ((temp2 - temp1) * ((2.0 / 3.0) - temp3) * 6.0)Else Return temp1End If End Function Private Shared Function MoveIntoRange(ByVal temp3As Double )As Double If temp3 < 0.0Then temp3 += 1.0ElseIf temp3 > 1.0Then temp3 -= 1.0End If Return temp3End Function Private Shared Function GetTemp2(ByVal HslColorAs HSLColor)As Double Dim temp2As Double If HslColor.Luminosity < 0.5Then temp2 = HslColor.Luminosity * (1.0 + HslColor.Saturation)Else temp2 = HslColor.Luminosity + HslColor.Saturation - _ (HslColor.Luminosity * HslColor.Saturation)End If Return temp2End Function Public Shared Widening Operator CType (ByVal colorAs Color) _As HSLColorDim hslColorAs HSLColor =New HSLColor() 'we store hue as 0-1 as opposed to 0-360 hslColor.Hue = color.GetHue() / 360.0 hslColor.Luminosity = color.GetBrightness() hslColor.Saturation = color.GetSaturation()Return hslColorEnd OperatorPublic Sub SetRGB(ByVal redAs Integer,ByVal greenAs Integer, _ByVal blueAs Integer)Dim hslColorAs HSLColor = _CType (Color.FromArgb(red, green, blue), HSLColor)Me .Hue = hslColor.HueMe .Saturation = hslColor.SaturationMe .Luminosity = hslColor.LuminosityEnd Sub Public Sub New ()End Sub Public Sub New (ByVal colorAs Color) SetRGB(color.R, color.G, color.B)End Sub Public Sub New (ByVal redAs Integer,ByVal greenAs Integer, _ByVal blueAs Integer) SetRGB(red, green, blue)End Sub Public Sub New (ByVal hueAs Double ,ByVal saturationAs Double , _ByVal luminosityAs Double )Me .Hue = hueMe .Saturation = saturationMe .Luminosity = luminosityEnd Sub End Class
Imports System.Drawing.Drawing2DPublic Class Form1 'Questa classe rappresenta la barra Class GlassBar 'Colore principale Private _ColorAs Color 'Area di spazio della barra Private _AreaAs RectanglePublic Property Color()As ColorGet Return _ColorEnd Get Set (ByVal valueAs Color) _Color = valueEnd Set End Property Public Property Area()As RectangleGet Return _AreaEnd Get Set (ByVal valueAs Rectangle) _Area = valueEnd Set End Property 'Procedura principale per disegnare Public Sub Draw(ByVal GAs Graphics) 'Sfumatura a tre colori: tonalità chiara, normale e chiara Dim BlendAs New ColorBlend(3) 'BlendBrush è il pennello che esegue sfumature lineari 'e tinteggerà lo sfondo passando per i tre colori di Blend Dim BlendBrushAs LinearGradientBrush 'MirrorBrush è il pennello che esegue campiture uniformi: 'creerà il riflesso rimpiendo un'area di bianco trasparente Dim MirrorBrushAs SolidBrush 'Questo è il colore della barra convertito in scala HSL Dim ColAs New HSLColor(Color) 'OutlinePen è la penna che disegnerà il contorno Dim OutlinePenAs Pen 'Per ottenere un colore più chiaro, aumentiamo la 'luminosità di 54. Siccome la classe è scritta per 'considerare valori Double da 0 a 1, usiamo la frazione 54/255 'perchè di solito le gradazioni hanno 256 varianti intermedie '(da 0 a 255) proprio come RGB. 'P.S. per i più solerti: avrete notato che la scala HSL 'è in 240esimi, ma non fa molta differenza. Potete usare 'benissimo 54/240 Col.Luminosity += 54 / 255 'Imposta i colori della sfumatura: Chiaro, Scuro, Chiaro. 'ToColor è una funzione che ho aggiunto io che converte 'un oggetto HslColor in un oggetto Drawing.Color normale '(ossia che segue le componenti RGB) Blend.Colors =New Color() {Col.ToColor, Color, Col.ToColor} 'Imposta le posizioni dei colori: all'inizio, a metà, 'alla fine Blend.Positions =New Single() {0, 0.5, 1} 'Crea il nuovo pennello: i colori passati nel costruttore sono 'assolutamente inutili in questo caso, poichè impostando la 'proprietà InterpolationColors obblighiamo il pennello 'ad usare la sfumatura di Blend BlendBrush =New LinearGradientBrush( _New Point(Area.X, Area.Y), _New Point(Area.X, Area.Y + Area.Height), _ Color.White, Color.Blue) BlendBrush.InterpolationColors = Blend 'Diminuisce la luminosità per avere un contorno più scuro Col.Luminosity -= 74 / 255 'Crea la nuova penna di colore scuro, e ampiezza 2pixel. OutlinePen =New Pen(Col.ToColor, 2) 'Crea il pennello per il riflesso. La funzione FromArgb 'restituisce un oggetto Color fornite in input se sue 'componenti Alhpa, Red, Green e Blue. Le ultime tre sono 'uguali e massime e costituiscono il Bianco puro. 'La prima è 90/255 e definisce una trasparenza 'abbastanza alta. MirrorBrush =New SolidBrush( _ Drawing.Color.FromArgb(90, 255, 255, 255)) 'Disegna tutto G.SmoothingMode = SmoothingMode.AntiAlias G.FillRectangle(BlendBrush, Area) G.FillRectangle(MirrorBrush, _New Rectangle(Area.X, Area.Y, Area.Width, Area.Height / 2)) G.DrawRectangle(OutlinePen, Area)End Sub End Class Private Sub Form1_Paint(ByVal senderAs Object, _ByVal eAs PaintEventArgs)Handles My Base.Paint 'Ecco alcuni esempi di glassbar con colori diversi Dim b1, b2, b3, b4As GlassBar b1 =New GlassBar b1.Color = Color.DarkRed b1.Area =New Rectangle(50, 50, 300, 40) b2 =New GlassBar b2.Color = Color.Green b2.Area =New Rectangle(50, 95, 300, 40) b3 =New GlassBar b3.Color = Color.Blue b3.Area =New Rectangle(50, 140, 300, 40) b4 =New GlassBar b4.Color = Color.Purple b4.Area =New Rectangle(50, 185, 300, 40) b1.draw(e.Graphics) b2.draw(e.Graphics) b3.draw(e.Graphics) b4.draw(e.Graphics)End Sub End Class
Risultato finale
The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.



