syscall/js包通过js.Global()返回一个js.Value类型的结构体,它指代JS中的全局对象。然后调用就类似于原来的javascript了,浏览器为window对象。通过Get()方法获取对象的字段。Invoke()方法可调用JS中的函数。
JS中的go.run()异步执行对应Go中的main()函数,此函数在整个生命周期不能返回,因为JS还需要调用。
在Web中画图
接上文,想实现在web中画图,修改go文件
package main
// 需要导入 syscall/js 包以调用 js API
import (
"math/rand"
"syscall/js"
"time"
)
const (
width = 400
height = 400
)
// 生成 0 - 1 的随机数
func getRandomNum() float32 {
rand.New(rand.NewSource(time.Now().UnixNano()))
n := float32(rand.Intn(10000))
return n / 10000.0
}
// 使用 canvas 绘制随机图
func draw() {
var canvas js.Value = js.
Global().
Get("document").
Call("getElementById", "canvas")
var context js.Value = canvas.Call("getContext", "2d")
// reset
canvas.Set("height", height)
canvas.Set("width", width)
context.Call("clearRect", 0, 0, width, height)
// 随机绘制 50 条直线
for i := 0; i < 50; i ++ {
context.Call("beginPath")
context.Call("moveTo", getRandomNum() * width, getRandomNum() * height)
context.Call("lineTo", getRandomNum() * width, getRandomNum() * height)
context.Call("stroke")
}
}
// 主程序入口
func main() {
println("wasm app works")
// bootstrap app
draw()
}
其它html和js文件就保持不变,访问页面时,将在浏览器中看到画的线条。
绑定点击事件,实现点击重新随机画图
package main
// 绘制随机图形
func draw() {
// ...
}
// 绑定点击事件
func addEventListener() {
// 回调中的操作将阻塞事件循环,需要明确地启动一个新的 goroutine
done := make(chan struct{})
var cb js.Callback = js.NewCallback(func(args []js.Value) {
go func() {
println("click")
draw()
}()
})
js.
Global().
Get("document").
Call("getElementById", "canvas").
Call("addEventListener", "click", cb)
<-done
}
// 启动应用
func bootstrapApp() {
draw()
addEventListener()
}
func main() {
println("wasm app works")
// bootstrap app
bootstrapApp()
}
在另一个网文中,关于DOM元素的获取(方法或许已过期,需要验证,我这里只是学习方法,阅读syscall/js后就能确定是否可用了)
package main
import (
"syscall/js"
)
func setDivRedColor(args []js.Value) {
// 获取DOM元素, 进行设置属性, call方法为调用js方法
js.Global().Get("document").Call("getElementById", "div").Set("style", "width: 300px; height: 300px; background-color: red")
// 注意, 此处设置style的时候, 是会覆盖掉html中的style设置
}
func main() {
js.Global().Set("setDivRedColor", js.NewCallback(setDivRedColor))
select {}
}