HTML Canvas绘制网格线条粗糊问题求助
解决Canvas网格线条过粗、模糊的问题
问题原因
你遇到的异常是两个问题叠加导致的:
- 线条对齐错误:Canvas绘制
lineWidth=1的线条时,若坐标为整数,线条中心会落在像素边界上,导致线条覆盖相邻两个像素并触发抗锯齿,看起来模糊且变粗(在DPR=2的屏幕上会显示为2物理像素)。 - 高DPI适配不完整:之前的适配代码仅调整了画布尺寸和上下文缩放,但未修正绘制坐标的偏移,无法解决线条对齐的根本问题。
解决方案
要实现1物理像素粗的清晰网格,需要同时处理高DPI适配和线条像素对齐:
修改后的完整JS代码
const canvas = document.getElementById('gridCanvas') as HTMLCanvasElement; const context = canvas.getContext('2d') as CanvasRenderingContext2D; const squareSize = 20; // CSS像素下的方格大小 const numRows = 10; const numCols = 15; const dpr = window.devicePixelRatio || 1; // 1. 设置Canvas的CSS尺寸(显示大小) canvas.style.width = `${numCols * squareSize}px`; canvas.style.height = `${numRows * squareSize}px`; // 2. 设置Canvas的实际像素尺寸(绘制缓冲区大小) canvas.width = numCols * squareSize * dpr; canvas.height = numRows * squareSize * dpr; // 3. 缩放绘图上下文,适配高DPI context.scale(dpr, dpr); // 修正:添加0.5px偏移,让线条对齐像素中心 const offset = 0.5; function drawGrid() { context.clearRect(0, 0, canvas.width / dpr, canvas.height / dpr); context.strokeStyle = 'black'; context.lineWidth = 1; // CSS像素下的线条宽度,对应1物理像素(dpr=2时实际是2设备像素) context.globalAlpha = 1.0; // 绘制水平线 for (let row = 0; row <= numRows; row++) { context.beginPath(); context.moveTo(offset, row * squareSize + offset); context.lineTo(numCols * squareSize + offset, row * squareSize + offset); context.stroke(); } // 绘制垂直线 for (let col = 0; col <= numCols; col++) { context.beginPath(); context.moveTo(col * squareSize + offset, offset); context.lineTo(col * squareSize + offset, numRows * squareSize + offset); context.stroke(); } } window.onload = drawGrid;
对应的HTML代码(无需修改,保持原结构即可)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Canvas Grid</title> <style> body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } </style> </head> <body> <canvas id="gridCanvas"></canvas> <script src="../dist/main.js"></script> </body> </html>
关键说明
- 像素对齐偏移:添加
0.5的偏移量,让线条的中心正好落在CSS像素的中心位置,避免抗锯齿导致的模糊。 - 高DPI适配:通过
dpr缩放画布尺寸和上下文,确保绘制的内容在高分辨率屏幕上显示清晰,lineWidth=1在CSS像素下对应1物理像素(设备像素为1*dpr)。 - 若仍有轻微模糊,可添加
context.imageSmoothingEnabled = false;关闭图像平滑,但对齐像素中心后通常不需要这一步。
内容的提问来源于stack exchange,提问作者DaraJ
相关产品推荐
相关产品推荐

