使用 (Tiny)GO 和 WebAssembly 创建开发者的离线页面 🦄💡✨
代码 代码 代码
开发者的离线页面很有趣,我们用 Rust 和 WebAssembly 实现了它。
Go语言很简单。我们能用Go和WebAssembly实现吗?答案是肯定的……
我这里有一个示例应用程序。如果您想从头开始编写,请查看此教程。
如果你只想查看源代码,请查看这个分支。
代码 代码 代码
go/main.go我们首先在.中导入“syscall/js”和“fmt” 。
“syscall/js”包在使用js/WASM架构时提供对WebAssembly宿主环境的访问。它的API基于JavaScript语义。此包处于实验阶段。🦄🦄
package main
import(
"fmt"
"syscall/js"
)
添加一些全局可用的变量,这些变量是我们可能需要在从 JavaScript 或浏览器调用函数时使用的变量。
var (
isPainting bool
x float64
y float64
ctx js.Value
color string
)
我们将手动在 . 中添加 canvas 元素out/index.html。
<canvas id="canvas"> </canvas>
删除函数Hello World内部的这行代码main,并替换为以下代码。
document从浏览器中获取对象。使用我们刚才添加的元素document。canvas
我们可以通过使用syscall/jsAPI来实现这一点。
func main() {
doc := js.Global().Get("document")
canvasEl := doc.Call("getElementById", "canvas")
}
API很简单。从JavaScript的全局命名空间获取文档。
在文档内部通过 ID 调用 canvas 元素。
我们将设置一些属性,例如canvasEl宽度、高度。我们还将获取画布的context。
bodyW := doc.Get("body").Get("clientWidth").Float()
bodyH := doc.Get("body").Get("clientHeight").Float()
canvasEl.Set("width", bodyW)
canvasEl.Set("height", bodyH)
ctx = canvasEl.Call("getContext", "2d")
然后我们将定义三个事件监听器mousedown| mousemove|mouseup到canvasElement。
鼠标向下
当我们点击鼠标时,绘画就开始了。
startPaint := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
e := args[0]
isPainting = true
x = e.Get("pageX").Float() - canvasEl.Get("offsetLeft").Float()
y = e.Get("pageY").Float() - canvasEl.Get("offsetTop").Float()
return nil
})
canvasEl.Call("addEventListener", "mousedown", startPaint)
请注意,返回 nil 非常重要,否则程序将无法编译。
整个 API 都是基于Reflect API 的。
鼠标移动
我们将定义绘制函数。
paint := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if isPainting {
e := args[0]
nx := e.Get("pageX").Float() - canvasEl.Get("offsetLeft").Float()
ny := e.Get("pageY").Float() - canvasEl.Get("offsetTop").Float()
ctx.Set("strokeStyle", color)
ctx.Set("lineJoin", "round")
ctx.Set("lineWidth", 5)
ctx.Call("beginPath")
ctx.Call("moveTo", nx, ny)
ctx.Call("lineTo", x, y)
ctx.Call("closePath")
// actually draw the path*
ctx.Call("stroke")
// Set x and y to our new coordinates*
x = nx
y = ny
}
return nil
})
canvasEl.Call("addEventListener", "mousemove", paint)
鼠标向上
最后,我们将定义当鼠标抬起事件触发时调用的退出方法。
exit := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
isPainting = false
return nil
})
canvasEl.Call("addEventListener", "mouseup", exit)
最后,我们将定义颜色选择器。在 `<head>` 标签中添加一个 `colors` div 元素out/index.html,并添加必要的 CSS 代码。
<style>
.color {
display: inline-block;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
margin: 10px;
}
</style>
<div id="colors></div>
我们将颜色定义为一个数组。然后遍历该数组中的颜色,并创建一个颜色样本节点。为该颜色样本添加一个点击事件监听器。
divEl := doc.Call("getElementById", "colors")
colors := [6]string {"#F4908E", "#F2F097", "#88B0DC", "#F7B5D1", "#53C4AF", "#FDE38C"}
for _, c := range colors {
node := doc.Call("createElement", "div")
node.Call("setAttribute","class", "color")
node.Call("setAttribute", "id", c)
node.Call("setAttribute","style", fmt.Sprintf("background-color: %s", c))
setColor := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
e := args[0]
color = e.Get("target").Get("id").String()
return nil;
})
node.Call("addEventListener", "click", setColor)
divEl.Call("appendChild", node)
}
就是这样。
现在运行以下命令启动 Web 服务器go run webServer.go。
使用以下方式将 Go 编译成 WebAssembly 模块
tinygo build -o ./out/main.wasm -target wasm -no-debug ./go/main.go
访问localhost:8080,即可看到超棒的画布,供您尽情发挥创意🦄。
💡 生成的WebAssembly模块只有52KB。TinyGo太棒了,它能生成体积小得惊人的 WebAssembly 二进制文件。它是如何做到的呢?敬请期待本系列的下一篇文章。💡
注意:请使用 Firefox 或 Firefox Nightly 版本。Chrome 浏览器有时会崩溃。
更多优化❤️
移除
fmt导入语句,替换fmt.Sprintf为普通的字符串拼接,这样可以再节省26KB 的空间。请在此处查看提交记录。
感谢Justin Clift分享这个小技巧 :)
你喜欢 Rust 吗?点击这里了解如何使用 Rust 开发 WebAssembly。
希望这篇文章能激励你开启精彩的 WebAssembly 之旅。如果你有任何问题、建议,或者觉得我遗漏了什么,欢迎留言。
你可以在推特上关注我。
如果你喜欢这篇文章,请点赞或留言。❤️
谢谢
文章内容。
文章来源:https://dev.to/sendilkumarn/create-dev-s-offline-page-with-tiny-go-and-web assembly-9n6