gpt4 book ai didi

javascript - 为什么这个html5 canvas动画这么密集?

转载 作者:行者123 更新时间:2023-11-30 14:27:35 25 4
gpt4 key购买 nike

我使用 Canvas 创建这个动画并将 svg 转换为 Canvas 形状。大多数时候它运行它会加热我的电脑并且风扇开始运转。

只是想知道代码、html5 Canvas 、 Canvas 路径或动画递归是否如此密集?

在 codepen 上查看:https://codepen.io/benbyford-the-lessful/pen/ZjjVdR?editors=1010#

    // check program is being run

console.log('bg animation running...');


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

// redo this - canvas size
//
var width = window.innerWidth,
height = window.innerHeight;

canvas.width = width * 2;
canvas.height = height * 2;

var gridSquareWidth = 20;
var gridWidth = (width * 2) / gridSquareWidth,
gridHeight = (height * 2) / gridSquareWidth;



var grid = [];

// create default grid array
for (var x = 0; x < gridWidth; x++) {
grid[x] = [];

for (var y = 0; y < gridHeight; y++) {
var rand = getRandomArbitrary(0,5);
var rand2 = getRandomArbitrary(0,2);

if(rand2 == 1 || x < (gridWidth / 4) || x > (gridWidth / 2) || y < (gridHeight / 4) || y > (gridHeight / 2)){
rand--;
}

if(rand > 2) grid[x][y] = 1;
}
}


//
// main update function
//
var animationSpeed = 0.1;
var animationSpeedCount = 0;
var running = true;
function update(dt) {

if(running){
animationSpeedCount += dt;
if(animationSpeedCount > animationSpeed){

moveGrid();
animationSpeedCount = 0;
}

draw();
}
}

var noOfFrames = 3;
var waveOffset = 15;
var increment = 0;
function moveGrid() {

var x = increment;
var x2 = increment - noOfFrames - waveOffset;

// add frmae wave
for (var i = 0; i < noOfFrames; i++) {
moveONeFrameForward(x, true);
x--;
}
// go back frmae wave
for (var i = 0; i < noOfFrames; i++) {
moveONeFrameForward(x2, false);
x2--;
}

// var x column, add of subtract by 1
function moveONeFrameForward(x, add){

if(x < 0){
x = Math.ceil(gridWidth + x);
}

if(x > 0 && x < gridWidth){

for (var y = 0; y < gridHeight; y++) {
if(grid[x][y] > 0){
if(add){
grid[x][y] = grid[x][y] + 1;
}else{
if(grid[x][y] > 1) grid[x][y] = grid[x][y] - 1;
}
}
}
}
}

// increment column
increment += 1;
if(increment > gridWidth){
increment = 0;

// stop running
// running = false;
}
}

var fills = ["#eeeeee","#efefef","#fefefe","#ffffff"];

function draw() {
// clear canvas to white
ctx.fillStyle = '#dddddd';
ctx.fillRect(0, 0, canvas.width, canvas.height);

for (var x = 0; x < gridWidth; x++) {
for (var y = 0; y < gridHeight; y++) {

var offsetX = x * gridSquareWidth;
var offsetY = y * gridSquareWidth;
var frame = 0;

switch (grid[x][y]) {
case 1:
frame = 1
break;
case 2:
frame = 2;
break;
case 3:
frame = 3;
break;
case 4:
frame = 4;
break;
default:
}
if(frame) drawframe(ctx, frame, offsetX, offsetY, fills);
}
}
}


// The main game loop
var lastTime = 0;
function gameLoop() {
var now = Date.now();
var dt = (now - lastTime) / 1000.0;

update(dt);

lastTime = now;
window.requestAnimationFrame(gameLoop);
};

// start game
gameLoop();


//
// UTILITIES
//

// cross browser requestAnimationFrame - https://gist.github.com/mrdoob/838785
if ( !window.requestAnimationFrame ) {

window.requestAnimationFrame = ( function() {

return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(
/* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
window.setTimeout( callback, 1000 / 60 );
};

})();
}

function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}


var frame1Center = 4.1;
var frame2Center = 2.1;
function drawframe(ctx, frame, x, y, fills) {

ctx.strokeStyle = 'rgba(0,0,0,0)';
ctx.lineCap = 'butt';
ctx.lineJoin = 'miter';
ctx.miterLimit = 4;
ctx.fillStyle = fills[frame-1];

switch (frame) {
case 1:
ctx.beginPath();
ctx.moveTo(3.1+x+frame1Center,0+y);
ctx.lineTo(0.6+x+frame1Center,0+y);
ctx.bezierCurveTo(0.3+x+frame1Center,0+y,0+x+frame1Center,0.3+y,0+x+frame1Center,0.6+y);
ctx.lineTo(0.3+x+frame1Center,12.1+y);
ctx.bezierCurveTo(0.3+x+frame1Center,12.4+y,0.6+x+frame1Center,12.7+y,0.8999999999999999+x+frame1Center,12.7+y);
ctx.lineTo(3.4+x+frame1Center,12.7+y);
ctx.bezierCurveTo(3.6999999999999997+x+frame1Center,12.7+y,4+x+frame1Center,12.399999999999999+y,4+x+frame1Center,12.1+y);
ctx.lineTo(4+x+frame1Center,0.6+y);
ctx.bezierCurveTo(4.1+x+frame1Center,0.3+y,3.7+x+frame1Center,0+y,3.1+x+frame1Center,0+y);
ctx.closePath();
ctx.fill();
ctx.stroke();
break;
case 2 || 6:
ctx.beginPath();
ctx.moveTo(4.4+x+frame2Center,0+y);
ctx.bezierCurveTo(3.1+x+frame2Center,0+y,0+x+frame2Center,0.8+y,0+x+frame2Center,2.1+y);
ctx.bezierCurveTo(0+x+frame2Center,3.4000000000000004+y,0.3+x+frame2Center,12.5+y,1.6+x+frame2Center,12.799999999999999+y);
ctx.bezierCurveTo(2.8+x+frame2Center,13+y,6+x+frame2Center,12+y,6+x+frame2Center,10.7+y);
ctx.bezierCurveTo(6+x+frame2Center,9.1+y,5.7+x+frame2Center,0+y,4.4+x+frame2Center,0+y);
ctx.closePath();
ctx.fill();
ctx.stroke();
break;
case 3 || 5:
ctx.beginPath();
ctx.moveTo(5.2+x,0 +y);
ctx.bezierCurveTo(7.5 +x,0+y,9.3+x,6.5+y,9.3 +x,8.7+y);
ctx.bezierCurveTo(9.3+x,10.899999999999999+y,6.300000000000001+x,12.799999999999999+y,4.1000000000000005+x,12.799999999999999+y);
ctx.bezierCurveTo(1.9000000000000004+x,12.799999999999999+y,0+x,6.3+y,0+x,4.1+y);
ctx.bezierCurveTo(0+x,1.8999999999999995+y,3+x,0+y,5.2+x,0+y);
ctx.closePath();
ctx.fill();
ctx.stroke();
break;
case 4:
ctx.beginPath();
ctx.arc(5.9+x,6.3+y,5.8,0,6.283185307179586,true);
ctx.closePath();
ctx.fill();
ctx.stroke();
break;
default:
}
};

最佳答案

很难准确地说出“为什么”,但肯定有一些地方可以改进。

  • 首先,您绘制的尺寸是所需尺寸的两倍。
    将 Canvas 大小设置为渲染后的大小,您可能会看到性能上的巨大改进。

  • 然后,您在每次绘制时都绘制了很多子路径(并且多次设置了上下文的属性没有任何意义)
    您可以尝试将所有这些子路径合并为更大的子路径,按 fillStyle 分组,这样光栅化器每帧只工作四次。这也可以稍微提高性能。

但我个人会采用的方法是在 4 个不同的 Canvas 上预渲染所有 4 个不同的状态。然后,只使用 drawImage 绘制所需的 strip 。
在最好的情况下,您最终只调用了 4 次 drawImage,值得一提的是 8 次调用。

这是一个粗略的概念证明:

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

// don't set it twice as big as needed
var width = window.innerWidth,
height = window.innerHeight;

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

var gridSquareWidth = 10;
var gridWidth = (width) / gridSquareWidth,
gridHeight = (height) / gridSquareWidth;

var grid = [];

// create default grid array
for (var x = 0; x < gridWidth; x++) {
grid[x] = [];

for (var y = 0; y < gridHeight; y++) {
var rand = getRandomArbitrary(0, 5);
var rand2 = getRandomArbitrary(0, 2);

if (rand2 == 1 || x < (gridWidth / 4) || x > (gridWidth / 2) || y < (gridHeight / 4) || y > (gridHeight / 2)) {
rand--;
}

if (rand > 2) grid[x][y] = 1;
}
}

var fills = ["#eeeeee", "#efefef", "#fefefe", "#ffffff"];

var frame1Center = 4.1;
var frame2Center = 2.1;

// the 4 points drawers
var drawers = [draw0, draw1, draw2, draw3];
// initialise our four possible states
var states = [
initState(0),
initState(1),
initState(2),
initState(3)
];

//
// main update function
//
var running = true;
var speed = 2;

var waveWidth = 200;
var waveMargin = gridSquareWidth * 4;
var waveStart = 0;
var waveEnd = waveWidth;

// start game
update();

function initState(status) {
var c = canvas.cloneNode();
var ctx = c.getContext('2d');
ctx.scale(0.5, 0.5); // to circumvent values being set for scale(2)

ctx.beginPath(); // single path
ctx.fillStyle = fills[status];
for (var x = 0; x < gridWidth; x++) {
for (var y = 0; y < gridHeight; y++) {
if (grid[x][y]) {
drawers[status](ctx, x * gridSquareWidth * 2, y * gridSquareWidth * 2);
}
}
}
ctx.fill(); // single fill

return c;
}

function draw0(ctx, x, y) {
ctx.moveTo(3.1 + x + frame1Center, 0 + y);
ctx.lineTo(0.6 + x + frame1Center, 0 + y);
ctx.bezierCurveTo(0.3 + x + frame1Center, 0 + y, 0 + x + frame1Center, 0.3 + y, 0 + x + frame1Center, 0.6 + y);
ctx.lineTo(0.3 + x + frame1Center, 12.1 + y);
ctx.bezierCurveTo(0.3 + x + frame1Center, 12.4 + y, 0.6 + x + frame1Center, 12.7 + y, 0.8999999999999999 + x + frame1Center, 12.7 + y);
ctx.lineTo(3.4 + x + frame1Center, 12.7 + y);
ctx.bezierCurveTo(3.6999999999999997 + x + frame1Center, 12.7 + y, 4 + x + frame1Center, 12.399999999999999 + y, 4 + x + frame1Center, 12.1 + y);
ctx.lineTo(4 + x + frame1Center, 0.6 + y);
ctx.bezierCurveTo(4.1 + x + frame1Center, 0.3 + y, 3.7 + x + frame1Center, 0 + y, 3.1 + x + frame1Center, 0 + y);
ctx.closePath();
}

function draw1(ctx, x, y) {
ctx.moveTo(4.4 + x + frame2Center, 0 + y);
ctx.bezierCurveTo(3.1 + x + frame2Center, 0 + y, 0 + x + frame2Center, 0.8 + y, 0 + x + frame2Center, 2.1 + y);
ctx.bezierCurveTo(0 + x + frame2Center, 3.4000000000000004 + y, 0.3 + x + frame2Center, 12.5 + y, 1.6 + x + frame2Center, 12.799999999999999 + y);
ctx.bezierCurveTo(2.8 + x + frame2Center, 13 + y, 6 + x + frame2Center, 12 + y, 6 + x + frame2Center, 10.7 + y);
ctx.bezierCurveTo(6 + x + frame2Center, 9.1 + y, 5.7 + x + frame2Center, 0 + y, 4.4 + x + frame2Center, 0 + y);
ctx.closePath();
}

function draw2(ctx, x, y) {
ctx.moveTo(5.2 + x, 0 + y);
ctx.bezierCurveTo(7.5 + x, 0 + y, 9.3 + x, 6.5 + y, 9.3 + x, 8.7 + y);
ctx.bezierCurveTo(9.3 + x, 10.899999999999999 + y, 6.300000000000001 + x, 12.799999999999999 + y, 4.1000000000000005 + x, 12.799999999999999 + y);
ctx.bezierCurveTo(1.9000000000000004 + x, 12.799999999999999 + y, 0 + x, 6.3 + y, 0 + x, 4.1 + y);
ctx.bezierCurveTo(0 + x, 1.8999999999999995 + y, 3 + x, 0 + y, 5.2 + x, 0 + y);
ctx.closePath();
}

function draw3(ctx, x, y) {
ctx.moveTo(5.9 + x, 6.3 + y);
ctx.arc(5.9 + x, 6.3 + y, 5.8, 0, 2 * Math.PI);
}


function update(dt) {

if (running) {
draw();
moveGrid();
}
window.requestAnimationFrame(update);
}


function moveGrid() {
waveStart = (waveStart + speed) % canvas.width;
waveEnd = (waveStart + waveWidth) % canvas.width;
}

function draw() {
ctx.fillStyle = '#dddddd';
ctx.fillRect(0, 0, canvas.width, canvas.height);
var x = 0;
// the roll logic is a bit dirty... sorry.
if (waveEnd < waveStart) {
x = waveEnd - waveWidth;
drawStrip(1, x, waveMargin);

x = waveEnd - waveWidth + waveMargin;
drawStrip(3, x, (waveWidth - (waveMargin * 2)));

x = waveEnd - waveMargin;
drawStrip(2, x, waveMargin);
x = waveEnd;
}

drawStrip(0, x, waveStart - x);
drawStrip(1, waveStart, waveMargin);
drawStrip(3, waveStart + waveMargin, waveWidth - (waveMargin * 2));
drawStrip(2, waveStart + (waveWidth - waveMargin), waveMargin);
drawStrip(0, waveEnd, canvas.width - Math.max(waveEnd, waveStart));
}

function drawStrip(state, x, w) {
if(x < 0) w = w + x;
if (w <= 0) return;
x = Math.max(x, 0);
ctx.drawImage(states[state],
Math.max(x, 0), 0, w, canvas.height,
Math.max(x, 0), 0, w, canvas.height
);

}



function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
:root,body,canvas {margin: 0}
<canvas id="bgCanvas"></canvas>

关于javascript - 为什么这个html5 canvas动画这么密集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51704150/

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