为何Canvas中fillText绘制的文本应当显示却无法展示/直接消失?
问题根因
你的绘制顺序完全颠倒了:先绘制了文本,之后才调用fillRect填充当前网格的底色,直接把刚绘制完成的文本完全覆盖。
- 用减号计算
textY时,文本位置落到了上一行的网格区域,当前网格的fillRect不会覆盖到上一行的内容,因此文本可以显示但整体向上偏移一个网格的位置 - 用加号计算
textY时,文本刚好落在当前网格内部,绘制完文本后马上被后续的fillRect色块覆盖,因此完全不可见 - 长文本被截断的原因同理:超出当前网格范围的文本部分,会被相邻网格的
fillRect色块覆盖
解决方案
1. 调整绘制顺序
把网格填充、边框绘制的逻辑移到文本绘制之前,保证文本渲染在最上层不会被覆盖。同时优化重复解析JSON的性能问题,修改后代码如下:
import { mapColorsToNumbers } from "./mapColorToNumber"; export const drawGame = (pixelArt, ctx) => { // 提前解析一次像素数据,避免重复parse消耗性能 const pixelList = JSON.parse(pixelArt.pixels); const rectCount = pixelList.length; const canvasPixelsCount = pixelArt.pixelArtWidth * pixelArt.pixelArtHeight - 1000; const newRectSize = Math.sqrt(canvasPixelsCount / rectCount); const colorsWithCodes = mapColorsToNumbers(pixelList); pixelList.forEach((pixel) => { // 第一步:先填充网格底色 if (pixel.pickedColor !== "white") { ctx.fillStyle = "grey"; } else { ctx.fillStyle = "white"; } ctx.fillRect( pixel.x * newRectSize, pixel.y * newRectSize, newRectSize, newRectSize ); // 第二步:绘制网格边框 ctx.strokeStyle = "white"; ctx.strokeRect( pixel.x * newRectSize, pixel.y * newRectSize, newRectSize, newRectSize ); // 第三步:最后绘制文本,保证在最上层 ctx.fillStyle = "red"; // 动态设置字体大小,适配网格尺寸,避免文本溢出 ctx.font = `${Math.max(12, newRectSize * 0.6)}px serif`; ctx.textAlign = "center"; ctx.textBaseline = "middle"; const textX = pixel.x * newRectSize + newRectSize / 2; const textY = pixel.y * newRectSize + newRectSize / 2; ctx.fillText("1", textX, textY); }); };
2. 额外优化建议
如果还存在长文本溢出的情况,可以使用ctx.measureText()方法提前计算文本宽度,当文本宽度超过网格宽度时自动缩小字体,或者添加省略号处理。
内容的提问来源于stack exchange,提问作者GeraltDieSocke
相关产品推荐
相关产品推荐

