以下代码(jsFiddle)在画布上的随机点处绘制一个红色正方形,注意擦除前一个(通过在其上用ctx.fillRect()填充一个白色正方形):

<html>
  <canvas id='canvas' width=300 height=300/>
 <script>
   const ctx = document.getElementById('canvas').getContext('2d');
   let prevRect = null;
   for (let i = 0 ; i < 10; i++) {
     if (prevRect != null) {
       ctx.fillStyle='white';
       ctx.fillRect(prevRect.x, prevRect.y, 50, 50);
     }
     ctx.fillStyle='red';
     const newRect = {x: Math.random()*(300-50), y: Math.random()*(300-50)};
     ctx.fillRect(newRect.x, newRect.y, 50, 50);
     prevRect = newRect;
   }
  </script>
</html>


该代码无法完全擦除先前的正方形,并且工件残留在屏幕上。相反,如果执行以下操作:

const newRect = {x: Math.floor(Math.random()*(300-50)), y: Math.floor(Math.random()*(300-50))};


...然后一切都会按预期进行。

我的问题是为什么。似乎完全没有必要在将值保留在prevRect中时截断,以使对fillRect()的两个调用使用完全相同的坐标(即使使用浮点数),因此两个正方形应始终完全对齐。

最佳答案

问题源于在画布上绘制事物的基本方式。绘制正方形时,形状的边缘会稍微“羽化”。因此,当您在前一个红色框上绘制白色框时,红色的残余会渗入半透明边缘。

如果您画10个白盒子而不是一个,那么问题就消失了。或者,如果使白框的尺寸可能大0.5像素,则可能会有帮助。



const ctx = document.getElementById('canvas').getContext('2d');
   let prevRect = null;
   for (let i = 0 ; i < 10; i++) {
     if (prevRect != null) {
       ctx.fillStyle='white';
       ctx.fillRect(prevRect.x - 0.75, prevRect.y - 0.75, 51.5, 51.5);
     }
     ctx.fillStyle='red';
     const newRect = {x: Math.random()*(300-50), y: Math.random()*(300-50)};
     ctx.fillRect(newRect.x, newRect.y, 50, 50);
     prevRect = newRect;
   }

body, html { padding: 0; }

canvas { border: 1px solid black; }

<canvas id=canvas height=300 width=300></canvas>





看起来每边都大0.75,效果很好,但是可以肯定,这是画布“逻辑”大小与实际屏幕大小的函数。

关于javascript - 使用浮点数时,fillRect()不完全重叠,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58136632/

10-16 13:34