html5画布中的图形:奇异且不受欢迎的光学效果

时间:2014-09-23 22:23:24

标签: javascript html5 canvas graphics artifacts

此程序运行。但是,尽可能地看到正方形翻转时有一个神器。必须表示矩阵值,并且还应根据角度看到该表示。有没有办法实现良好的可视化。为什么这会发生在我的代码中?

    var canvas=document.getElementById('canvas');
    var ctx=canvas.getContext('2d');

    var x=100;
    var y=100;
    var width=200;
    var height=200;
    var radianAngle=0;


    Rotar();


    var array = new Array2D(200,200);


    function Array2D(NumOfRows,NumOfCols)
    {
    var k=new Array(NumOfRows);
    for (i = 0; i < k.length; ++i)
    k[i] = new Array(NumOfCols);
    return k; 
    }

    function Rotar(){
    //Borramos 
    ctx.clearRect(0,0,canvas.width,canvas.height); 
    //Salvamos el estado
    ctx.save();
    // Transladamos su centro de gravedad
    ctx.translate(x+width/2,y+height/2); 
    //Otra mⳍ
    ctx.rotate(radianAngle);    



    var array = new Array2D(200,200);  
    for(i=0; i<200; i++)
    {
      for(j=0;j<200; j++)
      {
      array[i][j]=i+j;
      var r,g,b;
      r = array[i][j];
      g=50;
      b=50;
      //La parte de dibujo
      ctx.fillStyle = "rgba("+r+","+g+","+b+",100)";
      ctx.fillRect( i, j, 1, 1 ); 



     }
     }

  ctx.restore();    
      }

    $("#test").click(function(){

  radianAngle+=Math.PI/60;


  // call rotateSquare
  Rotar();
});
 body {
            background: #dddddd;
         }

         #canvas {
            background: #eeeeee;
            border: thin solid #aaaaaa;
         }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" height="500" width="500"></canvas>
<button id="test">Rotate</button><br>

Rotar();     });

1 个答案:

答案 0 :(得分:2)

这是一个典型的舍入问题:旋转上下文,然后在[0,199]中迭代(x,y)。但是在绘制小的一个像素宽的矩形时,它们将不能完美地适合一个像素,因此渲染器必须在几个真实设备像素上“漫射”颜色,并且由于r,g,b仅为圆形误差存储在8位。除此之外,微小矩形的坐标上的错误 - 最多可以在4个像素上进行栅格化,并且您拥有正在进行的网格。

进行此类转换时,规则是栅格化:迭代目标的像素并找到它们在源中的来源,而不是相反。
所以这是一个简单的方法:找到旋转的rect的边界框,在这个BBox中迭代,如果一个点在rect中计算它的颜色。
或者构建一个栅格化矩形的算法(最简单的方法是使用三角形,请参阅此处以获取我使用的三角形光栅化示例:http://jsfiddle.net/gamealchemist/5cnkr2s5/

但是......对于你在这里绘制的内容,最简单,更快捷的方法是构建线性渐变,将其用作fillStyle,并在单个fillRect调用中绘制整个矩形。换句话说:让画布(以及场景后面的GPU)为你做数学运算。

var grad = ctx.createLinearGradient(0,0,200,200);
grad.addColorStop(0,'#000');
grad.addColorStop(1,'#F00');
ctx.fillStyle = grad;

//
ctx.save();
ctx.clearRect( ... );
ctx.translate ( the upper left point) ;
ctx.rotate ( some angle );
ctx.fillRect(0, 0, 200, 200);
ctx.restore();

这里最简单的例子(点击'run'几次,角度随机化):

http://jsfiddle.net/gamealchemist/j57msxr5/11/

(Rq:你可以通过比较上面提到的三角形光栅化与context2D完成的相同工作来了解使用context2D的速度:http://jsfiddle.net/gamealchemist/zch3gdrx/