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

栏目: IT技术 · 发布时间: 3年前

内容简介:这篇文章会讲下,如果通过Go来操作canvas,然后画一个类似腾讯文档表格一样的,在线的表格。当然,这肯定是个demo(你懂的)。然后,这篇文章主要会讲下面几个点:这里我们就直接上Go的代码了,如果有对Go如何编译成wasm或者其他的基础问题,可以查看这个系列的之前的几篇文章。前端js的代码:

这篇文章会讲下,如果通过 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。先看下效果,然后再来讲下代码:

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

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

在上面的代码中,我们定义了一个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的绘制原理不是特别了解,你应该会看不懂这两行代码在干什么。

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

使用Go开发前端应用(四)- 操作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对象等等。但是,我们在实际使用的时候,一定要知道,什么场景,使用什么样的技术来实现,能够得到最优的性能,这才是我们在实际的项目开发中,需要考虑的点。这篇文章大概就到这里,有任何问题,欢迎联系我,:pray:。

欢迎关注我们的微信公众号,每天学习Go知识

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

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Everything Store

The Everything Store

Brad Stone / Little, Brown and Company / 2013-10-22 / USD 28.00

The definitive story of Amazon.com, one of the most successful companies in the world, and of its driven, brilliant founder, Jeff Bezos. Amazon.com started off delivering books through the mail. Bu......一起来看看 《The Everything Store》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具