Canvas绘制图形模糊的原因分析及锐化解决方法
解决Canvas绘制正方形模糊的问题
问题核心原因
你遇到的模糊问题主要来自三个点:
- Canvas的绘图缓冲区尺寸(
width/height属性)和页面显示尺寸未对齐,高DPI屏幕下浏览器会拉伸渲染导致模糊 - 奇数线宽的线条跨像素边界触发亚像素抗锯齿
- 未针对高DPI屏幕做适配
具体解决步骤
1. 适配高DPI屏幕,对齐缓冲区与显示尺寸
首先通过CSS设置Canvas的显示尺寸,然后根据设备像素比(devicePixelRatio)设置Canvas的实际绘图缓冲区尺寸,确保像素1:1映射:
#vs { background-color: rgb(17, 17, 17); /* 设置Canvas的显示尺寸 */ width: 300px; height: 300px; }
在JS中处理高DPI适配:
const vs = document.getElementById("vs"); const vs_ctx = vs.getContext("2d"); // 获取设备像素比 const dpr = window.devicePixelRatio || 1; // 获取Canvas的显示尺寸 const rect = vs.getBoundingClientRect(); // 设置Canvas的实际绘图缓冲区尺寸 vs.width = rect.width * dpr; vs.height = rect.height * dpr; // 缩放绘图上下文,确保绘制的内容适配高DPI vs_ctx.scale(dpr, dpr);
2. 避免亚像素绘制,对齐像素网格
当使用奇数线宽时,线条会居中在坐标上,跨像素边界导致模糊。可以通过偏移0.5像素,让线条完全落在像素网格上:
vs_ctx.strokeStyle = "purple"; vs_ctx.lineWidth = 3; // 偏移0.5像素,对齐像素网格 vs_ctx.strokeRect(50.5, 50.5, 20, 20);
如果用偶数线宽,直接使用整数坐标即可,不需要额外偏移。
3. 关闭图像平滑(可选)
如果仍有模糊感,可以关闭Canvas的图像平滑功能,强制锐化渲染:
vs_ctx.imageSmoothingEnabled = false;
修改后的完整代码
HTML
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>template</title> <link rel="stylesheet" href="css.css" /> </head> <body> <canvas id="vs"></canvas> <script type="module" src="main.js"></script> </body> </html>
CSS
#vs { background-color: rgb(17, 17, 17); width: 300px; height: 300px; }
JS
const vs = document.getElementById("vs"); const vs_ctx = vs.getContext("2d"); // 高DPI适配 const dpr = window.devicePixelRatio || 1; const rect = vs.getBoundingClientRect(); vs.width = rect.width * dpr; vs.height = rect.height * dpr; vs_ctx.scale(dpr, dpr); // 关闭图像平滑 vs_ctx.imageSmoothingEnabled = false; // 绘制对齐像素网格的正方形 vs_ctx.strokeStyle = "purple"; vs_ctx.lineWidth = 3; vs_ctx.strokeRect(50.5, 50.5, 20, 20);
内容的提问来源于stack exchange,提问作者23rfew
相关产品推荐
相关产品推荐

