在图形系统中,如何实现图层管理?

图形渲染思路

图形渲染的核心思路是这样的:每个图层都对应一个独立的Canvas画布。在这些画布上,各自渲染图层中的数据。最后,根据图层的顺序,将这些图层合并成一个完整的图形。

当各个图层都渲染完成后,有两种方式可以将它们合并成完整的图形:ctx.drawImage()ctx.putImageData()。第一种方式通常具有更高的渲染效率,而第二种方式则可以对像素进行处理,实现更灵活的渲染效果。

1
2
1. ctx.drawImage()
2. ctx.putImageData()

图形渲染过程

图形渲染过程主要包括以下三个关键步骤:

  1. 计算矩阵:首先,根据图形的视点范围和当前显示的viewPort来计算矩阵变换参数。这是为了在图形合成时进行坐标转换做好准备。

  2. 合成图形:然后,逐个图层地将图层中的几何对象渲染到各自的图层Canvas中。

  3. 渲染图形:最后,将各个图层的Canvas合并到图形的Canvas中,并展示出来。

总结为四个用于发起图形渲染的API,分别是立即刷新、异步刷新、刷新图层和重绘图形。

  • 立即刷新:就是告诉主线程立即开始图形渲染。这通常在当前视点范围内的数据发生变化后使用。

  • 异步刷新:利用HTML的Window对象的RequestAnimalFrame特性,在窗口下一次刷新时执行图形渲染。这种方式非常通用,在图形窗口属性、图层属性或图形对象属性发生变化时都可以使用。这样做的好处是,无论调用多少次异步刷新命令,浏览器都只在下一次窗口刷新时执行一次图形渲染命令。

  • 重绘图层:仅重新绘制某一层,而其他层则使用上次渲染后留下的缓存图像。这在处理大数据量时可以提高图像渲染效率。例如,在图形的浮动层上绘制橡皮线或拉框时,只需要重新绘制这些元素,而不需要重新绘制整个图形内容。

  • 重绘图形:根据新的参数重新绘制整个图形。发出此命令后,anyGraph会重新获取各个图层中指定视点的数据,重新计算矩阵,进行坐标转换,并将这些数据重新绘制到各个图层中。最后,由GraphRenderer将图形合成为完整的图形并显示出来。

示例效果与源代码:

运行效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html>

<head>
<title>图形</title>
<meta charset="UTF-8">
</head>

<body style="overflow: hidden; margin:10px;">
<div id="wrap">
<div id="graphWrapper" style="position:absolute; width:100%; height:100%; border:solid 1px #CCC;"></div>
</div>
</body>
<script type="module">
import { Graph, Layer, VectorSource, debug } from "/examples/src/index.js";

// 初始化graph对象
let graph = new Graph({
"target": "graphWrapper",
"layers": [
new Layer({
"source": new VectorSource({
"fileUrl": "/examples/data/geom.json"
})
})
]
});

// 显示辅助网格
debug.generateGrid(Object.assign({ "interval": 10, "graph": graph }));

// 图形渲染
graph.render();
</script>

</html>

尝试一下 »