canvas有时候会出现1像素的线条模糊不清且好像更宽的状况,以下图:html
这样的线条显然不是咱们想要的。html5
这篇文章的目的就是弄清楚里面的原理,以及解决它。canvas
你们都知道屏幕上最小的显示尺寸就是1像素,虽然小于1像素的东西可能显示不出来,但计算机可无论,他会试着画一下。spa
其实像素终究来讲也是一个单位,假如咱们把画布放大到足够大,足以看清楚每一个像素,会是什么状况呢?大概是这个样子:code
每一个像素都有起止范围,如图所示,他们的范围从左起,跨过1像素,到右止。
若是咱们画1像素线条的时候,遵循像素的起止范围,那么咱们确定能获得一个很标准的细线。以下:htm
但遗憾的是canvas的线条画法不同,上一篇文章咱们已经说了,canvas的每条线都有一条无限细的“中线”,线条的宽度是从中线向两侧延伸的。若是咱们仍是从第2个像素点画一条线,那么线条的中线就会靠齐到第2个像素的起点,而后咱们开始画了,问题也就来了:Canvas 的线条以中线向两侧延伸,而不是向某一边延伸(好比这里,若是只是往右侧延伸,那么咱们的问题就再也不是问题了),延伸事后咱们的线条其实是这样的:blog
此时又有个问题:计算机不容许出现小于1px的图形,因此他作了一个折中的事:把这两个像素都绘制了。get
因此,如此一来,原本1px的线条,就成了看起来2px宽的线条。class
失败的缘由找到了:Canvas中的line把中线与像素的起点对齐了,而不是像素的中间点。变量
那么咱们怎么解决这个蛋疼的问题?也许有人已经想到了:既然是由于两个的起点不同,那咱们就把他们的起点变得同样吧!
咱们让线条的中线和像素的中间点对齐就好了!
像素的中间点很好找,好比第2像素的中间点,依据图上的解释就是1.5像素的位置,那么x像素的中间点就是(x-0.5)px。
固然,在不很严谨的场合,你使用x+0.5也是能够的。
如今咱们在canvas上试试咱们的研究结果和对比。
看起来对了吧?
不过貌似这样一来咱们画线的时候就很是纠结,难道每次都去加这个让人郁闷的0.5?固然不是,由于咱们大部分时间都是用变量保存值的,就不用给每一个值加0.5 了
并且,对于lineWidth>1 的线,咱们也不用管它:由于只有线条宽1px的时候,这个问题才最明显。
var cvs = document.getElementById("cvs"); cvs.width = 300; cvs.height = 500; var ctx = cvs.getContext('2d'); ctx.moveTo(30,10); ctx.lineTo(200,10); ctx.lineTo(200,100); ctx.lineTo(30,100); ctx.lineWidth = 1; ctx.strokeStyle = 'red'; ctx.closePath(); ctx.stroke(); ctx.beginPath(); ctx.moveTo(30.5,200.5); ctx.lineTo(200.5,200.5); ctx.lineTo(200.5,300.5); ctx.lineTo(30.5,300.5); ctx.lineWidth = 1; ctx.strokeStyle = 'red'; ctx.closePath(); ctx.stroke();