javascript - 动画 Canvas 看起来像电视噪音

标签 javascript html image-processing canvas html5-canvas

我有一个名为 generateNoise() 的函数,它创建一个 Canvas 元素并为其绘制随机 RGBA 值;其中,给出了噪音的外观。


我的问题

什么是无限地动画噪声以给出运动外观的最佳方法。让它有更多的生命?


JSFiddle

function generateNoise(opacity) {
    if(!!!document.createElement('canvas').getContext) {
        return false;
    }
    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d'),
        x,y,
        r,g,b,
        opacity = opacity || .2;

        canvas.width = 55;
        canvas.height = 55;

        for (x = 0; x < canvas.width; x++){
            for (y = 0; y < canvas.height; y++){
                r = Math.floor(Math.random() * 255);
                g = Math.floor(Math.random() * 255);
                b = Math.floor(Math.random() * 255);

                ctx.fillStyle = 'rgba(' + r + ',' + b + ',' + g + ',' + opacity + ')';
                ctx.fillRect(x,y,1,1);

            }
        }
        document.body.style.backgroundImage = "url(" + canvas.toDataURL("image/png") + ")";

}
generateNoise(.8);

最佳答案

1/2017 更新:我重写了整个答案,因为它开始变得相当困惑,并解决了评论中指出的一些问题。原答案可见here .新答案本质上具有相同的代码,但有所改进,并且通过一些新技术,人们利用了自该答案首次​​发布以来可用的新功能。


对于“真正的”随机外观,我们需要使用像素级渲染。我们可以使用 32 位无符号缓冲区而不是 8 位来优化这一点,我们还可以在更新的浏览器中关闭 alpha channel ,从而加快整个过程(对于旧浏览器,我们可以简单地为 Canvas 元素)。

我们在主循环外创建了一个可重用的 ImageData 对象,因此主要成本仅为 putImageData() 而不是在循环内。

var ctx = c.getContext("2d", {alpha: false});       // context without alpha channel.
var idata = ctx.createImageData(c.width, c.height); // create image data
var buffer32 = new Uint32Array(idata.data.buffer);  // get 32-bit view

(function loop() {
  noise(ctx);
  requestAnimationFrame(loop)
})()

function noise(ctx) {
  var len = buffer32.length - 1;
  while(len--) buffer32[len] = Math.random() < 0.5 ? 0 : -1>>0;
  ctx.putImageData(idata, 0, 0);
}
/* for browsers wo/2d alpha disable support */
#c {background:#000}
<canvas id=c width=640 height=320></canvas>

一个非常有效的方法,以一些内存为代价,但降低了 CPU 的成本,是用噪声一次预渲染一个更大的屏幕外 Canvas ,然后将那个 使用随机整数偏移将 Canvas 放入主 Canvas 中。

它需要一些额外的准备步骤,但循环可以完全在 GPU 上运行。

var w = c.width;
var h = c.height;
var ocanvas = document.createElement("canvas");     // create off-screen canvas
ocanvas.width = w<<1;                               // set offscreen canvas x2 size
ocanvas.height = h<<1;

var octx = ocanvas.getContext("2d", {alpha: false});
var idata = octx.createImageData(ocanvas.width, ocanvas.height);
var buffer32 = new Uint32Array(idata.data.buffer);  // get 32-bit view

// render noise once, to the offscreen-canvas
noise(octx);

// main loop draw the offscreen canvas to random offsets
var ctx = c.getContext("2d", {alpha: false});
(function loop() {
  var x = (w * Math.random())|0;                    // force integer values for position
  var y = (h * Math.random())|0;
  
  ctx.drawImage(ocanvas, -x, -y);                   // draw static noise (pun intended)
  requestAnimationFrame(loop)
})()

function noise(ctx) {
  var len = buffer32.length - 1;
  while(len--) buffer32[len] = Math.random() < 0.5 ? 0 : -1>>0;
  ctx.putImageData(idata, 0, 0);
}
/* for browsers wo/2d alpha disable support */
#c {background:#000}
<canvas id=c width=640 height=320></canvas>

请注意,尽管使用后一种技术,您可能会遇到“卡住”的风险,因为新的随机偏移量与前一种随机偏移量相似。要解决此问题,请为随机位置设置标准以禁止连续放置太近的位置。

关于javascript - 动画 Canvas 看起来像电视噪音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22003491/

相关文章:

javascript - jQuery 以编程方式取消选中并重新选择复选框

javascript - 在要调用的函数中定义 `this` 是什么

php - 试图将我的嵌入照片库(来自 tinymce 编辑器)对齐在我的模态 div 的中心

perl - 拖尾不断增长的视频文件的最后一帧

javascript - 可以使用 javascript 更改图像调色板吗?

javascript - Angular2变量 'Undefined'外部方法

javascript - iframe 无法与表单中的标签一起使用

javascript - Ionic 2 ionic 搜索栏图标

javascript - AngularJS 为事件单选按钮添加一个类到父类

python - 使用 python 创建 jpeg 的缩略图