分享
  1. 首页
  2. 文章

使用Go开发前端应用(四)- 操作canvas绘制一个表格

zhongzhong05 · · 3358 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前言

这篇文章会讲下,如果通过Go来操作canvas,然后画一个类似腾讯文档表格一样的,在线的表格。当然,这肯定是个demo(你懂的)。然后,这篇文章主要会讲下面几个点:

  • 使用Go来操作canvas绘制表格
  • 使用js来操作canvas绘制表格
  • 性能问题

使用Go操作canvas绘制表格

这里我们就直接上Go的代码了,如果有对Go如何编译成wasm或者其他的基础问题,可以查看这个系列的之前的几篇文章。

package main
import (
	"fmt"
	"syscall/js"
	"time"
)
var drawCtx js.Value
var window js.Value
func init() {
	window = js.Global()
	doc := window.Get("document")
	body := doc.Get("body")
	canvas := doc.Call("createElement", "canvas")
	canvas.Set("height", window.Get("innerHeight"))
	canvas.Set("width", window.Get("innerWidth"))
	body.Call("appendChild", canvas)
	drawCtx = canvas.Call("getContext", "2d")
}
func drawTable() {
	width := window.Get("innerWidth").Int()
	height := window.Get("innerHeight").Int()
	// 绘制之前清空下画布
	drawCtx.Call("clearRect", 0, 0, width, height)
	// 单元格的宽高
	cellHeight := 22
	cellWidth := 120
	drawCtx.Set("strokeStyle", "#dcdcdc")
	drawCtx.Set("lineWidth", 1)
	drawCtx.Call("translate", -0.5, -0.5)
	drawCtx.Call("beginPath")
	// 划竖线
	for i := 0; i < width; i = i + cellWidth {
		drawCtx.Call("moveTo", i, 0)
		drawCtx.Call("lineTo", i, height)
		drawCtx.Call("stroke")
	}
	// 划横线
	for j := 0; j < height; j = j + cellHeight {
		drawCtx.Call("moveTo", 0, j)
		drawCtx.Call("lineTo", width, j)
	}
	drawCtx.Call("stroke")
	drawCtx.Call("translate", 0.5, 0.5)
}
func main() {
	drawTable()
	// 阻止go程序退出,因为退出了,js端就不能再调用了
	signal := make(chan int)
	<-signal
}
复制代码

前端js的代码:

const go = new Go()
WebAssembly.instantiateStreaming(fetch('main.wasm'), go.importObject)
 .then(async result => {
 go.run(result.instance);
 });
复制代码

上面就是一个平平无奇的使用Go绘制一个二维表格的demo。先看下效果,然后再来讲下代码:

效果就是上面这个样子,看起来跟腾讯文档表格还是挺像的,对不对?

在上面的代码中,我们定义了一个init函数和一个drawTable函数,你可能已经发现了,代码里面,其他任何地方都没有调用init函数,为什么可以正常运行?drawCtx等对象正常初始化了。这是为啥呢?其实如果你熟悉Go的话,就知道,init方法,在每个包加载执行之前,会先执行该包下的init方法。这个是Go语言本身的特性,在我们这个例子中,那就是init方法,会比main方法先执行。这样你应该明白了对不对。

init函数代码说明

	drawCtx = canvas.Call("getContext", "2d")
复制代码

在初始化方法中,前面的几行代码,就是往页面中添加一个canvas的dom,然后获取到canvas对象。上面的一行代码最关键,通过canvas对象,获取了canvas的2d上下文对象,有了这个对象之后,我们才能够执行绘制的操作。

drawTable函数代码说明

 width := window.Get("innerWidth").Int()
 height := window.Get("innerHeight").Int()
复制代码

从截图可以看出,我们的表格是占满整个窗口的,所以我们需要先获取窗口的宽高。

 drawCtx.Call("translate", -0.5, -0.5)
 drawCtx.Call("translate", 0.5, 0.5)
复制代码

如果你对canvas的绘制原理不是特别了解,你应该会看不懂这两行代码在干什么。

来看下去掉这两行代码之后的效果:

对比上面的截图,你应该可以发现这两行是用来干嘛的了。

drawCtx.Call("beginPath")
// 划竖线
for i := 0; i < width; i = i + cellWidth {
	drawCtx.Call("moveTo", i, 0)
	drawCtx.Call("lineTo", i, height)
	drawCtx.Call("stroke")
}
// 划横线
for j := 0; j < height; j = j + cellHeight {
	drawCtx.Call("moveTo", 0, j)
	drawCtx.Call("lineTo", width, j)
}
drawCtx.Call("stroke")
复制代码

这里的代码,应该比较简单了,就是分别绘制表格的横线和竖线。应该很容易看懂了对不对。

main函数里面,只有调用了drawTable()函数,没有其他操作,就不说了。

上面大概就是使用Go来操作canvas绘制一个二维的表格了,不过非常简陋,实际项目中肯定不是这么搞的,但是用的东西就是上面这些。你懂我意思吧?

使用js来操作canvas绘制表格

因为后面要对比下,js和wasm的操作canvas的性能,所以,还是给一个js的代码:

let drawCtx ;
const width = window.innerWidth
const height = window.innerHeight
function init() {
 const canvas = document.createElement("canvas");
 canvas.width = width;
 canvas.height = height;
 document.body.appendChild(canvas);
 drawCtx = canvas.getContext("2d")
}
function drawTable() {
 // 绘制之前清空下画布
 drawCtx.clearRect(0, 0, width, height)
 // 单元格的宽高
 const cellHeight = 22
 const cellWidth = 120
 drawCtx.strokeStyle = "#dcdcdc";
 drawCtx.lineWidth = 1;
 drawCtx.translate(-0.5, -0.5)
 drawCtx.beginPath()
 // 划竖线
 for(let i = 0; i < width; i = i + cellWidth ){
 drawCtx.moveTo(i, 0)
 drawCtx.lineTo(i, height)
 drawCtx.stroke()
 }
 // 划横线
 for(let j = 0; j < height; j = j + cellHeight) {
 drawCtx.moveTo(0, j)
 drawCtx.lineTo(width, j)
 }
 drawCtx.stroke()
 drawCtx.translate(0.5, 0.5)
}
init();
// const s = Date.now();
// for (let i=0; i< 100000; i++) {
 drawTable();
// }
// console.log(Date.now() - s)
复制代码

代码跟上面的Go代码,一模一样,因为我就是从上面复制过来,改成js的。 js的代码,我这里就不说明了,你应该都可以看懂的,对不对?

性能问题

绘制1000次

wasm(Go):300ms左右

js: 24ms左右

绘制10000次

wasm(Go):2.7s左右

js: 180ms左右

可以看到,直接使用js来绘制canvas会比wasm要快很多。 这其实也说明一个问题,wasm它的使用场景,并不是让你来操作dom的,它是使用在特定场景下的,比如上篇文章中说的文件md5计算的场景,操作dom这种,我们还是按常规操作就行了。 上面的测试基于我的这个demo代码,然后在Chrome浏览器,iMac下的测试数据,如果有问题,欢迎联系我。

总结

上面的例子可以看出,使用Go可以操作前端的任何东西,包括dom,js对象等等。但是,我们在实际使用的时候,一定要知道,什么场景,使用什么样的技术来实现,能够得到最优的性能,这才是我们在实际的项目开发中,需要考虑的点。这篇文章大概就到这里,有任何问题,欢迎联系我,????。


有疑问加站长微信联系(非本文作者)

本文来自:掘金

感谢作者:zhongzhong05

查看原文:使用Go开发前端应用(四)- 操作canvas绘制一个表格

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3358 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏