(原) Go与WebAssembly之二

原创文章,请后转载,并注明出处。

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 {}
}

相关文章