HTML Canvas 2D地图渲染优化:求高效合并同色相邻方块的算法
优化Canvas方块地图渲染:同色方块合并方案推荐
针对你提到的1080p下200个方块、30FPS需6000次绘制的性能问题,以及当前边缘追踪方法的复杂边缘情况,推荐几个更高效、易实现的同色方块合并方案:
1. 洪水填充+矩形合并法
这是最容易落地的方案,完全避开复杂的轮廓处理:
- 核心逻辑:遍历所有未标记的方块,用四连通/八连通洪水填充找出整个同色区域;对每个区域,按行扫描合并连续的同色方块段,再尝试将上下行的同段合并为竖矩形。
- 具体步骤:
- 用二维标记数组记录已处理的方块,避免重复计算。
- 遍历每个方块,若未标记且为目标颜色,启动洪水填充,收集该区域所有方块的坐标。
- 将收集到的坐标按行分组,每行内合并连续的列范围(比如行y中列2-5都是同色,就记为一个矩形
x:2, y:y, width:4, height:1)。 - 对比相邻行的同色矩形,若列范围完全重合且颜色一致,将它们合并为高度更大的矩形(比如把行y和y+1的2-5段合并成
height:2)。
- 优势:逻辑简单,边缘情况极少,生成的矩形可以直接用Canvas的
fillRect()绘制——这个API有硬件加速,性能远高于路径绘制,完美适配你的随机生成地图场景。
2. 逐行扫描线合并法
比洪水填充更省内存,适合大规模网格:
- 核心逻辑:逐行遍历网格,实时记录当前行的同色连续段,再与上一行的同色段对比,合并垂直方向连续的块。
- 具体步骤:
- 维护一个当前行的段列表,每个元素包含
起始列、结束列、颜色、起始行号。 - 处理当前行时,先扫描出所有同色连续段;然后和上一行的同色段逐一比对:如果两段的列范围重叠且颜色相同,就更新上一段的结束行号为当前行;如果不连续,就把上一段加入绘制队列,新建当前段。
- 遍历完所有行后,把最后一行的段加入绘制队列,统一用
fillRect()绘制。
- 维护一个当前行的段列表,每个元素包含
- 优势:不需要一次性存储整个连通区域的坐标,内存占用低,处理速度快,完全避免轮廓追踪的复杂逻辑。
3. Marching Squares轮廓提取法(如果需要矢量路径)
如果坚持要合并为单个矢量图形,用这个成熟算法替代手动轮廓追踪:
- 核心逻辑:遍历网格的内部边界(方块之间的缝隙),根据相邻方块的颜色差异,自动生成闭合的轮廓路径,内置处理边缘情况的逻辑。
- 具体步骤:
- 遍历每个方块的右边界和下边界(避免重复处理边界)。
- 对比当前方块和右侧/下方方块的颜色:如果颜色不同,就把这条边界线加入路径。
- 所有边界处理完成后,路径会自动形成闭合的同色区域轮廓,直接用Canvas的
beginPath()+lineTo()+fill()绘制。
- 优势:不需要手动顺时针追踪轮廓,算法本身会处理拐角、凹坑等边缘情况,生成的路径紧凑,适合需要矢量形状的场景。
额外优化小技巧
- 用
TypedArray(比如Uint8Array)存储网格颜色数据,比普通二维数组的访问速度更快,减少数据读取开销。 - 优先选择矩形合并方案:Canvas对
fillRect()的硬件加速优化远优于路径填充,能最大化提升渲染帧率。
内容的提问来源于stack exchange,提问作者Eejayy
相关产品推荐
相关产品推荐

