重复HTML画布元素(框)以填充整个视口 [英] Repeat HTML canvas element (box) to fill whole viewport

查看:52
本文介绍了重复HTML画布元素(框)以填充整个视口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动画画布,可以在背景上创建噪点效果.我的代码的简短说明如下:使用 for 循环,我在画布周围随机绘制了1px X 1px的正方形(点).它会产生静态噪音(颗粒).稍后,我用 requestAnimationFrame 对其进行动画处理.

I have an animated canvas to create a noise effect on the background. Short explanation of my code is following: using for loop I am drawing 1px X 1px squares (dots) around canvas at random. It creates a static noise (grain). Later, I animate it with requestAnimationFrame.

我的问题是,如果将画布的原始大小设置为整个视口,则浏览器将无法处理巨大的绘图空间,并且动画会变得非常缓慢.因此,我需要将画布的原始尺寸保持较小,例如50px,并在整个视口上重复.

My problem is that if I set the original size of the canvas to whole viewport, the browser can not handle huge drawing space and animation becomes extremely sluggish. So I need to keep the original size of canvas small, like 50px and repeat it on whole viewport.

我知道我可以轻松使用 document.body.style.backgroundImage ,该代码本身会自动重复该元素,但它不适合我的业务逻辑.我需要这个canvas元素来放置页面上的其他任何元素并保持透明.仅仅设置不透明度也不太适合我.

I know I can easily use document.body.style.backgroundImage which on itself repeats the element automatically, but it does not fit my business logic. I need this canvas element to layover any other element on the page and be transparent. Just setting opacity does not fit me as well.

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.className = "canvases";
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);

function generateNoise() {
  window.requestAnimationFrame(generateNoise);
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  let x;
  let y;
  let rgb;

  for (x = 0; x < canvas.width; x++) {
    for (y = 0; y < canvas.height; y++) {
      rgb = Math.floor(Math.random() * 255);
      ctx.fillStyle = `rgba(${rgb}, ${rgb}, ${rgb}, 0.2`;
      ctx.fillRect(x, y, 1, 1);
    }
  }

  canvas.setAttribute("style", "position: absolute;");
  canvas.style.zIndex = 1;
  document.body.appendChild(canvas);
}

generateNoise();

.canvases {
  margin: 50px;
  border: 1px solid black;
}

推荐答案

在画布上产生噪点(通常在像素级别工作)的最佳方法是使用

The best to generate noise on a canvas (and to work at a pixel level in general) is to use an ImageData.
Painting every pixel one by one will be extremely slow (a lot of instructions to the GPU), while a simple loop over a TypedArray is quite fast.

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
let image; // using let because we may change it on resize

onresize = (evt) => {
  const width = canvas.width = window.innerWidth;
  const height = canvas.height =window.innerHeight;
  image = new ImageData(width, height);
};
onresize();
const anim = (t) => {
  const arr = new Uint32Array(image.data.buffer);
  for( let i = 0; i < arr.length; i++ ) {
    // random color with fixed 0.2 opacity
    arr[i] = (Math.random() * 0xFFFFFF) + 0x33000000;
  }
  ctx.putImageData(image, 0, 0);
  requestAnimationFrame(anim);
};
anim();

canvas { position: absolute; top: 0; left: 0 }

<canvas></canvas>

如果它仍然太慢,您也可以仅针对画布大小的一部分生成噪点并多次绘制:

If it's still too slow, you could also generate the noise only for a portion of the canvas size and draw it multiple times:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
let image; // using let because we may change it on resize

onresize = (evt) => {
  const width = canvas.width = window.innerWidth;
  const height = canvas.height =window.innerHeight;
  image = new ImageData(width / 2, height / 2);
};
onresize();
const anim = (t) => {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  const arr = new Uint32Array(image.data.buffer);
  for( let i = 0; i < arr.length; i++ ) {
    // random color with fixed 0.2 opacity
    arr[i] = (Math.random() * 0xFFFFFF) + 0x33000000;
  }
  const width = image.width;
  const height = image.height;
  ctx.putImageData(image, 0, 0);
  ctx.drawImage(canvas, 0, 0, width, height, width, 0, width, height);
  ctx.drawImage(canvas, 0, 0, width * 2, height, 0, height, width * 2, height);

  requestAnimationFrame(anim);
};
anim();

canvas { position: absolute; top: 0; left: 0 }

<canvas></canvas>

这篇关于重复HTML画布元素(框)以填充整个视口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆