#E6E6E6 【VB 物件】FadeCircle 實現動態漸層圓圈 作者:吳文成

  我喜歡欣賞調和與充滿意象的色彩,在製作網站的藝術創作時,色彩的選取與搭配總是讓人煞費苦心,在苦心之後便是實現想像的欣慰感,例如在紀事的〈我是一棵秋天的樹〉便隱隱呈現光與影、色與相的疊和,沒有專門研究色彩學的我,似乎培養出專屬的色彩審美感。就在撰寫如何實現兩幅影像的疊加漸變的時候,我開始好奇不同色系的色彩要如何有層次地變化。色彩的最偉大解析就是十九世紀初的三原色說,混合紅、綠、藍三色光便可以得到各種不同的色彩,這讓程式撰寫者可以用三個分色的數值( 0∼255 之間 )來模擬所有色彩,例如黃色就是 Red=255、Green=255
、Blue=0 的派色結果 。另一個與 RGB 混色理論分庭抗禮的色彩數值解析系統,就是 HSB 色彩屬性理論,它將色彩分為色調(Hue,色相)、濃度( Saturation,飽和度,彩度,Colourfulness )與亮度(Brightness,明度)三個屬性,數值分別在 0∼359、0∼100 與 0∼100 之間。

  當 Saturation=100、Brightness=100,Hue=0∼359 之間的色彩變化,如[[img src=computer/ColorSpread.gif height=218 width=202 align=right]]旁圖上方的長彩條所示,而下方的塊區顯示的是,當 Hue=0(紅色)時,濃度與亮度的所有組合變化。三個屬性的搭配能夠讓我們模擬出全部的色彩,這樣我們便可以建立出 RGB 到 HSB 的轉換關係(注意,HSB 系統有許多數值組合是重複的色彩 , HSB 的另個等價的寫法是 HSV,V 指的是 Value)。這些是色彩定義的客觀數值,但是色彩之間搭配所形成的對比感、同化感、冷暖感,甚至是立體感,卻是主觀的,以下面的圖來看
,是屬於暖色系的樣式,但是到底有多「暖
[[img src=computer/FadeCircle1.gif height=218 width=218 align=left]]」是因人感受而異。這張圖是由我所撰寫的 FadeCircle 物件所演示的 ,此物件能夠動態地連續演示色彩的漸變,就像是自然調和而富有變化的漩渦流一般(我將執行檔與原始碼附在文末)

  我們要如何實現色彩的動態連續漸變呢?首先要選擇使用某一種色彩解析理論
, 較為簡單的 RGB 對我們來說就夠用了
。接下來的流程是這樣,隨機選擇一個起始顏色(假設位於中心處),然後向外建立一連續而隨機(怎麼做?)的色系分布,這就是靜態的初始色系,要讓它「動」起來,我們需要有一個計時器,按照時間間隔讓每一個「色圈」(聽起來春心蕩漾!)圓周向外(或向內)移動一個單位,這樣看起來就像是色塊[[img src=computer/FadeCircle2.gif height=218 width=218 align=right]]如漩渦般在移動。但是問題來了,總是要有新的顏色產生出來,才像是富有變化的漩渦流!如果每個色圈(眼睛又亮了)是向外移動,那麼新的顏色也要同時在最中心「冒」出來,這個新顏色也需要是連續而隨機的色彩。

  建立連續而隨機的色彩,作法是指定 Red 、 Green 與 Blue 三個分色個別漸變的方向( -1 或 +1 ),然後再隨機指定該變化的數值(變異度),如果紅色系要減少
,那麼新分色就是 Red=(原 Red) + (-1)*變異度,這樣,三個分色都隨機而連續的組合,就能夠產生富有變化並且分佈調和的新色彩。這是核心的原理,但是只要多花點心思、多些靈感,還可以有很多有意思的視覺效果,例如漸層方塊、潮浪式來回漸變,甚至漸變的方式可以轉為相應的 Midi 音符 , 這樣一來,動態色彩就會音樂化(這樣的靈感類似於所謂的碎形音樂,這是疊代幾何給予音樂化的例子),於是除了視覺的禮讚,還有聽覺的饗宴。

  寫文章的時候,我似乎習慣想到什麼就寫什麼,似乎與原主題無關,只是有許多的想法在腦袋裡激盪,就順手寫了出來。其實有很多創意是令人躍躍欲試而想要實現的;然而創意的靈感創意的實踐是兩種不同的能力、不同的價值,這兩種才能或是兩種人才的緊密溝通與合作,好的作品才能夠面世,如果有機會,我再另外談談創意與其知識基礎的話題。

  我只把 FadeCircle 物件較為關鍵的部分原始碼,給列舉在下面:

' Radius 是指動態漸層圓圈的半徑(像素),為選擇性參數
' DrawWidth 是指圓圈圓周的厚度(像素),為選擇性參數
'   表現為色彩塊的寬度
' VariationDegree 是指色彩漸變的變異度(像素),為選擇性參數
'   表現為色彩分布的複雜度
' DelayInterval 是漸層漸變的間隔時間(毫秒),為選擇性參數

Public Sub Initialize(DestObject As Object, Optional Radius As Long = 150, Optional DrawWidth As Integer = 2, Optional VariationDegree As Integer = 2, Optional ByVal DelayInterval As Long = 40)
 On Error GoTo errorLabel
 
 ' 賦值給所需的變數
  Set toObj = DestObject
  ' Radius 預設為 150,最低 10
  If Radius <= 0 Then Radius = 10
  ' DrawWidth 預設為 2,最低 2
  dwWidth = IIf(DrawWidth < 2, 2, DrawWidth)
  nSplit = Radius \ dwWidth - 1
  ' nSplit 即分割數至少為 1
  If nSplit < 1 Then nSplit = 1
  ReDim eachColor(nSplit)
  ' VariationDegree 預設為 2,最低 1
  m_VariationDegree = IIf(VariationDegree < 1, 1, VariationDegree)
 ' 設置控件 DestObject 的屬性值
 With DestObject
  .ScaleMode = vbPixels
  ' 圓圈圓周的厚度,加上被掩蓋的 Margin
  .DrawWidth = dwWidth + 1
 End With
 ' 動態新增控件,一個 Timer
 createTimer
 ' 設置漸變的時間間隔
  ' DelayInterval 預設為 40,最低 1
  tmrActive.Interval = IIf(DelayInterval < 1, 1, DelayInterval)
  tmrActive.Enabled = False
 ' 隨機設定動態漸層的起始色彩分布,共有 nSplit 個色彩塊
 ResetColorSpread
Exit Sub
errorLabel:
 Err.Raise 513, , "目的控制項不支援 FadeCircle 的功能"
End Sub

' 隨機設定色彩分布
Public Sub ResetColorSpread()
 Randomize Timer
 ' 隨機設置第一個色彩塊
 With eachColor(0)
 .Red = Int(Rnd * 256)
 .Green = Int(Rnd * 256)
 .Blue = Int(Rnd * 256)
 End With
 ' 隨機設置色彩各分色的漸變方向
 dirR = getDirection
 dirG = getDirection
 dirB = getDirection
 ' 依漸變方向,設置其餘的色彩塊
 Dim n As Integer
 For n = 1 To nSplit
  With eachColor(n)
  .Red = shiftColor(eachColor(n - 1).Red, dirR)
  .Green = shiftColor(eachColor(n - 1).Green, dirG)
  .Blue = shiftColor(eachColor(n - 1).Blue, dirB)
  End With
 Next n
 
 ' 繪製所有色彩塊
 drawCircle
End Sub

' 隨機產生 -1 或 +1 的任一數字
Private Function getDirection()
 Randomize Timer
 getDirection = Int(Rnd * 2) * 2 - 1
End Function

' 依漸變方向,傳回下一個色彩分色值
Private Function shiftColor(srcRGB As Integer, dirRGB As Integer) As Integer
 Randomize Timer
 
 shiftColor = srcRGB + (Int(Rnd * m_VariationDegree) + 1) * dirRGB
 If shiftColor > 255 Then shiftColor = 255: dirRGB = -dirRGB
 If shiftColor < 0 Then shiftColor = 0: dirRGB = -dirRGB
End Function

' 按照時間間隔執行動態漸層的色彩繪製
Private Sub tmrActive_Timer()
 Dim n As Integer
 ' 將分佈的色彩塊由內向外更替一次
 ' 除了第一個色彩塊之外

 For n = nSplit To 1 Step -1
  With eachColor(n)
  .Red = eachColor(n - 1).Red
  .Green = eachColor(n - 1).Green
  .Blue = eachColor(n - 1).Blue
  End With
 Next n
 ' 依漸變方向,設置第一個色彩塊
 With eachColor(0)
 .Red = shiftColor(.Red, dirR)
 .Green = shiftColor(.Green, dirG)
 .Blue = shiftColor(.Blue, dirB)
 End With
 
 ' 繪製所有色彩塊
 drawCircle
End Sub

' 繪製所有色彩塊
Private Sub drawCircle()
 Dim n As Integer
 For n = 0 To nSplit
  With eachColor(n)
  toObj.Circle (toObj.ScaleWidth / 2, toObj.ScaleHeight / 2), n * dwWidth, RGB(.Red, .Green, .Blue)
  End With
 Next n
End Sub

範例源碼下載
可執行檔下載
2004/10/14