为什么我用HTML5 Canvas绘制的线条在画布右边缘透明度降低?
问题成因
这个现象的核心原因是Canvas 2D上下文的路径绘制机制,没有主动清空路径导致线条被重复叠加绘制:
- Canvas的
stroke()方法会绘制当前上下文中所有累积的路径,你在循环中没有调用beginPath()清空路径,每一轮循环都会不断往上下文里添加新的线条路径:- 最左侧的线条会被后续每一轮的
stroke()都绘制一次,累计被绘制146次 - 越靠右侧的线条被累计绘制的次数越少,最右侧的线条仅被绘制1次
- 最左侧的线条会被后续每一轮的
- Canvas默认线宽为1px,当线条坐标为整数值时,线条会落在两个物理像素的边界上,触发抗锯齿渲染呈现半透明效果,叠加次数越多的线条颜色越深,叠加次数越少颜色越淡,刚好对应你观察到的“越靠右颜色越浅”的现象。
修复方案
你只需要在每次绘制新线条前调用beginPath()清空当前路径即可,所有线条都会仅被绘制1次,颜色完全一致。
修改后的核心代码如下:
<!DOCTYPE html> <html> <head> <title>Bar Graph</title> <script> function draw() { inverterOutputCanvas = document.getElementById('inverter-output').getContext('2d'); inverterOutputCanvas.strokeStyle = '#0000FF'; for (let i=0; i<730; i+=5) { inverterOutputCanvas.beginPath(); // 新增这行清空当前路径 inverterOutputCanvas.moveTo(i+2, 100); inverterOutputCanvas.lineTo(i+2, Math.floor(Math.random()*100)); inverterOutputCanvas.stroke(); } } </script> </head> <body onload="draw();"> <canvas id="inverter-output" width="730" height="100" style="border: 1px solid lightgray;"></canvas> </body> </html>
如果想要进一步避免抗锯齿带来的半透明效果,你可以把x坐标调整为半整数,比如修改为i + 2.5,让1px宽的线条刚好落在单个物理像素范围内,颜色更纯净。
内容的提问来源于stack exchange,提问作者Dave H.
相关产品推荐
相关产品推荐

