gpt4 book ai didi

javascript - 重复 HTML Canvas 元素(框)以填充整个视口(viewport)

转载 作者:行者123 更新时间:2023-12-03 08:30:12 25 4
gpt4 key购买 nike

我有一个动画 Canvas 来在背景上创建噪音效果。我的代码的简短说明如下:使用 for 循环,我在 Canvas 周围随机绘制 1px X 1px 正方形(点)。它会产生静态噪音(颗粒)。后来,我使用 requestAnimationFrame 将其设置为动画。

我的问题是,如果我将 Canvas 的原始大小设置为整个视口(viewport),浏览器将无法处理巨大的绘图空间,并且动画变得极其缓慢。所以我需要保持 Canvas 的原始尺寸较小,例如 50px,并在整个视口(viewport)上重复它。

我知道我可以轻松使用 document.body.style.backgroundImage ,它本身会自动重复该元素,但它不符合我的业务逻辑。我需要这个 Canvas 元素来覆盖页面上的任何其他元素并且是透明的。仅仅设置不透明度也不适合我。

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;
}

最佳答案

在 Canvas 上生成噪声(并且通常在像素级别工作)的最佳方法是使用 ImageData .
逐个绘制每个像素将非常慢(向 GPU 发送大量指令),而 TypedArray 上的简单循环则相当快。

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>

如果仍然太慢,您还可以仅针对 Canvas 大小的一部分生成噪声并多次绘制:

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>

关于javascript - 重复 HTML Canvas 元素(框)以填充整个视口(viewport),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65340502/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com