Canvas中ctx.lineTo绘制线段长度异常:设120px却画出160px
Canvas绘制线段长度与预期不符的问题解决
问题根源
你遇到的问题核心在于Canvas元素的绘图缓冲区尺寸与CSS显示尺寸不匹配。
Canvas存在两个独立的尺寸属性:
- 绘图缓冲区尺寸:由HTML标签的
width和height属性控制,这是Canvas内部用于绘制图形的实际像素画布,默认值为300px(宽)×150px(高)。 - CSS显示尺寸:由CSS的
width和height属性控制,是Canvas在页面上呈现的视觉尺寸。
当这两个尺寸不一致时,浏览器会自动将绘图缓冲区的内容拉伸/压缩到CSS设置的显示尺寸,导致绘制的图形比例失真。你仅设置了CSS的480px×240px,但未指定Canvas的绘图缓冲区尺寸,默认的300×150画布被拉伸到480×240,缩放比例为480/300=1.6,代码中Y轴的120px会被放大为120×1.6=192px(你测量的160px可能存在测量误差或环境差异,但核心原因是尺寸不匹配)。
解决方案
1. 直接设置Canvas的HTML属性尺寸与CSS一致
修改HTML中的Canvas标签,添加width和height属性,使其值与CSS显示尺寸完全匹配:
<canvas id="canvas" width="480" height="240"></canvas>
这种方式让绘图缓冲区和显示尺寸完全对齐,绘制的坐标会直接对应页面上的实际像素,不会出现缩放失真。
2. 动态适配高DPI屏幕(可选)
如果需要适配高分辨率屏幕,可通过JavaScript动态设置缓冲区尺寸并调整缩放比例:
let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); // 获取CSS计算出的显示尺寸 const displayWidth = canvas.clientWidth; const displayHeight = canvas.clientHeight; // 适配设备像素比,避免高DPI屏幕下图形模糊 const dpr = window.devicePixelRatio || 1; canvas.width = displayWidth * dpr; canvas.height = displayHeight * dpr; ctx.scale(dpr, dpr); // 后续正常绘制逻辑 ctx.lineWidth = 4; ctx.strokeStyle = "#000"; ctx.beginPath(); ctx.moveTo(120, 0); ctx.lineTo(120, 120); ctx.stroke();
完整可运行代码示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> * { margin: 0; padding: 0; } canvas { border: 1px solid #d0d0d0; justify-content: center; vertical-align: middle; width: 480px; height: 240px; position: absolute; top: 50%; left: 50%; margin-top: -120px; margin-left: -240px; } </style> </head> <body> <canvas id="canvas" width="480" height="240"></canvas> <script> let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); ctx.lineWidth = 4; ctx.strokeStyle = "#000"; ctx.beginPath(); ctx.moveTo(120, 0); ctx.lineTo(120, 120); ctx.stroke(); </script> </body> </html>
内容的提问来源于stack exchange,提问作者Tzury Bar Yochay
相关产品推荐
相关产品推荐

