解决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
CSS#vs {
background-color: rgb(17, 17, 17);
width: 300px;
height: 300px;
}
JSconst 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