結(jié)合之前文章中的例子莺治,我們這次來用代碼繪制一個圖形耕漱,然后顯示在用Sciter制作的GUI圖形界面中,并且讓它自動旋轉(zhuǎn)羊异。
下面的例子中的信息量很大,除了之前的使用gg包進行代碼繪圖彤断,還演示了純用Gox代碼來操控HTML中的DOM元素(完全不使用Sciter中的TiScript)野舶,包括手動創(chuàng)建元素、選擇元素和設(shè)置其屬性等宰衙,并通過修改圖片標簽的transform樣式屬性平道,結(jié)合Go語言中的協(xié)程(類似線程)實現(xiàn)圖形不斷旋轉(zhuǎn)的效果。
先來看看最終實現(xiàn)的效果:
準備要做的界面就是這樣的供炼,簡簡單單巢掺,最上面是一個div,其中一個span顯示紅字劲蜻,下面就是一個img標簽裝載的圖形陆淀。程序運行后,圖形將以中心為軸每個1秒中順時針旋轉(zhuǎn)45度先嬉。
下面就是實現(xiàn)該效果的完整代碼:
// 設(shè)置image/color包的簡稱
// github.com/fogleman/gg包已經(jīng)默認簡稱gg
color = image_color
// 建立imagetk包的引用轧苫,注意該包的用法比較特殊
itk = imagetk.NewImageTK()
// 建立一個繪圖環(huán)境,圖片大小為 600×400 像素
contextT = gg.NewContext(600, 400)
// 用十六進制方式設(shè)置當(dāng)前顏色
contextT.SetHexColor("FFFFFF")
// 用當(dāng)前顏色來清空整個圖片
contextT.Clear()
// 設(shè)置線寬為 2 個像素
contextT.SetLineWidth(2)
// 設(shè)置RGB顏色疫蔓,每種顏色的數(shù)值范圍是 0.0 - 1.0
contextT.SetRGB(0.0, 0.0, 1.0)
// 畫一個圓含懊,以坐標為 (200, 200) 的點為圓心,半徑為 50像素
contextT.DrawCircle(250, 250, 60)
// 真正進行線條繪制衅胀,并且保留繪圖路徑以便后面填充顏色
contextT.StrokePreserve()
// 創(chuàng)建一個漸變色填充方案 gradientT
// 是兩點之間的圓環(huán)式漸變色
gradientT = gg.NewRadialGradient(250, 250, 0, 250, 250, 80)
// 創(chuàng)建一個顏色的基本方法
colorT = new(color.RGBA)
colorT.R = uint8(0)
colorT.G = uint8(0)
colorT.B = uint8(0)
colorT.A = uint8(255)
gradientT.AddColorStop(0, colorT)
// 注意創(chuàng)建顏色的快捷方法
gradientT.AddColorStop(1, itk.NewRGBA(0, 0, 255, 255))
// 設(shè)置用漸變色 gradientT 填充
contextT.SetFillStyle(gradientT)
// 真正進行填充岔乔,并清除繪畫路徑,因為后面已經(jīng)不需要了
contextT.Fill()
// 開始用填充的方式繪制一個矩形
// 用RGBA色彩體系設(shè)置當(dāng)前顏色
// 用 0 - 255 的數(shù)值范圍表示顏色和透明度
// 設(shè)置一定的透明度以便顯示出被覆蓋住的圖形(圓形)
contextT.SetRGBA255(0, 255, 0, 180)
// 繪制一個左上角點坐標為 (300, 200)滚躯,寬 100雏门,高 100的矩形
contextT.DrawRectangle(300, 200, 100, 100)
// 僅填充顏色不繪制邊線
contextT.Fill()
// 開始用路徑法畫一個三角形
// 用十六進制字符串設(shè)置顏色
// 可以加上前面的“#”號嘿歌,也可以后面加上一個字節(jié)表示透明度
contextT.SetHexColor("#FF000099")
// 將虛擬的畫筆移動到坐標為 (300, 120) 的點
contextT.MoveTo(300, 120)
// 從當(dāng)前點繪制一條線到坐標為 (240, 230)的點為止
// 當(dāng)前點將隨之移動到 (240, 230)
contextT.LineTo(240, 230)
// 繼續(xù)繪制一條直線到 (360, 230)
contextT.LineTo(360, 230)
// 繼續(xù)繪制一條直線到 (300, 120)
contextT.LineTo(300, 120)
// 創(chuàng)建一個新的線性漸變色
gradientT = gg.NewLinearGradient(240, 120, 360, 230)
// 注意從16進制數(shù)字創(chuàng)建顏色的方法
gradientT.AddColorStop(0, itk.NewRGBAFromHex("#00FF00FF"))
gradientT.AddColorStop(1, itk.NewRGBAFromHex("0000FFFF"))
gradientT.AddColorStop(0.5, itk.NewRGBAFromHex("FF0000"))
// 漸變色也可以用于線條顏色的漸變
contextT.SetStrokeStyle(gradientT)
// 設(shè)置粗一點的線寬以體現(xiàn)漸變色
contextT.SetLineWidth(10)
// 真正繪制三角形
contextT.Stroke()
// 從gg的畫布獲取Go語言中的image.Image對象
// 注意 := 和 = 作為賦值用,在Gox語言中是等價的
img := contextT.Image()
// 創(chuàng)建一個字節(jié)緩沖區(qū)茁影,用于存放圖片的二進制數(shù)據(jù)
bufT = new(bytes.Buffer)
// 將生成的圖片以PNG格式編碼到緩沖區(qū)中
image_png.Encode(bufT, img)
// 獲取字節(jié)緩沖區(qū)的字節(jié)數(shù)組([]byte)類型引用
dataT = bufT.Bytes()
// 設(shè)置github.com/sciter-sdk/go-sciter及其子包window的簡稱
sciter = github_scitersdk_gosciter
window = github_scitersdk_gosciter_window
// 將圖片的字節(jié)數(shù)組數(shù)據(jù)轉(zhuǎn)換為BASE64編碼的字符串
base64StrT := tk.EncodeToBase64(dataT)
// 設(shè)置Sciter格式的HTML網(wǎng)頁字符串
// 此處非常簡單宙帝,就是一個網(wǎng)頁框架
// 后續(xù)DOM操作將由Gox代碼來進行
// 注意,為了正確在Sciter中顯示中文募闲,最好加上兩種meta定義utf-8編碼
htmlT := `
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
</body>
</html>
`
// 鎖定GUI線程步脓,理論上GUI編程都要求在同一線程中更新界面元素
runtime.LockOSThread()
// 創(chuàng)建Sciter窗口,并指定窗口區(qū)域位置及大小
w, err := window.New(sciter.DefaultWindowCreateFlag, sciter.NewRect(0, 0, 800, 600))
checkError(err)
// 設(shè)置該窗口的一些屬性
w.SetOption(sciter.SCITER_SET_SCRIPT_RUNTIME_FEATURES, sciter.ALLOW_FILE_IO | sciter.ALLOW_SOCKET_IO | sciter.ALLOW_EVAL | sciter.ALLOW_SYSINFO)
// 載入HTML頁面框架
// 第二個參數(shù)是基URL(base url)浩螺,我們一般不用
w.LoadHtml(htmlT, "")
// 設(shè)置窗口標題靴患,注意是中文的
w.SetTitle("圖片轉(zhuǎn)向")
// 獲取Sciter頁面的根元素
rootT, _ := w.GetRootElement()
// 獲取body元素
bodyT, _ := rootT.SelectFirst("body")
// 創(chuàng)建一個div,其中文本為空(第二個參數(shù))
divT, _ := sciter.CreateElement("div", "")
// 在body元素中插入div要出,第二個參數(shù)是插入的位置
_ := bodyT.Insert(divT, 0)
// 設(shè)置div的innerHTML
// 第二個標志SIH_REPLACE_CONTENT表示替換innerHTML的全部
// 還有可用的標志位有SIH_INSERT_AT_START蚁廓、SIH_APPEND_AFTER_LAST
// SOH_REPLACE、SOH_INSERT_BEFORE厨幻、SOH_INSERT_AFTER相嵌,看名字即可知道大意
divT.SetHtml(`<span id="titleTextID">演示圖片</span>`, sciter.SIH_REPLACE_CONTENT)
// 設(shè)置div的id屬性
divT.SetAttr("id", "mainDivID")
// 設(shè)置div的style屬性(即CSS)
divT.SetStyle("margin-bottom", "10px")
// 獲取我們之前定義的span標簽
// 這是在設(shè)置div的HTML中用文本定義的
// 注意選擇器的快捷寫法
spanT, _ := bodyT.SelectFirst("span#titleTextID")
// 設(shè)置文字顏色為紅色
spanT.SetStyle("color", "#ff0000")
// 再創(chuàng)建一個img元素準備裝載圖片
imgT, _ := sciter.CreateElement("img", "")
// 在body中插入元素,序號為1况脆,也就是第二個元素饭宾,即在前面的div之后
_ := bodyT.Insert(imgT, 1)
// 設(shè)置該元素的src屬性為BASE64格式的圖片
imgT.SetAttr("src", `data:image/png;base64,`+base64StrT)
// 設(shè)置圖片初始的旋轉(zhuǎn)角度為0,即不旋轉(zhuǎn)
imgT.SetStyle("transform", "rotate(0deg)")
// 設(shè)置旋轉(zhuǎn)的旋轉(zhuǎn)軸為圖片中心點
imgT.SetStyle("transform-origin", "50% 50%")
// 輸出目前的根節(jié)點的HTML文本以供參考
// 第二個參數(shù)為true表示是outerHTML格了,否則是innerHTML
plv(rootT.Html(true))
// 啟動一個goroutine協(xié)程看铆,負責(zé)圖片旋轉(zhuǎn)
// 由于后面的w.Run是阻塞的,所以必須要用線程來處理旋轉(zhuǎn)
// 旋轉(zhuǎn)的方法是不斷修改img元素的transform樣式的角度值
// 每次順時針旋轉(zhuǎn)45度
go func() {
angleT := 0
for i= 0; i< 20; i ++ {
// 旋轉(zhuǎn)20次盛末,每次間隔1秒
tk.SleepSeconds(1)
angleT += 45
imgT.SetStyle("transform", fmt.Sprintf("rotate(%ddeg)", angleT))
}
}()
// 顯示窗口并運行GUI圖形界面
w.Show()
w.Run()
代碼中依然有非常詳盡的注釋弹惦,實現(xiàn)思路也非常清晰。附加幾點說明:
- 為代碼清晰悄但,一些異常情況還是沒有處理棠隐;
- 輸出的結(jié)果HTML中,一些屬性可能會沒有檐嚣;
- 旋轉(zhuǎn)為20次助泽,通過循環(huán)控制,可以設(shè)置成無限
- 注意嚎京,Gox制作的圖形界面程序嗡贺,如果Windows上不想出現(xiàn)CMD的黑框,可以下載Goxg版本鞍帝,或者在自行編譯時诫睬,加上ldflags="-H windowsgui"參數(shù)。
注意:
Gox語言是脫胎于Go語言(Golang)的開源腳本語言帕涌,解釋執(zhí)行摄凡,但相比Go語言更貼近高級語言续徽,語法硬性限制也少一些;是一門偏向快速應(yīng)用的語言架谎,也可以說是一個集成工具;
-
Gox語言主要優(yōu)勢有三點:
- 第一辟躏,Gox語言本身只有一個可執(zhí)行文件谷扣,綠色免配置,下載即可使用捎琐,無需安裝Go語言環(huán)境会涎,無需編譯,非常適合快速制作原型以及云服務(wù)器上的遠程開發(fā)瑞凑;
- 第二末秃,Gox中可以直接使用絕大多數(shù)Go語言標準庫中的對象和方法函數(shù),也內(nèi)置了很多常用籽御、優(yōu)秀的第三方庫练慕,充分發(fā)揮Go語言多年積累的資源優(yōu)勢;
- 第三技掏,與很多其他主流語言不同铃将,Gox語言著力解決了GUI圖形界面編程的問題,內(nèi)置了基于Giu(imgui)哑梳、LCL劲阎、Sciter的三套圖形界面編程庫,直接可以進行快捷高效的圖形界面開發(fā)(LCL鸠真、Sciter只需分別下載一個動態(tài)鏈接庫文件悯仙,執(zhí)行和分發(fā)時附帶上即可),特別適合編寫演示原型系統(tǒng)吠卷。
作為腳本語言锡垄,Gox語言性能肯定不如Go語言這樣的編譯型語言快,但由于Gox語言與Go語言的緊密聯(lián)系祭隔,Gox語言編寫的腳本可以很容易的改寫成Go語言代碼偎捎,編譯執(zhí)行后就可以發(fā)揮Go語言的速度優(yōu)勢了。因此序攘,Gox語言也比較適合做初期的Go語言調(diào)試茴她,還有一個更直接的方式是使用Gotx(在Gox官網(wǎng)上也有下載),這是使用完全和Go語言一樣語法的解釋器程奠,可以理解成集成了Go語言標準庫和不少第三方庫的解釋執(zhí)行的Go語言丈牢,一樣也不需要搭建Go語言環(huán)境。Gotx與Gox的區(qū)別在于瞄沙,Gotx仍然遵循Go語言的文法己沛,代碼相對復(fù)雜一些慌核,限制也多一些,但改寫回Go語言準備編譯執(zhí)行時申尼,基本上沒有成本垮卓。
Gox的官網(wǎng)在這里,也可以在瀏覽器搜索引擎中直接搜索“gox語言”师幕,Github頁面在這里粟按,在這里可以看到很多Gox語言的學(xué)習(xí)指南和實際應(yīng)用實例。