Problemas com setInterval e argumentos indefinidos
-
27-09-2019 - |
Pergunta
Estou tentando criar uma luz estroboscópica básica no navegador usando o elemento canvas.Espero que setInterval continue chamando a função changeBG para mudar para uma cor de fundo aleatória.Esta função funciona bem sozinha, mas não quando chamada por setInterval.Tentei abrir esta página no firebug e me disse que as cores eram indefinidas.Aqui está o código problemático.
<html>
<head>
<title>Strobe!</title>
<link rel="stylesheet" type="text/css" href="reset.css" />
<script type="text/javascript">
function changeBG(colors,ctx,canvas) {
ctx.fillStyle = colors[Math.floor(Math.random()*colors.length)]
ctx.fillRect(0,0,canvas.width,canvas.height)
}
function eventLoop() {
var colors = ['#000000','#ff0000','#00ff00','#0000ff','#ffff00','#ff00ff','#00ffff']
var canvas = document.getElementById('mainCanvas')
var ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
//changeBG(colors,ctx,canvas)
setInterval("changeBG(colors,ctx,canvas)", 1000);
}
</script>
</head>
<body onload="eventLoop()">
<canvas id="mainCanvas" width="800" height="600">
</canvas>
</body>
Eu sou novo em javascript, então qualquer insight seria muito apreciado.
Solução
Seu código funcionaria se você não estivesse passando uma string para setInterval.Por estar em uma string, não é possível criar um fechamento nas variáveis que você está tentando usar.
Em vez disso, tente isto:
setInterval(function() {
changeBG(colors,ctx,canvas);
}, 1000);
Usando este método, você está passando uma função anônima para setInterval.Ele chamará essa função uma vez por intervalo, que neste exemplo é de 1.000 milissegundos.
A função pode usar as variáveis cores, ctx e canvas porque elas existem no escopo onde a função é declarada.Isso cria um fechamento para que essas variáveis ainda existam (no que diz respeito à nossa função anônima) quando ela for chamada repetidamente.
Por enquanto, você provavelmente pode apenas usar este código.Para maior compreensão, sugiro pesquisar funções e encerramentos anônimos.
Outras dicas
Você pode passar diretamente uma função, em vez de uma string para avaliar, como
setInterval(function(){changeBG(colors,ctx,canvas)}, 1000);
Boa sorte provocando epilepsia para alguém
A raiz do problema é o escopo da variável quando o código de intervalo é executado, as cores e as outras variáveis não estão no escopo.
Experimente isto:
<html>
<head>
<title>Strobe!</title>
<link rel="stylesheet" type="text/css" href="reset.css" />
<script type="text/javascript">
function eventLoop() {
var colors = ['#000000','#ff0000','#00ff00','#0000ff','#ffff00','#ff00ff','#00ffff']
var canvas = document.getElementById('mainCanvas')
var ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
setInterval(function() {
ctx.fillStyle = colors[Math.floor(Math.random()*colors.length)]
ctx.fillRect(0,0,canvas.width,canvas.height)
}, 1000);
}
</script>
</head>
<body onload="eventLoop()">
<canvas id="mainCanvas" width="800" height="600">
</canvas>
</body>
Experimente este atualizadosetInterval(function(){changeBG(colors,ctx,canvas)}, 1000);