代码之家  ›  专栏  ›  技术社区  ›  Musixauce3000

使用“ImageData”数据数组设置动画会导致非常意外和类似故障的结果

  •  0
  • Musixauce3000  · 技术社区  · 6 年前

    我最近使用 ImageData 数据阵列;就是那个 ctx.getImageData() ctx.putImageData() 方法,并对我自己说,“这可能是一个非常有效的方式来动画画布上的移动物体充满”。所以我把它和 requestAnimationFrame(callback) 声明,但那是事情变得奇怪的时候。我所能做的最好的描述就是说画布上最左边的一列像素在最右边的一列像素中被复制,这是基于你为画布指定的坐标 get put ctx 方法,这可能会产生奇怪的后果。

    0, 0 像这样:

    imageData = ctx.getImageData( 0, 0, cvs.width, cvs.height );
    
    //  here I set the pixel colors according to their location
    //  on the canvas using nested for loops to target the
    //  the correct imageData array indexes.
    
    ctx.putImageData( imageData, 0, 0 );
    

    enter image description here

    ImageData坐标来获得绘制的图像和画布边缘之间的一些空间,我改变了 得到

    imageData = ctx.getImageData( 1, 1, cvs.width, cvs.height );
    
    for ( var x = 0; x < cvs.width - 92; x++ ) {
        for ( var y = 0; y < cvs.height - 92; y++ ) {
            // array[ x + y * width ] = value / x; // or similar
        }
    }
    
    ctx.putImageData( imageData, 2, 2 );
    

    enter image description here

    漂亮!但错了。。。所以我把它复制了出来 codepen . 有人能帮我理解和克服这种行为吗?

    注意:代码笔具有缩小的绘图区域。如果你改变主意 得到 得到 最有趣的行为是零。

    1 回复  |  直到 6 年前
        1
  •  0
  •   enxaneta    6 年前

    我把你的密码改了一点。在你的双循环中,我声明了一个变量 var i = (x + y*cvs.width)*4; 这只是减少了代码的冗长,以便我能更好地看到它。i变量表示imageData.data数组中像素的索引。既然你在做

            imageData.data[i - 4 ] ...
            imageData.data[i - 3 ] ...
            imageData.data[i - 2 ] ...
            imageData.data[i - 1 ] ...
    

    变量i=(x+y*cvs.width)*4; var i = 4 + (x + y*cvs.width)*4; . 当你设置它的动画,因为 imageData 是在 test() 函数的基础上重新计算imageData.data数组的值。所以在第二帧中,你将第一帧的1px线再次复制,并向上移动1px,向左移动1px。

    我希望这是你问的。

    var ctx, cvs, imageData;
    	cvs = document.getElementById('canv');
    	ctx = cvs.getContext('2d');
    
    function test() {
    	
    	// imageData = ctx.getImageData( 0, 0, cvs.width, cvs.height );
    	  // produces a line on the right side of the screen
    	
    	imageData = ctx.getImageData( 1, 1, cvs.width, cvs.height );
    	  // bizzar reverse cascading
    	
    	for (var x=0;x<cvs.width-92;x++) {
    		for (var y=0;y<cvs.height-92;y++) {
    			var i = 4+(x + y*cvs.width)*4;
    			imageData.data[i - 4 ] = Math.floor((255-y)-Math.floor(x/55)*55);
    			imageData.data[i - 3 ] = Math.floor(255/(cvs.height-92)*y);
    			imageData.data[i - 2 ] = Math.floor(255/(cvs.width-92)*x);
    			imageData.data[i - 1 ] = 255;
    		}
    	}
    	
    	ctx.putImageData( imageData, 0, 0 );
    	
    	requestAnimationFrame( test );
    	
    }
    
    test();
    canvas {
    	box-shadow: 0 0 2.5px 0 black;
    }
    <canvas id="canv" height="256" width="256"></canvas>